今天有個同事問我一個SQL問題,覺得有點意思,雖然能很快定位並解決問題,但是就是有種說不清道不明的感覺。因為不能解釋清楚(很多是建立在假設上),順便記錄一下,希望有清楚原理的人能解答一二。
原SQL語句不便於說明問題,我用一個簡單的例子來描述這個問題,請看下面SQL:
SELECT TYPE, COUNT(1) FROM sys.objects t GROUP BY sys.objects.type; 消息 4104,級別 16,狀態 1,第 2 行 無法綁定由多個部分組成的標識符 "sys.objects.type"。 如果是English版本,則會報如下錯誤: 消息 4104,級別 16,狀態 1,第 3 行 The multi-part identifier "sys.objects.type" could not be bound.
SQL腳本里面的查詢對象sys.objects 使用了別名t,但是如果在GROUP BY 字段名上使用了表名,則會報如上錯誤。我試着使用了下面幾種方式,結果都沒有問題。
SELECT TYPE, COUNT(1) FROM sys.objects GROUP BY TYPE; SELECT TYPE, COUNT(1) FROM sys.objects GROUP BY sys.objects.type; SELECT TYPE, COUNT(1) FROM sys.objects t GROUP BY t.type; SELECT TYPE, COUNT(1) FROM sys.objects t GROUP BY type;
我自己的解釋(假設)是:因為對所要查詢的表使用了別名,則SQL語句在解析的時候,例如上面報錯的SQL,則會將GROUP BY sys.objects.type 解析成GROUP BY t.sys.objects.type; 這樣就會導致編譯器無法識別這個對象t.sys.objects.type。因為根本沒有這樣一列。但是就像我開篇所說那樣,有種說不清道不明的感覺,感覺是這么回事,解釋也似乎合理,但是總感覺缺乏說服力,於是我又設計了下面一個小例子:
1 DROP TABLE TEST; 2 3 4 SELECT * INTO TEST FROM sys.objects; 5 6 7 SELECT t.name FROM TEST t , sys.objects s 8 9 WHERE t.object_id = s.object_id AND t.name ='Test' 10 11 12 13 SELECT t.name FROM TEST t , sys.objects s 14 15 WHERE t.object_id = s.object_id AND TEST.name ='Test' 16 17 消息 4104,級別 16,狀態 1,第 2 行 18 19 無法綁定由多個部分組成的標識符 "TEST.name"。
可以肯定的是,如果對表使用了別名,則在后面引用表中字段需要區別時,則必須使用別名,而不能用原表名,否則就會報無法綁定由多個部分組成的標識符錯誤。