我有以下选择:
SELECT DISTINCT pl
FROM [dbo].[VendorPriceList] h
WHERE PartNumber IN (SELECT DISTINCT PartNumber
FROM [dbo].InvoiceData
WHERE amount > 10
AND invoiceDate > DATEADD(yyyy, -1, CURRENT_TIMESTAMP)
UNION
SELECT DISTINCT PartNumber
FROM [dbo].VendorDeals)
这里的问题是表
[dbo].VendorDeals
没有列 PartNumber
,但是没有检测到错误,并且查询适用于联合的第一部分。
更重要的是,IntelliSense 还允许并识别
PartNumber
。仅当在复杂语句中时,此操作才会失败。
很明显,如果您限定列名称,错误就会很明显。
这不是 SQL Server/T-SQL 方言解析中的错误,不,这正在按预期完全工作。问题或错误出在“你的”T-SQL 中;特别是因为您还没有限定您的专栏。由于我没有您的表的定义,我将首先提供示例 DDL:
CREATE TABLE dbo.Table1 (MyColumn varchar(10), OtherColumn int);
CREATE TABLE dbo.Table2 (YourColumn varchar(10) OtherColumn int);
然后是一个与您的查询类似的示例:
SELECT MyColumn
FROM dbo.Table1
WHERE MyColumn IN (SELECT MyColumn FROM dbo.Table2);
首先,这将解析;这是一个有效的查询。其次,假设
dbo.Table2
包含
至少一行,则将返回表
dbo.Table1
中的 每一 行,其中 MyColumn
具有非 NULL
值。为什么?好吧,让我们用表名来限定列,因为 SQL Server 会解析它们:SELECT Table1.MyColumn
FROM dbo.Table1
WHERE Table1.MyColumn IN (SELECT Table1.MyColumn FROM dbo.Table2);
请注意,
IN
中的列也引用了Table1
,而不是
Table2
。默认情况下,如果子查询中省略了列的别名,则“假定”引用该子查询中定义的表。但是,如果子查询中的任何表都没有该名称的列,则将假定引用存在该列的表;在这种情况下Table1
。让我们举一个不同的例子,使用表中的另一列:
SELECT OtherColumn
FROM dbo.Table1
WHERE OtherColumn IN (SELECT OtherColumn FROM dbo.Table2);
这将被解析如下:
SELECT Table1.OtherColumn
FROM dbo.Table1
WHERE Table1.OtherColumn IN (SELECT Table2.OtherColumn FROM dbo.Table2);
这是因为OtherColumn
存在于
both表中。因为,在子查询中,
OtherColumn
不合格,所以
假设所需的列是在同一范围内定义的表中的列,
Table2
。
那么解决办法是什么呢?别名和限定您的列:SELECT T1.MyColumn
FROM dbo.Table1 T1
WHERE T1.MyColumn IN (SELECT T2.MyColumn FROM dbo.Table2 T2);
毫不奇怪,这会出错,因为 Table2
没有列 MyColumn
。
就我个人而言,我建议除非您在查询中仅引用了
一个表,否则您可以对所有
列进行别名和限定。这不仅确保不能引用错误的列(例如在子查询中),而且意味着其他读者确切地知道正在引用哪些列。它还可以阻止未来的失败。老实说,我已经记不清多年来有多少次由于“不明确的列”错误而导致进程失败,因为表的定义被更改,并且引用该表的查询没有被开发人员正确限定......