SQL Server 中的 T-SQL - 错误还是功能? [重复]

问题描述 投票:0回答:1

我有以下选择:

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
1个回答
5
投票

这不是 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

就我个人而言,我建议除非您在查询中仅引用了

一个
表,否则您可以对
所有

列进行别名和限定。这不仅确保不能引用错误的列(例如在子查询中),而且意味着其他读者确切地知道正在引用哪些列。它还可以阻止未来的失败。老实说,我已经记不清多年来有多少次由于“不明确的列”错误而导致进程失败,因为表的定义被更改,并且引用该表的查询没有被开发人员正确限定......

    

© www.soinside.com 2019 - 2024. All rights reserved.