我有两张桌子:
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)
有没有办法在这样的查询中检查子查询是否正确?
谢谢!
答案 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)
这不应该发生,但我可以猜出一些可能发生的原因:
SupplierLocation
为空,因此查询优化器会编译一个根本不包含子查询的计划。
您只使用@id
中不存在的Supplier
值进行测试,因此查询优化器知道子查询将始终不返回任何记录,因此永远不会尝试提取不存在的列。
服务器以某种方式使用未提及不存在列的缓存计划(旧版本)。
事实上似乎更有可能发生错误,但是由于某些原因你没有看到错误。