2016-07-26 99 views
3

出意外,我注意到下面的查詢實際上是有效的:SQL update語句引用條款

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

在哪裏只是一個布爾表達式。你也可以使用'WHERE 1 = 1'或'WHERE 1 = 0'。他們都是有效的 - 有沒有規則必須有一個有效的加入 –

+0

這是記錄的地方?這看起來很奇怪,因爲從一個人看這個聲明看來,這似乎是無效的。它看起來像試圖更新一個甚至不是查詢的一部分的表(由於from子句)。 –

+0

@ JennyO'Reilly他們顯然並不認爲值得爲每一個像你的同事這樣的人可以編程一些愚蠢的事情引入警告/錯誤。查詢其他表,但從不使用它們。這樣的時間最好花在提高人們做有用的事情上的能力上,而不是阻止他們在腳下自殺。 –

回答

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 

所有的名字其中id = 1的@table成爲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 
1

第一條語句不能按預期工作,因爲它缺少與自行車和插入表的整個INNER JOIN行。如果沒有SQL Server將更新所有的行,所有行會資格的更新當inserted.owner_id = 123456

您可以重現此觸發的外TSQL,如:

更新自行車設定價格= NULL SomeOtherTable 其中SomeOtherTable.SomeColumn ='some_value_that_exists'

這是SQL Server中的語法上有效的語句。如果意圖是基於某個無關表中存在的行的存在來更新自行車表,因爲這兩個表沒有關聯,那麼這就是你如何做的。但那不是你的要求。因此,爲什麼它更新所有記錄,而不是隻更新所有記錄.id在編程方面,這被稱爲邏輯錯誤。

內加入使得它更嚴格,力僅更新那些符合2個表之間的連接條件(bikes.id = inserted.id比較)

1

深入淺出的from子句低於查詢optional..Consider ..

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子句解釋,僅向相關部分顯示。

如果對象bein g updated與FROM子句中的對象相同,並且只有一個對FROM子句中的對象的引用,可以指定或不指定對象別名。如果正在更新的對象在FROM子句中出現多次,則只有一次對該對象的引用不能指定表別名。在FROM子句中的對象的所有其他引用都必須包含對象別名

只要上面的規則是有效的(如你的情況),SQL會很樂意更新表更新條款後,立即發現