【发布时间】:2019-08-11 19:54:15
【问题描述】:
这个简单的 VBA 语句不能按预期工作:
strSQl = "UPDATE Inventory SET NumberOfBlocks = BlocksReserved, LastUser = 'Me' WHERE InventoryID = 1234;"
CurrentDb.Execute strSQl, dbFailOnError + dbSeeChanges
LastUser 更新了,但 NumberOfBlocks 保持不变,没有错误。
如果我在 SSMS 中或作为 Access 查询运行此语句,它会起作用。
如果我在 VBA 语句中使用变量 ..."SET NumberOfBlocks = " & intBlocksReserved & ",...,它可以工作。
恒定工作:..."SET NumberOfBlocks = 555"...
这个也有效:NumberOfBlocks = (BlocksReserved * 1)
NumberOfBlocks 和 BlocksReserved 都是 smallint 且不为 null;记录有一个时间戳/行版本字段。
环境:Access 2016 和 SQL 2016 后端。
任何想法为什么我的初始陈述会默默地失败?谢谢!
更多测试证实了我之前的发现:
- 创建了一个新的 Access db,表 Inventory:ID (AutoNumber, PK), NumberOfBlocks (Integer), BlocksReserved (Integer), LastUser (Short Text 10)
-
在 SQL Server 中创建了一个表:
[ID] [int] IDENTITY(1,1) 非空, [NumberOfBlocks] [smallint] NULL, [BlocksReserved] [smallint] NULL, [LastUser] nvarchar NULL, [RV] [时间戳] NOT NULL
设置ID为主键,链接SQL表,两者都输入测试数据。
-
在两张表上运行完全相同的代码(仅更改了表名):
将 strSQl 变暗为字符串
strSQl = "UPDATE Inventory SET NumberOfBlocks = BlocksReserved, LastUser = 'Me';" CurrentDb.Execute strSQl,dbFailOnError + dbSeeChanges
结果:
本地访问表:NumberOfBlocks = BlocksReserved, LastUser = 'Me'
链接的 SQL 表:NumberOfBlocks 不变,LastUser = 'Me'
更多注释:
- 将 SQL Server 中的数据类型更改为 int(而不是 smallint)并没有什么不同。
-
但是,显式转换字段是有效的:
...SET NumberOfBlocks = CInt(BlocksReserved)...
-
就像
...SET NumberOfBlocks = (BlocksReserved * 1)...
我猜,这将我的帖子从一个问题变成了一个提醒......
【问题讨论】:
-
静默失败,因为 CurrentDb.Execute 是为这种行为而设计的。为什么要用同一张表中另一个字段的相同数据更新一个字段?
-
这条记录的字段比较多。我不得不拆分原始记录,即我首先插入了一个包含剩余可用库存数量的记录,这使得原始记录完全保留给该订单号,即它允许我们稍后更改或取消该订单。
-
为什么要保存“剩余可用库存数量”?评论allenbrowne.com/AppInventory.html
-
其背后的业务逻辑有点复杂,可能是我解释的不好——抱歉!但我的问题纯粹是技术问题:为什么“SET NumberOfBlocks = BlocksReserved”会失败,而“SET NumberOfBlocks = 50”或 SET NumberOfBlocks = (BlocksReserved * 1)” 有效。
-
由于其他人似乎忽略了您已经分享的细节(即,对我来说很明显您已经检查过数据类型等),我会冒险并责怪 Access。由于它没有将其作为传递执行,因此 Access 必须在发送到 SQL Server 之前分析和重建查询。抱歉,我不熟悉 SQL Server,但我知道您应该能够观察到从 Access 传递到服务器的查询。我怀疑 SQL Server 没有收到相同的查询。这并没有解释为什么会发生这种情况,而是将原因归结为 Access。
标签: sql-server ms-access vba sql-update sqldatatypes