Где пункт с ИЛИ И занимает много времени, чтобы бежать - PullRequest
0 голосов
/ 20 марта 2019

У меня есть базовый запрос вида:

DECALRE @TestVar int = 0;

SELECT * FROM TestTable     
WHERE
  TestTable.ColA = 1 AND
  (@TestVar = 0
     OR
  (@TestVar = 1 AND TestTable.TestColumn = 'Test')) 

Этот запрос занимает 30 секунд. Если я удаляю: (@TestVar = 1 AND TestTable.TestColumn = 'Test') из ГДЕ для запуска требуется 1 секунда.

Я думал, что SQL Server не будет оценивать (@TestVar = 1 AND TestTable.TestColumn = 'Test'), если первая часть предложения WHERE верна?

Что я могу сделать, чтобы условие TestTable.TestColumn = 'Test' не оценивалось, если оно не нужно?

1 Ответ

1 голос
/ 20 марта 2019

Параметр «Перекомпилировать» является хорошим вариантом здесь.

Если вы хотите чему-то научиться, вы можете попробовать Dynamic SQL (найдите его в Интернете :)).

    DECLARE @TestVar int = 0;
    DECLARE @TestTable TABLE (TestColumn VARCHAR(50), ColA INT);

    INSERT INTO @TestTable (TestColumn, ColA)
    VALUES ('Test', 1), ('NotTest', 1 ),('Unknown', 1),
           ('Test', 0), ('NotTest', 0 ),('Unknown', 0);

    /* Keeping this one for comparison, just uncomment to check */
    --SELECT * 
    --FROM @TestTable tt
    --WHERE
    --  tt.ColA = 1 AND
    --  (@TestVar = 0
    --     OR
    --  (@TestVar = 1 AND tt.TestColumn = 'Test'));


    DECLARE @sql NVARCHAR(4000);
    DECLARE @parameters NVARCHAR(4000);

    SET @sql = 
    N'DECLARE @TestTable TABLE (TestColumn VARCHAR(50), ColA INT);' +
    N'' +
    N'INSERT INTO @TestTable (TestColumn, ColA)' +
    N'VALUES (''Test'', 1), (''NotTest'', 1 ),(''Unknown'', 1),' +
    N'       (''Test'', 0), (''NotTest'', 0 ),(''Unknown'', 0);' +
    N'' +
    N'SELECT * FROM @TestTable tt WHERE tt.ColA = 1' 

    IF @TestVar = 0
        SET @sql = @sql; /* Do nothing, just adding it for show. @TestVar=0 will always be true */
    IF @TestVar = 1
        SET @sql = @sql + N' AND tt.TestColumn = ''Test'''; /* Only adding the TestColumn check. @TestVar=1 will always be true */
    IF @TestVar NOT IN (0, 1)
        SET @sql = @sql + N' AND 0=1';

    SET @parameters = N'@TestVar INT'

    /* Use this one for checking the statement */
    -- print @sql 

    /* Make sure to use parameterized dynamic sql or you will have security that looks like a Swiss cheese. 
Most tutorials will teach you about this*/
    EXEC sp_executesql @sql, @parameters, @TestVar = @TestVar;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...