我正在尝试使用对我无法控制的ODBC服务器的MS访问对传递查询进行更新。我不得不使用通行证的原因是,我要访问的记录具有255个以上的字段(如果可以的话,我会使用链接表)。
我一直在使用此资源来获取数据使用PassThrough(http://www.techonthenet.com/access/tutorials/passthrough/basics09.php)
查询简称: SELECT FullName, PointNumber FROM DNP3.CDNP3AnalogIn
ODBC Connect Str是:ODBC;DSN=SCX6_DB;LOCATION=Main;UID=admin;PWD=password;LOCALTIME=False;
现在,在访问数据库中,我有一个名称(fullname,pointnumber)的表(SCADA DB标签),我想使用更新通行证查询更新ODBC数据库内的字段,但我不确定这个怎么做。
我将上一个查询保存为dnp3_cdnp3analogin查询,并尝试进行新的查询:
UPDATE [DNP3_CDNP3AnalogIn Query] INNER JOIN [SCADA DB Tags] ON
[DNP3_CDNP3AnalogInQuery].FullName = [SCADA DB Tags].FullName
SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = [SCADA DB Tags].[PointNumber];
但是我从访问中获得错误:Operation must use an updateable query.
我知道可以做到这一点,但我似乎找不到一个例子(我可能不会谷歌搜索正确的短语)。Microsoft Page(http://technet.microsoft.com/en-us/library/bb188204(v = sql.90).aspx)说:There is, however, one important limitation: the results returned by SQL pass-through queries are always read-only. If you want to enable users to perform updates based on the data retrieved, you must write code to handle this.
不幸的是,它没有给出示例!
谁能给我解决方案,如果需要,我可以使用VBA吗?如果需要,我也可以提供更多背景。不幸的是,我不是访问专家,我只是想提出一个可以节省我一些时间的自动解决方案。
当他们说"如果您想允许用户[从传递查询中检索到的数据]执行更新,则必须编写代码来处理此问题:"他们可能是指这样的东西:
Option Compare Database
Option Explicit
Public Sub UpdateSqlServer()
Dim cdb As DAO.Database, rst As DAO.Recordset
Dim con As Object ' ADODB.Connection
Dim cmd As Object ' ADODB.Command
Const adParamInput = 1
Const adInteger = 3
Const adVarWChar = 202
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset( _
"SELECT " & _
"[SCADA DB Tags].FullName, " & _
"[SCADA DB Tags].PointNumber " & _
"FROM " & _
"[DNP3_CDNP3AnalogIn Query] " & _
"INNER JOIN " & _
"[SCADA DB Tags] " & _
"ON [DNP3_CDNP3AnalogIn Query].FullName = [SCADA DB Tags].FullName", _
dbOpenSnapshot)
Set con = CreateObject("ADODB.Connection")
con.Open "DSN=SCX6_DB;"
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = _
"UPDATE DNP3.CDNP3AnalogIn SET " & _
"PointNumber=? " & _
"WHERE FullName=?"
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput) ' PointNumber
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255) ' FullName
cmd.Prepared = True
Do Until rst.EOF
cmd.Parameters(0).Value = rst!PointNumber
cmd.Parameters(1).Value = rst!FullName
cmd.Execute
rst.MoveNext
Loop
Set cmd = Nothing
con.Close
Set con = Nothing
rst.Close
Set rst = Nothing
Set cdb = Nothing
End Sub
注意:
- 代码使用您现有的ODBC DNS。
- 它使用准备好的语句执行更新,提高效率并防止与SQL注入有关的失败。
- 源记录集在通过查询上执行内部加入,以确保代码仅尝试更新服务器上实际存在的服务器上的行。
您是说[DNP3_CDNP3Analogin查询]是基于服务器端的,而该表[SCADA DB标签]是局部基于的吗?在这种情况下,您不能使用通过查询。
,由于表格在不同的位置,尽管不能同时触摸这两个位置。
但是,您可以在循环中执行"单个"服务器端(通过)。如果您设置了通过查询并保存它,则此代码将起作用:
Dim qdfPass As DAO.QueryDef
Dim rstLocal As DAO.Recordset
Dim strSQL As String
Dim strSQL2 As String
Set qdfPass = CurrentDb.QueryDefs("MyPass")
strSQL = "UPDATE [DNP3_CDNP3AnalogIn Query] " & _
"SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = 'xxxx' " & _
"WHERE [DNP3_CDNP3AnalogInQuery].FullName = 'zzzz' "
Set rstLocal = CurrentDb.OpenRecordset("[SCADA DB Tags]")
Do While rstLocal.EOF = False
strSQL2 = Replace(strSQL, "xxxx", rstLocal!PointNumber)
strSQL2 = Replace(strSQL2, "zzzz", rstLocal!FullName)
qdfPass.SQL = strSQL2
qdfPass.Execute
rstLocal.MoveNext
Loop
rstLocal.Close