0

Access 2003 の VBA 内で、

  1. TableA主キー ( AID) と現在の日付として新しいオートナンバーでレコードを作成します
  2. によって選択されたように、から複数の外部キー ( ) を使用して の新しいレコードTableCを関連付けるいくつかのレコードを作成します。AIDTableABIDTableBQueryB

したがって、 with s 2,5,7,8QueryBからレコードを返す場合、 withおよびwith でレコードを作成したいと思います。TableBBIDTableAAID = 1Date = 8/23/13

そして、次のようにTableC表示します。

AID   BID
---------    
  1    2
  1    5
  1    7
  1    8

どうすればいいですか?2 番目のフィールドが必要であることを思い出すまで、最初のことを達成することは問題ありませんでした。今私のコードは次のようになります。

Dim SQLstr As String
Dim db As DAO.Database
Set db = CurrentDb

SQLstr = "INSERT INTO TableA (FieldA, Date) "_
         & "VALUES (list13.value, Date());"

db.Execute SQLstr

List13、開いているフォームのコントロールです (名前を便利なものに変更できないか、フォームの残りの部分に表示されるレコードを制御できなくなります)。しかし、 と を追加するFieldAlist13.value、次のようなエラー メッセージが表示されます。

パラメータが少なすぎます。予想: 1

AID = 1また、新しいレコード (この場合は) を、すべてのQueryBレコードが関連付けられている定数として使用したいことをどのように説明すればよいかわかりません。いろいろ検索した結果、 を使いたいと思います@@IDENTITYが、方法がわかりません。

編集: 最終的に、AID を適切に返す次のコードを取得しました。

Dim rs As DAO.Recordset
Dim AIDvar As Integer

Set rs = db.OpenRecordset("select @@identity")
AIDvar = rs(0)

そして、私はここを閲覧していましたが、次のコードは、フィールド データと定数を組み合わせて INSERT INTO を使用するために提案されました。

strText = "foo"
strInsertSQL = _
"INSERT INTO tblA(fld1, fld2, fld3) " _
& "Select fldA, fldB, '" & strText & "' AS Expr1 " _
& "From tblB ;"

だから私が残っているのは次の質問です:

  • 最初のコードで "list13.value" を使用することの何が問題になっていますか? 編集:だから、私はそれを修正しました:

    strText = CStr(List13.Value)          
    SQLstr = "INSERT INTO InvoiceT (AcctID, InvDate) "_
    & "VALUES (" & strText & ", Date());"
    

しかし、@@IDENTITY コードですべてをまとめると、オーバーフロー エラーが発生します。どうすればそれを回避できますか?

  • 最後にコピーしたコード ブロックの「foo」の意味は何ですか?
  • 同じコード ブロック内の「AS Expr1」の意味は何ですか?
  • @@IDENTITY コード ブロックの strText を AIDvar に置き換えると機能しますか?
  • TableA が実際に開いていない場合に "OpenRecordset" が機能するのはなぜですか? これが私を混乱させるという私の考えはどこで間違っていますか?
4

1 に答える 1

0

あなたが望むものを達成するための最短の方法ではないかもしれませんが、コードをあまり考え直すことなく、(新しいフィールドを追加するなど) 行うことを簡単に変更できるため、おそらく最も柔軟です。

Public Sub DoWork()
    Dim db As DAO.Database
    Dim rsA As DAO.Recordset
    Dim newAID As Long

    Set db = CurrentDb()

    ' First, add the new record in TableA ang get its ID '
    Set rsA = db.OpenRecordset("TableA", dbOpenTable, dbFailOnError)
    If Not (rsA Is Nothing) Then
        With rsA
            .AddNew
                !FieldA = list13.Value
                !ActionDate = Now
            .Update
            ' Safe way to get the ID '
            .Move 0, .LastModified
            newAID = !ID
            .Close
        End With
        Set rsA = Nothing
    End If

    Dim rsB As DAO.Recordset
    Dim rsC As DAO.Recordset

    ' Second, open QueryB as a read-only recordset '
    Set rsB = db.OpenRecordset("QueryB", dbOpenSnapshot)
    If Not (rsB Is Nothing) Then
        ' Only proceed if QueryB returned some data '
        If rsB.RecordCount > 0 Then
            ' Open TableC so we can insert the result of QueryB '
            Set rsC = db.OpenRecordset("TableC", dbOpenTable, dbFailOnError)
            With rsC
                Do While Not rsB.EOF
                    .AddNew
                        !AID = newAID
                        !BID = rsB!ID
                        ' whatever other fields from QueryB '
                        ' that you need to insert in TableC '
                    .Update
                Loop
                .Close
            End With
            Set rsC = Nothing
        End If
        rsB.Close
        Set rsB = Nothing
    End If

    Set db = Nothing

End Sub

このコードはすべて単純な SQL ステートメントに簡単に置き換えることができますが、このようなことを純粋なレコードセットで安全に行う方法を示したかったのです。
手動の SQL コマンドを使用する短い代替手段は、次のようになります。

Public Sub DoWork()
    Dim sql As String
    Dim newAID As Variant

    ' First, add the new record in TableA ang get its ID '
    sql = sql & "INSERT INTO TableA (FieldA, ActionDate) "
    sql = sql & "VALUES (" & List13.Value & ", " & CDec(Now()) & ")"

    CurrentDb().Execute sql, dbFailOnError
    newAID = CurrentDb().Execute("SELECT @@IDENTITY")(0)

    ' Second, insert QueryB into TableC '
    sql = vbNullString
    sql = sql & "INSERT INTO TableC (AID, BID) "
    sql = sql & "SELECT " & newAID & ", QueryB.ID FROM QueryB"
    CurrentDb().Execute sql, dbFailOnError
End Sub

いくつかのコメント

  • このサイトを最大限に活用したい場合は、何を達成する必要があるかについて明確なビジョンを持っていることを確認してください. 気が変わって新しいフィールドを追加する必要があったという事実は、どこに行きたいのか本当にはっきりしていないように見えます. テーブルとフィールドの命名規則も、同じ質問内で一貫していません。
    最初にそれを解決します。現時点では、あなたは暗闇の中で突き刺しているように見えます.あなたの質問への答えを突き止めることを望んでいます.
    問題に対する明確なビジョンがなければ、誰もあなたを助けることはできません。

  • Dateフィールド名などの予約語は使用しないでください。これは間違いなく混乱を引き起こし、ある時点で常に出没し、奇妙なエラーを引き起こします。

  • 使い方を学ぶRecordsets。すべての問題を解決できるわけではありませんが、複雑なクエリや更新を挿入または実行する必要がある場合は必要です。

  • 手動で SQL 文字列を作成することは避けてください。可能な限り (クエリが本当に簡単でない限り)、パラメーター化されたクエリを使用します。ユーザーがテキストボックスに入力したデータを含むクエリを手動で作成しないでください。ある時点で、クエリを壊す文字 (引用符'"、改行、特殊文字、さらには悪質なデータベース コマンドなど) が含まれます。

  • SELECT @@IDENTITYは便利ですが、使用するときは注意が必要です。挿入の直後に実行する必要があり、必要なものが返されない場合があります。

于 2013-08-26T01:06:08.980 に答える