Access - 使用链接表更新本地表(但没有主键)
Posted
技术标签:
【中文标题】Access - 使用链接表更新本地表(但没有主键)【英文标题】:Access - Update local table with linked table (but without primary key) 【发布时间】:2019-06-19 10:13:23 【问题描述】:我有一个小的 ACCESS 工具,我想在其中读取链接表并更新本地表。导入新条目就像一种魅力,但是当我尝试更新现有条目时,它总是会引发异常(运行时错误 3073)。
这是我的代码
Sub UpdateBLPNR()
With CurrentDb
Set tdf = .CreateTableDef("ext_BEL_PLZ")
tdf.Connect = "ODBC;DSN=EasyProd PPS;DataDirectory=PATH;SERVER=NotTheServer;Compression= ;DefaultType=FoxPro;Rows=False;Language=OEM;AdvantageLocking=ON;Locking=Record;MemoBlockSize=64;MaxTableCloseCache=5;ServerTypes=6;TrimTrailingSpaces=False;EncryptionType=RC4;FIPS=False"
tdf.SourceTableName = "BEL_PLZ"
.TableDefs.Append tdf
.TableDefs.Refresh
End With
Dim SQLUpdate As String
Dim SQLInsert As String
SQLUpdate = "UPDATE BEL_PLZ " & _
"INNER JOIN ext_BEL_PLZ " & _
"ON(BEL_PLZ.NR = ext_BEL_PLZ.NR) " & _
"SET BEL_PLZ.BEZ = ext_BEL_PLZ.BEZ "
SQLInsert = "INSERT INTO BEL_PLZ (NR,BEZ) " & _
"SELECT NR,BEZ FROM ext_BEL_PLZ t " & _
"WHERE NOT EXISTS(SELECT 1 FROM BEL_PLZ s " & _
"WHERE t.NR = s.NR) "
DoCmd.SetWarnings False
DoCmd.RunSQL (SQLUpdate)
DoCmd.RunSQL (SQLInsert)
DoCmd.SetWarnings True
DoCmd.DeleteObject acTable, "ext_BEL_PLZ"
End Sub
已经发现 Access 在使用链接表更新本地表时可能会遇到一些问题,但我无法找到解决方法。
(SQLInsert 正在工作,SQLUpdate 正在杀死我)
这是我的最终解决方案(感谢 ComputerVersteher)-->
Sub UpdateBLPNR()
'Define Variables
Dim SQLUpdate As String
Dim SQLInsert As String
Dim qdf As DAO.QueryDef
'Create temporary table and update entries
With CurrentDb
Set tdf = .CreateTableDef("ext_BEL_PLZ")
tdf.Connect = "ODBC;DSN=EasyProd PPS;DataDirectory=PATH;SERVER=NotTheServer;Compression= ;DefaultType=FoxPro;Rows=False;Language=OEM;AdvantageLocking=ON;Locking=Record;MemoBlockSize=64;MaxTableCloseCache=5;ServerTypes=6;TrimTrailingSpaces=False;EncryptionType=RC4;FIPS=False"
tdf.SourceTableName = "BEL_PLZ"
.TableDefs.Append tdf
.TableDefs.Refresh
With .OpenRecordset("SELECT ext_BEL_PLZ.NR, ext_BEL_PLZ.BEZ " & _
"FROM ext_BEL_PLZ INNER JOIN BEL_PLZ ON BEL_PLZ.NR = ext_BEL_PLZ.NR", dbOpenSnapshot)
Set qdf = .Parent.CreateQueryDef("")
Do Until .EOF
qdf.sql = "PARAMETERS paraBEZ Text ( 255 ), paraNr Text ( 255 );" & _
"Update BEL_PLZ Set BEL_PLZ.BEZ = [paraBEZ] " & _
"Where BEL_PLZ.NR = [paraNr]"
qdf.Parameters("paraBez") = .Fields("BEZ").Value
qdf.Parameters("paraNr") = .Fields("NR").Value
qdf.Execute dbFailOnError
.MoveNext
Loop
End With
End With
'Run SQL Query (Insert)
SQLInsert = "INSERT INTO BEL_PLZ (NR,BEZ) " & _
"SELECT NR,BEZ FROM ext_BEL_PLZ t " & _
"WHERE NOT EXISTS(SELECT 1 FROM BEL_PLZ s " & _
"WHERE t.NR = s.NR) "
DoCmd.SetWarnings False
DoCmd.RunSQL (SQLInsert)
DoCmd.SetWarnings True
'Drop temporary table
DoCmd.DeleteObject acTable, "ext_BEL_PLZ"
End Sub
【问题讨论】:
正确,要么更新条目,要么插入新条目 然后删除加入更新!这导致只读。使用子选择。 或者导入表(不是链接),创建pk,更新。 如何将内连接换成子选择方式? (想继续使用链接表) 避免DoCmd
尤其是SetWarnings False
,无知不是幸福;),使用On Error Resume Next和Err对象来决定警告是否重要。
【参考方案1】:
从只读表创建记录集以获取值。
Dim qdf As DAO.QueryDef
With CurrentDb
With .OpenRecordset("SELECT ext_BEL_PLZ.NR, ext_BEL_PLZ.BEZ " & _
"FROM ext_BEL_PLZ INNER JOIN BEL_PLZ ON BEL_PLZ.NR = ext_BEL_PLZ.NR", dbOpenSnapshot)
Set qdf = .Parent.CreateQueryDef(vbNullString)
qdf.SQL = "PARAMETERS paraBEZ Text ( 255 ), paraNr Long;" & _
"Update BEL_PLZ Set BEL_PLZ.BEZ = [paraBEZ] " & _
"Where BEL_PLZ.NR = [paraNr]"
Do Until .EOF
qdf.Parameters("paraBez") = .Fields("BEZ").Value
qdf.Parameters("paraNr") = .Fields("NR").Value
qdf.Execute dbFailOnError
.MoveNext
Loop
End With
End With
【讨论】:
参数类型匹配表字段? BEL_PLZ.Bez 少于或等于 255 个字符? 是的,“Bez”总是少于 255 个字符,因为我们的刨削软件有一些限制【参考方案2】:你不能这样做。
Access 本身以外的其他数据源上的链接表需要一个主键来支持更新。
通过 GUI 进行链接时,Access 允许您指定一个备用键,如果没有主键,但如果有一个应该是您的主键,则该键唯一地标识行。
【讨论】:
据我所知,链接表中没有主键(它是一个非常古老的 dbf 数据库,但不幸的是我们无法在 2020 年之前切换到 SQL 数据库)。我的想法是使用 VBA 链接表,复制/更新本地表并取消链接表。我必须避免对链接表进行任何更改,因为它将被另一个部门访问和更改。 然后从制作表的完整副本开始,不要执行涉及链接表的更新。就这么简单。 正确,我有一个本地表,从链接表中导入 2 列,然后更新或创建本地表中的条目,并出于安全原因断开链接表 如果表只有这两列,另一种方法可能是:使用DELETE
查询删除已经出现的行,然后使用插入查询插入所有行。如果有其他列您希望不受影响,那当然不是一种选择。
顺便说一句,我打开了一个关于这个on Access UserVoice的问题。这是 Access 数据库引擎的常见限制性限制,并且经常会产生问题。以上是关于Access - 使用链接表更新本地表(但没有主键)的主要内容,如果未能解决你的问题,请参考以下文章
MS Access:来自 SQL Server 的只读链接表?
MS Access 2007 - 导入表后,记录集不再可更新