[SQL]養成好習慣以避免寫出預期外的SQL Statements

  • 5569
  • 0

[SQL]養成好習慣以避免寫出預期外的SQL Statements

今天被雷到,記取教訓,在此記錄一下

一般來說在下SQL 時,若有二個以上的Table,通常我們都給與別名或是在Select時會給與指定Table Name

例如:

select TableA.id,TableB.amount
from TableA
inner join TableB on TableA.id = TableB.aid

 

然而若在子句Select裡,通常只有單一個Table情形下,可能會像下面這麼寫

select TableA.id,TableA.salary
from TableA
where id in (select xxx from TableB where sid=... and amount=..... )

 

在子句select 裡的條件 sid 及amount就沒有特別給與指定TableName,這個語法多數情況下也可能不會有問題,且sid及amount

直覺下指的是TableB的欄位

 

然而今天被雷到的SQL Statements也就是在一個子句select 裡的條件未指定TableName,而產生意外結果的經驗

Table結構如下

【empsalary】

image

【emppayexec】

image

 

原先的SQL Statements是

update emppayexec set payamount=0 
where empsalaryid in ( select id from empsalary where salary=0 and payid='82952AE8-1E5A-464E-9E33-F21E661CF7F8' )

這個SQL Statements本身其實有個錯誤存在,也就是where條件裡的select子句,empsalary這個Table本身並沒有payid這個欄位

所以原本預期這個語法應該會直接掛掉發生SQL Error才對,但結果卻不是如此,這個SQL Statements是順利執行了,

也真的Update了部份資料

這個結果令人有點錯愕,明明條件式中有錯誤,為何全句會順利執行了?

因此接著用執行計劃分析一下,看這整個SQL Statements是如何被順利執行的,執行計劃顯示如下

image

 

此時有了發現,在執行計劃中原本where條件裡的select子句中的payid這個欄位,被對應到外層原先要update的emppayexec

這個資料表了,也就是說原先的SQL Statements陰錯陽差的等同如下的SQL Statements

update emppayexec set payamount=0 
where empsalaryid in ( select id from empsalary where salary=0)
and payid='82952AE8-1E5A-464E-9E33-F21E661CF7F8'

因此若原先的SQL Statements是有給與指定Table名稱的,就會如同原先預期般的發生SQL Error,而不會陰錯陽差的Update

到其它資料

image

所以為了避免日後陰錯陽差的被雷到,還是養成好習慣『為你的欄位指定資料表』,即使SQL Statements會變的長一些,該謹慎一點

時還是該謹慎一些的好

 

若本文對您有所幫助,歡迎轉貼,但請在加註【轉貼】及來源出處,並在附上本篇的超連結,感恩您的配合囉。

By No.18