如果我想用简单的连接编写查询,我可以这样做:
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标准(我猜这里 - 我不知道它是否符合要求)并鼓励良好的编码约定?
答案 0 :(得分: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*/
答案 1 :(得分: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
类型。哪一个用于过滤器? (这可能会对执行计划产生影响)。一个更好的例子是由 Martin Smith
因此,一般来说,通过使SQL更“宽容”,同时引入新的错误来源,你不会获得太多收益。但是,您可以对某些数据库(而不是SQL Server)执行此操作:
select * from customer c
join order o
using (customerid)
where customerid = 100
或者这个(如果customerid是唯一的常用列名)
select * from customer c
natural join order o
where customerid = 100
答案 2 :(得分:1)
您收到错误,因为订单和客户表中都存在customerid列,并且SQL不知道该条件应该应用于哪个列。
答案 3 :(得分:0)
在JOINing
两个表之后,结果表包含2个具有相同名称customerid
的列。因此,您需要通过将表名添加为前缀来告诉WHERE
子句使用哪个列。
答案 4 :(得分:0)
嗯......你知道结果集只包含完全相同customerid
的条目,但数据库服务器却没有,因为他没有理解"你在说什么。如果你有一个连接在结果集中没有两个customerid完全相同,你会很高兴,服务器区分它们。 ;)
答案 5 :(得分:0)
只有当我们需要对多于一个表中的字段执行某些操作时才出现不明确的列错误,因此在这种情况下,SQL无法识别它需要从哪个表提交操作。