SQL оператор с пользовательским типом выдает ошибку - PullRequest
0 голосов
/ 29 апреля 2020

Я создал пользовательский тип с именем membertypes, который состоит из одного столбца типа int с именем membertype,

У меня есть хранимая процедура, например:

        declare @membertypes dbo.MemberTypes;
        INSERT INTO @membertypes VALUES (1);
        INSERT INTO @membertypes VALUES (3);

        declare @membertypecount int = (select count(1) from @membertypes)

        select username, MiniThumbNail, userID,
        from members
        where members.membertype in (case when @membertypecount > 0 then (select membertype from @membertypes) else members.membertype end)

Не работает, я получаю сообщение об ошибке:

Подзапрос вернул более 1 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

Однако, если я изменю код на этот это работает: -

        declare @membertypes dbo.MemberTypes;
        INSERT INTO @membertypes VALUES (1);
        INSERT INTO @membertypes VALUES (3);

        select username, MiniThumbNail, userID,
        from members
        where members.membertype in (select membertype from @membertypes)

Почему исходный код вызывает эту ошибку?

Ответы [ 3 ]

1 голос
/ 29 апреля 2020

Это ваша логика c:

   where members.membertype in (case when @membertypecount > 0 
                                     then (select membertype from @membertypes)
                                     else members.membertype 
                                 end)

Вы не понимаете, что такое выражения case. Выражение case - это выражение, которое возвращает одно скалярное значение. «Скалярное» значение имеет простой тип, такой как целое число или строка. (Некоторые базы данных расширяют это, чтобы включить кортежи и массивы, но SQL Сервер не является одним из них.) Другими примерами выражений являются арифметические c ('1 + 1'), функции (len('abc')) и даже простые столбцы.

Подзапросы не просты.

К счастью, то, что вы хотите сделать, легко без case:

where members.membertype in (select membertype from @membertypes) or
      not exists (select 1 from @membertypes)
0 голосов
/ 29 апреля 2020

Почему исходный код вызывает эту ошибку?

Это недопустимо:

case when @membertypecount > 0 then (select membertype from @membertypes) else members.membertype end
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

В CASE WHEN x THEN y y должно представлять один значение как 1, 'apple' et c. Недопустимо, чтобы CASE WHEN выбирал один из нескольких наборов данных для подачи в IN.

0 голосов
/ 29 апреля 2020

case выражение будет возвращать только одно значение с одной строкой, в то время как подзапрос может иметь несколько строк. Итак, выражение case не будет работать

Итак, вы можете использовать left join вместо:

select username, MiniThumbNail, userID 
from members mb left join
     @membertypes mt
     on mt.membertype = mb.membertype
where (@membertypecount = 0 or mt.membertype is not null);
...