出于意外,我注意到以下查询实际上是有效的:
UPDATE bikes
SET price = NULL
FROM inserted
WHERE inserted.owner_id = 123456
这是触发器的一部分,有人忘记将原始表加入inserted
表。结果是,当执行触发器时,所有价格都设置为NULL
。
正确的SQL语句是这样的:
UPDATE bikes
SET price = NULL
FROM inserted
INNER JOIN bikes ON bikes.id=inserted.id
WHERE inserted.owner_id = 123456
第一个声明如何/为何有效?
答案 0 :(得分:1)
第一个语句没有按预期工作,因为它缺少带有自行车和插入表的整个INNER JOIN行。如果没有,SQL Server将更新所有行,因为当inserted.owner_id = 123456时,所有行都有资格获得更新。
您可以在TSQL中在触发器之外重现此内容,如:
更新自行车设置价格= null 来自SomeOtherTable 其中SomeOtherTable.SomeColumn =' some_value_that_exists'
这是SQL Server中语法上有效的语句。如果Intention是根据某些无法连接的表中某行的存在来更新自行车表,因为这两个表没有关联,那么这就是你要做的。但这不是你的要求。因此,为什么它更新所有记录而不仅仅是那些匹配bikes.id的记录。在编程术语中,这被称为逻辑错误。
内部联接使其更具限制性,并强制仅更新与2个表之间的连接条件匹配的行(bikes.id = inserted.id比较)
答案 1 :(得分:1)
为什么它不会有效? SQL Server并不知道您尝试做什么。它认为您想要更新另一个表上存在某些条件的所有字段。 请参阅下面的上一次更新。
<强> SETUP 强>
declare @table table
(
id int,
name varchar(10)
)
declare @itable table
(
id int,
name varchar(10)
)
insert into @table (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
insert into @itable (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
@table上的所有名称都将更改为zzz
update @table
set name = 'zzz'
from @itable i
where i.id = 1
select * from @itable
select * from @table
@table上id = 1的所有名称都变为yyy
update @table
set name = 'yyy'
from @itable i
inner join @table t on i.id = t.id
where i.id = 1
select * from @itable
select * from @table
这不会更新任何内容
update @table
set name = 'aaa'
from @itable i
where i.id = 133
select * from @itable
select * from @table
答案 2 :(得分:1)
简单来说,from子句是可选的..在查询下面考虑..
update table
set id=10
在update子句之后有一个表,sql只是更新它..
现在考虑以下查询..
update table1
set id=40
from table2..
您认为SQL的作用是什么,它会更新与第一次查询相同的所有行。
除非你引用from子句中的另一个表并加入如下
update t1
set t1.id=40
from
table1 t1
join
table2 t2
on t1.id=t2.id
下面的是更新语法中的from子句解释,它被剥离以仅显示相关部分..
如果要更新的对象与FROM子句中的对象相同,并且FROM子句中只有一个对象的引用,则可能指定也可能不指定对象别名。如果正在更新的对象在FROM子句中出现多次,则对该对象的一个且仅一个引用不得指定表别名。 FROM子句中对象的所有其他引用必须包含对象别名
只要上述规则有效(如您的情况),SQL将很乐意更新在update子句后立即找到的表