Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在from子句中具有不同表的SQL update语句_Sql_Sql Server - Fatal编程技术网

在from子句中具有不同表的SQL update语句

在from子句中具有不同表的SQL update语句,sql,sql-server,Sql,Sql Server,出于意外,我注意到以下查询实际上是有效的: UPDATE bikes SET price = NULL FROM inserted WHERE inserted.owner_id = 123456 这是触发器的一部分,其中有人忘记将原始表连接到插入的表。结果是,当执行触发器时,所有价格都设置为NULL 正确的SQL语句如下所示: UPDATE bikes SET price = NULL FROM inserted INNER JOIN bikes ON bikes.id=inser

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

UPDATE bikes
SET price = NULL
FROM inserted
WHERE inserted.owner_id = 123456
这是触发器的一部分,其中有人忘记将原始表连接到插入的
表。结果是,当执行触发器时,所有价格都设置为
NULL

正确的SQL语句如下所示:

UPDATE bikes
SET price = NULL
FROM inserted
     INNER JOIN bikes ON bikes.id=inserted.id
WHERE inserted.owner_id = 123456

第一条语句的有效性如何/为什么?

第一条语句没有按预期工作,因为它缺少与bikes和inserted表的整个内部联接行。如果没有该选项,SQL Server将更新所有行,因为当inserted.owner_id=123456时,所有行都有资格进行更新

您可以在TSQL中的触发器外部复制此内容,如:

更新设置价格=空 从别的桌子上 其中SomeOtherTable.SomeColumn='某个存在的值'

这是SQL Server中语法有效的语句。如果打算基于某个不相关的表中某一行的存在来更新bikes表,而该行由于这两个表不相关而无法联接,那么您可以这样做。但这不是你的要求。因此,为什么它会更新所有记录,而不是仅更新那些在编程术语中与bikes.id匹配的记录,这称为逻辑错误


内部联接使它更具限制性,并强制只更新那些与两个表之间的联接条件相匹配的行(bikes.id=inserted.id比较)

为什么它无效?SQL Server不知道您要做什么。它认为您希望更新另一个表中存在某些条件的所有字段请参阅下面的上次更新。

设置

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

简单地说,from子句是可选的。考虑下面的查询…

update table 
set id=10
update table1
set id=40
from table2..
在update子句之后有一个表,sql只是更新它

现在考虑下面的查询…

update table 
set id=10
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
下面是update语法中from子句的解释,仅对相关部分进行说明

如果要更新的对象与FROM子句中的对象相同,并且FROM子句中只有一个对该对象的引用,则可以指定或不指定对象别名。如果要更新的对象在FROM子句中出现多次,则对该对象的引用不能指定表别名,而且只能出现一次。FROM子句中对对象的所有其他引用必须包含对象别名


只要上述规则有效(就像您的情况一样),SQL就会很高兴地在update子句之后立即更新找到的表,其中仅是一个布尔表达式。您还可以使用
其中1=1
其中1=0
。它们都是有效的-没有关于必须有有效连接的规则。这有记录吗?这似乎很奇怪,因为当你看这句话时,它似乎是无效的。看起来有人试图更新一个甚至不属于查询一部分的表(因为from子句)。@JennyO'Reilly他们显然认为不值得为像您的同事这样的人可能会编写一些愚蠢的程序的每种情况引入警告/错误,例如查询其他表但从不使用它们。这样的时间最好花在提高人们做有用事情的能力上,而不是阻止他们自食其果。如果你把它应用到官方的T-SQL定义中,它是完全有效的。你说得对,这毫无意义。但是,WHERE是一个逻辑表达式,它会导致true/false,这取决于程序员如何正确使用该表达式。