为什么一个if语句下的查询是false运行?

Why is a query under a IF statement that is false running?

我有一个应用程序对 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

在用户select使用产品之前它看起来像这样

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

这是给我的错误:

Column name or number of supplied values does not match table definition.

我知道为什么会出现此错误,我正在 select 使用的 table 不是针对该数据类型制作的。

但是,为什么当我有 IF (0=1) 时它甚至试图 运行 第一个 IF 子句 - 为什么这部分不只是被跳过而 SELECT 0 只是 运行?我原以为它应该是这样工作的,但我不断收到有关列 name/number 与 table 定义不匹配的错误。当用户使用 select 一个产品,而我得到 IF (1=1) 并且我有合适的 table/function/datatype,一切都会顺利进行。我只是不知道为什么它会在 IF(1=0) 之前抛出一个错误。为什么这个 happen/how 我可以得到我的预期行为,即我的第一个 IF 语句下 BEGIN\END 中的所有内容都不会 运行 除非表达式为真。

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

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

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

中编译以下内容
if(someBoolWhichIsFalse)
    intValue = "hello";

根本无效。

运行时代码还没有执行,还在解析和词法分析阶段。没有任何内容被跳过,它只需要是完全有效的代码,而不考虑运行时条件。

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