来自子句

时间:2016-07-26 09:42:30

标签: sql sql-server

出于意外,我注意到以下查询实际上是有效的:

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

第一个声明如何/为何有效?

3 个答案:

答案 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子句后立即找到的表