create table tb1(id int identity(1,1),name varchar(10),remark varchar(50) default '');
create table tb2(xid int identity(1,1),name varchar(10));
insert into tb1(name)
select 'a'
union all select 'b'
union all select 'c'
insert into tb2(name) select 'x'
select * from tb1 where id in(select id from tb2)
select * from tb1 where id in(select xid from tb2)
drop table tb1
drop table tb2;
結果是:
id name remark
----------- ---------- --------------------------------------------------
1 a
2 b
3 c
id name remark
----------- ---------- --------------------------------------------------
1 a
從這段指令碼執行後,就可以發現問題:
為何select * from tb1 where id in(select id from tb2)在執行的時候不對條件中的子查詢語句做語法檢查呢?而且預設的等價於1=1呢?
而且,select * from tb1 where id in(select id from tb2 where id=1)會按照select * from tb1 where id in(select xid from tb2 where xid=1)來執行,這說明子查詢語句的文法沒有被檢查,但是過濾卻起到了作用,這的確是很奇怪的事情。
如果我在敲sql語句的時候誤把 select * from tb1 where id in(select xid from tb2)中的select xid敲成select id,那麼取出的資料就會有問題(全取出),但是卻得不到提示,因為語法檢查跳過了。所以,這個在寫sql語句的時候,就是一個潛在的泥坑。
據說在oracle中也存在類似的問題,沒有試。
大家在寫sql指令碼時,還是要謹慎啊,因為今天早上我的sql就出現了這樣的問題,謹記教訓啊。