SQL更新的行为更新表不在条件中

时间:2012-12-03 23:35:00

标签: sql sql-server sql-update

运行以下查询时

UPDATE Invoices
SET PaymentTotal = 1
FROM Vendors
WHERE Vendors.VendorID = 34 -- true for some row

SQL Server更新发票中的所有记录。但是,当条件与Vendors表中的任何行不匹配时:

UPDATE Invoices
SET PaymentTotal = 1
FROM Vendors
WHERE Vendors.VendorID = -34 -- false for all rows

没有行更新。为什么?

编辑:这是一个完整的学术问题,我知道这不是编写查询的理想方式。

2 个答案:

答案 0 :(得分:1)

您的原始查询:

UPDATE Invoices
SET PaymentTotal = 1
FROM Vendors
WHERE Vendors.VendorID = 34

相当于:

update i set paymenttotal = 1
from vendors v
cross join invoices i
where v.vendorid = 34

交叉联接返回两个集合的乘积,当vendors减少为具有条件v.vendorid = -34的空集时,结果集为空,因为任何乘以零的都是零。

答案 1 :(得分:0)

这是因为对于发票中的每个值,WHERE子句在第一种情况下被评估为true(存在 a 供应商,其ID为34),因此每个记录都会更新当ID = -34时反之亦然 - 没有记录被更新,因为VendorID = -34总是假的。

例如,假设我们设置了发票I {... does not matter ... }和供应商V.VendorIDs {1 .. 35}

set PaymentTotal = 1 when VendorID=34 exists  
-- 34 exists so this is executed

set PaymentTotal = 1 when VendorID=-34 exists
-- -34 does not exists so this is never executed

这些是在不相关的集合之间设置操作,因此不会预期结果(不经过这种类型的分析)。

如果您要将它们联系起来(如下面的查询),则此逻辑会发生变化,您会得到“预期”结果。


我相信你想要这样的东西:

UPDATE Invoices
SET PaymentTotal = 1
FROM Vendors
WHERE Vendors.VendorID = 34 and Invoices.VendorID = Vendors.VendorID

...而且我假设您实际上并不知道VendorID,而是另一个Vendor字段,这样该查询才有意义(因为如果您已经知道ID,则查询另一个表是没有用的。)