powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / особенности конструкций ... in (select ...)
11 сообщений из 11, страница 1 из 1
особенности конструкций ... in (select ...)
    #32022869
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут с другом произошел такой теоритический спор.
Допустим есть такой скрипт

set ansi_nulls on
declare @t table(i int null)
insert @t select 1 union select null

if (2 in (select * from @t)) print 'in' else print 'out'
if not (2 in (select * from @t)) print 'in' else print 'out'

Последние две строки отличаются наличием not в условии и на первый взгляд в любом случае должны давать разный результат. Однако результат будет одинаков.

Вопрос в следующем: можно ли это считать ошибкой в SQL сервере?
С одной стороны если стоит set ansi_nulls on, то значение операции по сравнению с null-ом неопределено, но с другой стороны можно ли считать конструкцию in (select ...) сравнением? Явно это нигде не описано.
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022877
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> но с другой стороны можно ли считать конструкцию in (select ...) сравнением

Я думаю можно, если я ничего не путаю то конструкцией (2 in (select * from @t)) мы проверяем является ли множество "2" подмножеством @t, и как это можно проверить без сравнения?
Под рукой нет книжек, а исчисление предикатов 1-го порядка я уже изрядно подзабыл, думаю в данном случае и теорией это можно подтвердить.
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022878
Фотография Александр Степанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В данном случае это все равно что

if 2=1 or 2=null print 'in' else print 'out'
if NOT (2=1 or 2=null) print 'in' else print 'out'

--FALSE or NULL = FALSE
--NOT (FALSE or NULL)=NOT(NULL)=FALSE
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022885
MadDog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сравнение.
Запрос вида:
select * from table1 where id in (select id from table2)
можно переделать в:
select * from table1 join table2 on table2.Id = table1.Id
как раз сравнение.
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022886
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Согласен с Genady насчет "как проверить без сравнения". А план выполнения показывает что будет использоваться Table Scan
в 1-ом случае OBJECT: (@t) WHERE: (2=@t.(i))
во 2-ом OBJECT: (@t) WHERE: (@t.(i)=NULL OR 2=@t.(i))
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022903
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Glory
Какой план выполнения данных запросов совершенно не важно, просто оператор if работает с двузначной логикой, т.е. на выходе получим либо True либо false, в СУБД же однако введено еще одно значение ("Не знаю", точнее "неопределено"
)
поэтому возникает вопрос входит ли значение два в множество значений, среди которых есть хрен его знает какие. Самый простейший способ определить это взять и перебрать множество и сравнить значения, ну и естественно тут же возникает вопрос а каким будет результат сравнения 2 с "хрен его знает с чем"?
Если флаг set ansi_nulls включен, то один "хрен его знает что" не равно другому "хрен его знает что", а если выключен, то мы просто к домену возможных значений добавляем еще одно - "хрен его знает что" и тогда 2 <> Null, впрочем это всем понятно, вопрос SergSuper-а является выражение in сравнением? Я думаю да, почему описал выше.

p.s. Сорри за несколько вольную трактовку значения Null
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022956
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я бы не спешил оправдывать мелко-мягких в том, что - "все работает как предписано..."

Возьмем 4 цитаты из BOL по поводу упомянутых выше выражений:
\n1. IN (T-SQL) - Determines if a given value matches any value in a subquery or a list.
Result Type - Boolean
Result Value - TRUE or FALSE.

Определились - "IN (T-SQL)" это логическое выражение.
\n2. SET ANSI_NULLS (T-SQL) - Specifies SQL-92 compliant behavior of the Equals (=) and Not Equal to (<&gt comparison operators when used with null values.
Remarks: The SQL-92 standard requires that an equals (=) or not equal to (<&gt comparison against a null value evaluates to FALSE.

Определились еще раз - SET ANSI_NULLS - устанавливает соответствие стандарту SQL-92, и даже уточнили - что именно стандарт предусматривает.
\n3. Operator Precedence - When a complex expression has multiple operators, operator precedence determines the sequence in which the operations are performed.
NOT
AND
ALL, ANY, BETWEEN, IN, LIKE, OR, SOME

Оказыватся - логический оператор IN - аж на 2 уровня выше приоритетом, чем NOT.
Вот и к противоречию пришли - по стандарту SQL-92 - IN должен вернуть FALSE, а NOT - обязан его перевернуть в TRUE.
Почему же этого не происходит?
А вот почему:
\n4. When SET ANSI_NULLS is ON, all comparisons against a null value evaluate to UNKNOWN.

Оба-на!! Оказывается у логических операторов, кроме TRUE и FALSE, появилось еще одно значение - UNKNOWN...
(цитаты насчет того, что ветки выполнения в выражениях типа IF в этом случае идут как по FALSE я не нашел, но по контексту - можно догадаться).

Выходит - мелко-мягкие уже давно реализовали "троичную логику", а мы об этом даже и не догадывались...
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022964
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, вот такая конструкция работает одинаково правильно - вне зависимости от установок SET ANSI_NULLS:

if exists (select * from @t where i=2) print 'in' else print 'out'
if not exists (select * from @t where i=2) print 'in' else print 'out'
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022984
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 qu-qu
>Выходит - мелко-мягкие уже давно реализовали "троичную логику", а мы об этом даже и не догадывались...

Похоже об этом не догадывались только вы это достаточно известная проблема, я не работал с другими СУБД, но есть у меня стойкое подозрение что там ситуация такая же
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022987
MadDog
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такое дело.

create table...
...
b bit NULL
...
...
Рейтинг: 0 / 0
особенности конструкций ... in (select ...)
    #32022989
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / особенности конструкций ... in (select ...)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]