[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】
【emppayexec】
原先的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是如何被順利執行的,執行計劃顯示如下
此時有了發現,在執行計劃中原本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
到其它資料
所以為了避免日後陰錯陽差的被雷到,還是養成好習慣『為你的欄位指定資料表』,即使SQL Statements會變的長一些,該謹慎一點
時還是該謹慎一些的好
By No.18