我有两个表:
-
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列)
总之:没有——至少没有简单的方法。
如果代码运行时没有抛出错误(但您恰好知道输出不正确),则应用程序逻辑中存在错误。
如果代码运行时没有抛出错误,并且你不知道它是否工作正确,那么就没有魔法棒可以让你挥动来验证它。
这就是测试的作用:检查运行的代码是否正常工作。
代码审查也可以帮助实现这个目标。
这不应该发生,但我可以猜测一些可能发生的原因:
-
SupplierLocation
为空,因此查询优化器将编译一个根本不包含子查询的计划。 -
你只测试
@id
值,不存在于Supplier
,所以查询优化器知道子查询将始终返回不记录,因此永远不会得到远到试图提取一个不存在的列。 -
服务器正在使用缓存计划(旧版本),该计划没有提及不存在的列
看起来更有可能的是错误实际上正在发生,但由于某些原因您没有看到它