2011-10-21 60 views
4

如果我想編寫一個查詢用一個簡單的加盟,我可以這樣做:不明確的列名 - 是不是?

select * from customer c 
join order o 
on c.customerid = o.customerid 
where c.customerid = 100 

,這一切工作正常。在這個查詢中,是否有一個原因,我必須指定一個表別名 - 即。 c.customerid?爲什麼我不能寫這個:

select * from customer c 
join order o 
on c.customerid = o.customerid 
where customerid = 100 

我得到錯誤Ambiguous column name 'customerid'。在這種情況下,如果WHERE子句中只有一列,並且它是我要加入的列,那麼這實際上是「模棱兩可」?還是隻是遵守ANSI標準(我在這裏猜測 - 我不知道它是否符合)並鼓勵良好的編碼規範?

回答

6

針對您的特殊例子,我想不出在何種情況下會有所作爲的任何情況。但是,對於字符串列上的INNER JOIN,它可以執行下列操作。

DECLARE @customer TABLE 
(customerid CHAR(3) COLLATE Latin1_General_CI_AS) 

INSERT INTO @customer VALUES('FOO'); 

DECLARE @order TABLE 
(customerid CHAR(3) COLLATE Latin1_General_CS_AS) 

INSERT INTO @order VALUES('FOO'); 


SELECT * 
FROM @customer c 
JOIN @order o 
ON c.customerid = o.customerid COLLATE Latin1_General_CS_AS 
WHERE c.customerid = 'Foo' /*Returns 1 row*/ 

SELECT * 
FROM @customer c 
JOIN @order o 
ON c.customerid = o.customerid COLLATE Latin1_General_CS_AS 
WHERE o.customerid = 'Foo' /*Returns 0 rows*/ 
+0

不錯,這是比我想到的更好的例子。 –

+0

@馬丁史密斯 - 感謝a)回答這個問題和b)提供一個有趣的例子 –

1

因爲CustomerID列中的順序和客戶表存在,SQL不知道哪一列的條件,應適用於你所得到的錯誤。

0

JOINing兩個表,將所得表包含具有customerid同名2列。所以你需要通過添加表名作爲前綴來告訴WHERE子句使用哪個列。

5

省略表的別名確實會讓一個不明確的列引用。只是讓你join一個left join,你會立即明白爲什麼:

select * from customer c 
left join order o 
on c.customerid = o.customerid 
where customerid = 100 -- here, the semantics are quite different 

另一個原因:一列可能是INTEGER類型,其他類型SMALLINT的。哪一個用於過濾器? (這可能會影響執行計劃)。一個更好的例子是由馬丁史密斯

因此,一般來說,你會得到很多,通過使SQL更「寬容」,同時引入新的錯誤來源。你可以做一些數據庫(不SQL Server)的事,但是是這樣的:

select * from customer c 
join order o 
using (customerid) 
where customerid = 100 

還是這個(如果客戶ID是唯一的公共列名)

select * from customer c 
natural join order o 
where customerid = 100 
+0

+1雖然SQL Server不支持「使用」或「自然連接」,但我不確定數據類型是如何影響事物的?無論如何,'INNER JOIN'只會返回符合'smallint'範圍的值。 –

+0

@MartinSmith:你說得對,謝謝。數據類型可能會影響執行計劃。 –

0

嗯......你知道,結果集只包含與customerid完全相同的條目,但是數據庫服務器不會,因爲他不「理解」您指定的內容。如果你有一個在結果集中沒有完全相同customerid的連接,你會很高興,服務器區分它們。 ;)

0

不明確的列錯誤只有當我們需要做哪些有一個以上的表,所以在這種情況下,SQL無法識別從表遞交它需要經營領域的一些操作來。