1

我有两张桌子:

  • SupplierLocation带柱子Id | SupplierId | ThirdPartyId

  • Supplier带柱子Id | Company

我们正在使用 SQL Server 2008。我正在尝试纠正一些写得不好的查询。例如,即使子查询中的列名不正确(供应商表没有 ThirdPartyId),以下查询也不会引发错误:

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

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

谢谢!

4

4 回答 4

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

于 2013-06-14T19:19:43.437 回答
1

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

一种方法是限定列名。

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)

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

于 2013-06-14T19:25:44.857 回答
0

一句话:不——至少,没有简单的方法。

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

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

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

代码审查也有助于实现这一目标。

于 2013-06-14T19:19:16.013 回答
-1

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

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

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

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

似乎更有可能实际上发生了错误,但由于某种原因您没有看到它。

于 2013-06-14T19:09:09.217 回答