如何使用 ADO 中的参数化查询或存储过程为 MSACCESS 子表单数据表创建可更新的记录源?

How can I create an updateable recordsource for an MSACCESS subform datasheet with a parameterised query or stored procedure in ADO?

我在数据表视图中设置了一个子表单,我正在尝试根据用户选择指定的参数使用来自 SQL 服务器的数据进行更新。

我通常使用存储过程来实现这一点,并让 VBA 通过 ADO 调用它们,但此数据的不同之处在于 RecordSource 需要能够 amended/edited 直接在数据中 table.

我有一个数据 table,我目前用来显示数据,它使用以下代码:

Dim db As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sp As ADODB.Command

Set db = New ADODB.Connection
Set rs = New ADODB.Recordset
Set sp = New ADODB.Command
Set ps = frmName
    db.Open dbString
    db.CursorLocation = adUseClient

    With sp
        .ActiveConnection = db
        .CommandText = "x04_ch_sl_ptsTable"
        .CommandType = adCmdStoredProc
        .Parameters.Append sp.CreateParameter("@tmName", adVarChar, adParamInput, 4, tmName)
    End With

    sp.Parameters.Append sp.CreateParameter("@wkEnd", adDBTimeStamp, adParamInput, , wkEnd)
        Set rs = sp.Execute
        Set ps.subFormDataViewer.Form.Recordset = rs
        Exit Sub
    End If
db.Close

能否对此进行修改以使数据集可更新?

到目前为止,这是我能够实现我想要做的事情的唯一方法,但由于明显的安全和注入问题,我不想走这条路:

ps.subFormDataViewer.Form.RecordSource = " SELECT p.ps_dateClaim as [Date], p.ps_id as [ID], p.ps_empid as [Employee ID], e.hc_fullName as [Employee], p.ps_pts as [Claimed] " & _
                                            " FROM (([ODBC;DRIVER=SQL Server;SERVER=<REDACTED>;Integrated_Security=SSPI;DATABASE=<REDACTED>].prod_pts as p " & _
                                            " INNER JOIN [ODBC;DRIVER=SQL Server;SERVER=<REDACTED>;Integrated_Security=SSPI;DATABASE=<REDACTED>].hc_employee as e " & _
                                                " ON p.ps_empid = e.hc_empid) " & _
                                            " WHERE (p.ps_dateClaim = #" & wkEnd & "#" & _
                                                " AND (e.hc_teamName = '" & tmName & "'); "

我尝试了以下 ADO 方法但没有成功:

    With sp
        Set .ActiveConnection = db
        .CommandText = " SELECT t.Date, t.TeamName, t.Reference, t.Status, t.Reason, t.Checked " & _
                        " FROM testTbl as t" & _
                        " WHERE t.TeamName = @tmName "
            .Parameters.Append .CreateParameter(, adVarChar, adParamInput, 4, tm)
        Set rs = .Execute
    End With
    With sp
        Set .ActiveConnection = db
        .CommandText = " SELECT t.Date, t.TeamName, t.Reference, t.Status, t.Reason, t.Checked " & _
                        " FROM testTbl as t" & _
                        " WHERE t.TeamName = ? "
        Set rs = .Execute(, Array(tm))
    End With

(第二个示例确实生成了数据,但记录集不可更新,因为它将每个字段识别为 "expression")

我已经能够用 DAO 实现这个:

Dim db as DAO.Database
Dim rs as DAO.Recordset
Dim qd as DAO.QueryDef
Dim dbSQL as string

dbSQL = " SELECT t.Date, t.TeamName, t.Reference, t.Status, t.Reason, t.Checked " & _
                        " FROM testTbl as t" & _
                        " WHERE t.TeamName = tmName1 "
Set qd = db.CreateQueryDef("", dbSQL)

With qd
    .Parameters!tmName1 = tm
End With

Set rs = qd.OpenRecordset
Set ps.subFormDataViewer.Form.Recordset = rs

您的字段 ps_dateClaim 似乎不是时间戳,而是 DateTime 字段,因此尝试使用:

sp.Parameters.Append sp.CreateParameter("@wkEnd", adDate, adParamInput, , wkEnd)

你不能。从存储过程返回的记录集不可更新。

当然,如果你希望它是可更新的,你可以使用使用 DAO 的参数化查询。

有关如何创建参数化查询,请参阅 使用 DAO 部分。请注意,我强烈警告不要这样做,上次我使用 Access 在处理参数化查询 filters/sorts 时有一些错误。

您还可以查看使用 ADO 部分了解如何通过直通查询执行此操作。

请注意,混淆您的 SQL 服务器地址是徒劳的(可以使用互联网流量分析工具轻松发现),并且由于您似乎没有使用加密连接,因此您当前对其他参数的混淆很容易解决也。这可能足以阻止没有 SQL 服务器安全经验的好奇用户,但这绝不是真正的安全。

对于可更新的 ADO 记录集:

With sp
    Set .ActiveConnection = db
    .CommandText = " SELECT t.Date, t.TeamName, t.Reference, t.Status, t.Reason, t.Checked " & _
                    " FROM testTbl as t" & _
                    " WHERE t.TeamName = ?"
        .Parameters.Append .CreateParameter(, adVarChar, adParamInput, 4, tm)
    Dim rs AS ADODB.Recordset
    Set rs = New ADODB.Recordset
    rs.CursorLocation = adUseClient
    rs.Open sp, , adOpenDynamic, adLockOptimistic
End Wit