如何验证子查询是否正确?

时间:2013-06-14 19:01:23

标签: sql-server-2008 tsql subquery syntax-error in-clause

我有两张桌子:

  • SupplierLocationId | SupplierId | ThirdPartyId

  • SupplierId | Company

我们正在使用SQL Server 2008.我正在尝试纠正一些写得不好的查询。例如,以下查询运行时不会抛出错误,即使子查询中的列名不正确(Supplier表没有ThirdPartyId):

SELECT * 
FROM SupplierLocation 
WHERE SupplierId IN (SELECT ThirdPartyId 
                     FROM Supplier 
                     WHERE Id = @id)

有没有办法在这样的查询中检查子查询是否正确?

谢谢!

4 个答案:

答案 0 :(得分:1)

使用别名并限定列名称。

SELECT * 
FROM SupplierLocation as SL
WHERE SL.SupplierId IN (SELECT S.ThirdPartyId 
                     FROM Supplier as S
                     WHERE S.Id = @id)

在子查询中包含来自各种来源的数据是完全合法的:

SELECT *, ( select Id + ThirdParty + @Id from Supplier where Id = @Id ) as GuessWhat
FROM SupplierLocation as SL
WHERE SL.SupplierId IN (SELECT S.ThirdPartyId 
                     FROM Supplier as S
                     WHERE S.Id = @id)

如果您没有明确说明这些来源,那么您可能会惊讶地发现SQL Server可以解决的问题。只要您使用JOIN来限定所有列名称,这是一种好习惯。

SSMS中的Parse工具将检测一些但不是全部错误。这是一个方便的起点。

答案 1 :(得分:1)

虽然不是这个问题的通用解决方案,但可以重写提供的示例,以便查询编译器捕获类似的错误。

一种方法是对列名进行限定。

SELECT * 
FROM SupplierLocation 
WHERE SupplierId IN (SELECT Supplier.ThirdPartyId 
    FROM Supplier 
    WHERE Id = @id)

另一个是使用存在而不是

中的位置
SELECT * 
FROM SupplierLocation 
WHERE EXISTS (SELECT *
    FROM Supplier 
    WHERE ID = SupplierID
    AND ID = @ID)

(当然在本例中甚至不需要子查询。可以直接针对@ID变量检查SupplierID列)

答案 2 :(得分:0)

总之:不 - 至少,没有简单的方式。

如果代码运行时没有抛出错误(但你碰巧知道输出不正确),那么应用程序逻辑就会出错。

如果代码在没有抛出错误的情况下运行,并且你知道它是否正常工作,那么就没有魔法棒可以挥动来验证它。

这是测试的目的:检查运行的代码是否正常工作。

代码审查也可以帮助实现这一目标。

答案 3 :(得分:-1)

这不应该发生,但我可以猜出一些可能发生的原因:

  1. SupplierLocation为空,因此查询优化器会编译一个根本不包含子查询的计划。

  2. 您只使用@id中不存在的Supplier值进行测试,因此查询优化器知道子查询将始终不返回任何记录,因此永远不会尝试提取不存在的列。

  3. 服务器以某种方式使用未提及不存在列的缓存计划(旧版本)。

  4. 事实上似乎更有可能发生错误,但是由于某些原因你没有看到错误。