В состоянии внутри оператора CASE в SQL Server - PullRequest
0 голосов
/ 28 августа 2018

У меня запрос, который я переносил из Postgres (10.1) в Microsoft SQL Server (13.0)

Запрос работает в Postgres в:

SELECT * 
FROM source
WHERE
    1 = CASE 
           WHEN 234 NOT IN (SELECT user_id
                            FROM usergroup)
              THEN SOURCE .source_id IN (SELECT DISTINCT sl.source_id
                                         FROM sourcelevel SL)
              ELSE 1
        END

Сбой SQL Server с этим сообщением об ошибке:

Сообщение 156, Уровень 15, Состояние 1, Строка 11
Неверный синтаксис рядом с ключевым словом «IN».

Эта проблема, похоже, связана с использованием условия IN в CASE/WHEN/ELSE/END, потому что, если я удаляю эту конструкцию при выполнении запроса:

SELECT * 
FROM source
WHERE
    SOURCE .source_id IN (SELECT DISTINCT sl.source_id
                          FROM sourcelevel SL)

Выполняется без ошибок.

Есть ли хитрость в использовании синтаксиса IN внутри оператора CASE с SQL Server?

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Ошибка не в части NOT IN, а в этом:

THEN SOURCE .source_id IN (SELECT DISTINCT sl.source_id
                           FROM sourcelevel SL)

Я не знаю о PostgreSQL, но SQL Server определенно не поддерживает это условие:

WHERE 1 = SOURCE.source_id IN (SELECT..

Тщательно анализируя ваш запрос ..

SELECT * 
FROM source
WHERE 1 = (CASE WHEN 234 NOT IN(SELECT user_id FROM usergroup)
                   THEN SOURCE.source_id IN (SELECT DISTINCT sl.source_id FROM sourcelevel AS SL)
                   ELSE 1
           END)

Похоже, что запрос просто ограничивает результат запроса, если идентификатор пользователя не входит в группу пользователей.

Замена CASE на IF (потому что CASE не будет работать как внешняя часть запроса)

IF (SELECT user_id FROM usergroup WHERE user_id = 234) IS NULL  
BEGIN
    SELECT * 
    FROM source
    WHERE source.source_id IN (SELECT DISTINCT sl.source_id FROM sourcelevel AS SL)
END
ELSE BEGIN
    SELECT * FROM source
END
0 голосов
/ 28 августа 2018

Я почти уверен, что все сводится к следующему - с @u в качестве параметра идентификатора пользователя:

SELECT * FROM source
WHERE exists(select * from usergroup where user_id=@u)
or exists(select * from sourcelevel sl where sl.source_id=source.Sourceid)
0 голосов
/ 28 августа 2018

SQL Server не имеет тип данных Boolean. Вместо этого вы можете выполнить рефакторинг для вложенного выражения CASE, как показано ниже, возвращая 0 или 1:

SELECT * from source
WHERE
    1 =
         CASE WHEN 234 NOT IN(
            SELECT  
                user_id
            FROM
                usergroup  
            )
        THEN
            CASE WHEN SOURCE.source_id IN(
                SELECT DISTINCT
                    sl.source_id
                FROM
                sourcelevel SL

            ) THEN 1 
              ELSE 0
             END

        ELSE
            1
        END;

Я думаю, что это также может быть изменено без CASE, например:

SELECT *
FROM source
WHERE 234 IN(
    SELECT user_id
    FROM usergroup  
    )
    OR 
    SOURCE.source_id IN(
        SELECT sl.source_id
        FROM sourcelevel SL
    );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...