0

在 VBA 中,在 Access 2003 中,我需要

  1. TableA使用新的自动编号作为主键 ( AID) 和当前日期创建记录
  2. 创建多个记录,TableC其中AID从新记录TableA与多个外键 ( BID)关联,TableB由 选择QueryB

因此,如果从with s 2、5、7、8QueryB返回记录,那么我想在with和TableBBIDTableAAID = 1Date = 8/23/13

然后TableC这样出现:

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

我该怎么做呢?完成第一件事很顺利,直到我想起我需要第二个领域。现在我的代码如下:

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打开表单中的控件在哪里(我无法将名称更改为有用的名称,否则它将不再控制显示在表单其余部分上的记录)。但是一旦我添加了FieldAand list13.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)

我正在浏览here,建议使用以下代码将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 代码块中用 AIDvar 替换 strText 会起作用吗?
  • 如果 TableA 实际上没有打开,为什么“OpenRecordset”会起作用?我的想法哪里出错了,这让我感到困惑?
4

1 回答 1

0

Maybe not the shortest way to achieve what you want, but it's probably the most flexible since you can easily modify what you do (like add new fields) without having to rethink your code too much:

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

You could easily replace all this code with straight SQL statements but I wanted to show how you would do something like this safely with pure recordsets.
The shorter alternative using manual SQL commands would be something like:

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

Some comments

  • If you want to get the best out of this site, make sure you have a clear vision of what you need to achieve. The fact that you changed your mind and needed to add new fields makes it look like you really have no clear idea of where you want to go. Your naming convention for tables and fields is also inconsistent within the same question.
    Settle that first. At the moment it looks like you are stabbing in the dark, hoping to pin the answer to your question.
    No-one can help you if you don't have a clear vision of your problem.

  • Do not use reserved words like Date for field names. This is bound to cause confusion and it will always come back to haunt you at one point or another, causing strange errors.

  • Learn to use Recordsets. They are not the answer to all problems, but they are necessary if you need to insert or perform complex queries and updates.

  • Avoid constructing SQL strings by hand. As much as possible (unless the query is really trivial), use parameterised queries. Never construct a query by hand that includes data that the user typed in a textbox: at one point or another it will contain characters that will break your query (like quotes '", line returns, special characters or even evil database commands).

  • SELECT @@IDENTITY is useful but you must be careful when using it: it must be run directly after the insert and there are some cases where it doesn't return what you want.

于 2013-08-26T01:06:08.980 回答