如何使用 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
我在数据表视图中设置了一个子表单,我正在尝试根据用户选择指定的参数使用来自 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 的参数化查询。
有关如何创建参数化查询,请参阅
您还可以查看使用 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