如何验证子查询是否正确



我有两个表:

  • SupplierLocation,列Id | SupplierId | ThirdPartyId

  • Supplier带列Id | Company

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

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

是否有一种方法来检查,在这样的查询子查询是正确的?

谢谢!

使用别名并限定列名

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工具将检测一些错误,但不是全部错误。这是一个方便的起点。

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

一种方法是限定列名。

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

另一个是使用where exists而不是where in

SELECT * 
FROM SupplierLocation 
WHERE EXISTS (SELECT *
    FROM Supplier 
    WHERE ID = SupplierID
    AND ID = @ID)

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

总之:没有——至少没有简单的方法。

如果代码运行时没有抛出错误(但您恰好知道输出不正确),则应用程序逻辑中存在错误。

如果代码运行时没有抛出错误,并且你不知道它是否工作正确,那么就没有魔法棒可以让你挥动来验证它。

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

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

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

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

  2. 你只测试@id值,不存在于Supplier,所以查询优化器知道子查询将始终返回不记录,因此永远不会得到远到试图提取一个不存在的列。

  3. 服务器正在使用缓存计划(旧版本),该计划没有提及不存在的列

看起来更有可能的是错误实际上正在发生,但由于某些原因您没有看到它

相关内容

  • 没有找到相关文章

最新更新