【问题标题】: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 中的所有内容都不会运行,除非表达式为真。

【问题讨论】:

    标签: sql sql-server tsql sql-server-2016


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢。这是有道理的。
    【解决方案2】:

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

    if(someBoolWhichIsFalse)
        intValue = "hello";
    

    它根本无效。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多