为啥错误运行的 IF 语句下的查询?

Posted

技术标签:

【中文标题】为啥错误运行的 IF 语句下的查询?【英文标题】:Why is a query under a IF statement that is false running?为什么错误运行的 IF 语句下的查询? 【发布时间】:2021-12-03 03:02:50 【问题描述】:

我有一个使用大量字符串插值进行 SQL 查询的应用程序。我知道这是一个 SQL 注入威胁,这是客户和我们都知道的事情,希望我们可以专注于下一次重大重构。我这样说是为了理解来自 GUI 的 Root Container.property 东西。

我有这个问题

IF (Root Container.UserSelectedProduct=1)
    begin
        DECLARE @TestNumbers Root Container.SQLProductType;
        INSERT INTO @TestNumbers SELECT * FROM Root Container.DBTable;
        SELECT *
        FROM Root Container.SQLProductFunction (@TestNumbers)
        WHERE [ID] = Root Container.Level;
    end
else
    Select 0

在用户选择产品之前,它看起来像这样

IF (0=1)     
  BEGIN
    DECLARE @TestNumbers myDataType;
    INSERT INTO @TestNumbers SELECT * FROM [MySchema].[TheWrongTable];     
    SELECT * FROM [dbo].[myfunction] (@TestNumbers)
    WHERE [ID] = 1;
  END
ELSE
  SELECT 0

这给了我错误:

列名或提供的值的数量与表定义不匹配。

我知道为什么会出现此错误,我从中选择的表不是为该数据类型创建的。

但是,当我有IF (0=1) 时,为什么它甚至试图运行第一个 IF 子句 - 为什么这部分不只是跳过,而 SELECT 0 只运行?我原以为这就是它应该如何工作的,但是我不断收到有关列名/编号与表定义不匹配的错误。当用户确实选择了一个产品并且我得到了IF (1=1) 并且我有适当的表/函数/数据类型时,这一切都很顺利。我只是不知道为什么在 IF(1=0) 之前它会抛出一个错误。为什么会发生这种情况/我如何才能获得我的预期行为,即我的第一个 IF 语句下的 BEGIN\END 中的所有内容都不会运行,除非表达式为真。

【问题讨论】:

【参考方案1】:

不解释 T-SQL。无论运行时条件如何,它都必须有意义。事实上,它甚至不做短路。您的代码是无效的,并且它无法访问并不重要 - T-SQL 不会仅仅因为它可以被消除而忽略一段无效代码,这是一个常见的错误来源(例如在 C++ 中)这在模板中很常见)。

只要确保在没有选择产品的情况下您仍然可以获得有效的 SQL;如果必须,请使用错误的表(或辅助表)。

【讨论】:

谢谢。这是有道理的。【参考方案2】:

答案很简单: SQL 代码在执行之前 被服务器完全编译,所以这基本上是一个编译错误。这有点像尝试在 C# 中编译以下内容

if(someBoolWhichIsFalse)
    intValue = "hello";

它根本无效。

运行时代码甚至还没有被执行,它还处于解析和词法分析阶段。没有任何内容被跳过,它只需要是完全有效的代码,与运行时条件无关。

这发生在每个范围内,即在每次调用过程或临时批处理时,该代码必须是可编译的。

【讨论】:

以上是关于为啥错误运行的 IF 语句下的查询?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript IF 语句错误地评估 TRUE - 为啥?

为啥我从多个“if”语句中收到“无效赋值左侧”错误?

Access VBA - If/Else 语句不断给我一个错误,但我不知道为啥[重复]

为啥使用“if-else”语句会在看似相同的三元运算符构造不会产生 TypeScript 编译器错误?

sql的语句提示有语法错误,求大神 create database if not exists `fwzl`;

java 为啥使用continue会使程序错误