metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2011-03-12 12:00 pm

Век живи, век учись

Внезапно: жизнь заставила узнать как правильно сравнивать поля в базах данных на равенство/неравенство:
A IS NOT DISTINCT FROM B
A IS DISTINCT FROM B

[identity profile] gsbelarus.livejournal.com 2011-03-12 10:32 am (UTC)(link)
о да, начать читать руководства пользователя никогда не поздно :)

[identity profile] madeveloper.livejournal.com 2011-03-12 11:33 am (UTC)(link)
А зачем понадобилось (NULL == NULL) ?

[identity profile] metaclass.livejournal.com 2011-03-12 11:34 am (UTC)(link)
Условие в триггере "запретить менять значение поля".
if (old.A is distinct from new.A) then exception ECannotChangeField;

[identity profile] avnik.livejournal.com 2011-03-12 11:46 am (UTC)(link)
А разве if (old.A == new.A) (ну или != не достаточно?)
Я триггеров не писал лет 8, (и вообще "чистого" SQL не видел года 3-4 уже -- коньструктора от SQLAlchemy хватало за глаза)

[identity profile] metaclass.livejournal.com 2011-03-12 11:48 am (UTC)(link)
Нет, не достаточно.
A=null(или null=B,null<>A,null<>B) возвращают null, которые интерпретируется как false, поэтому условие не выполняется.

[identity profile] avnik.livejournal.com 2011-03-12 11:56 am (UTC)(link)
А оно вне триггеров употребляется? Или это что-то firebird specific? Не поленился посмотреть внутрь SQLAlchemy -- DISTINCT только в запросах употребляется, и в рефлекшне от dialects.firebird

[identity profile] metaclass.livejournal.com 2011-03-12 12:02 pm (UTC)(link)
Обычный оператор сравнения. Судя по всему, существует в Postgresql, DB2 и Firebird.

[identity profile] metaclass.livejournal.com 2011-03-12 12:03 pm (UTC)(link)
И вообще это ANSI SQL стандарт судя по всему.

[identity profile] avnik.livejournal.com 2011-03-12 12:12 pm (UTC)(link)
SA триггеры не генерит, а в запросах делает (видимо) только DISTINCT в селектах на колонки. Там кодогенератор из собственного DSL в SQL с кешированием и прочим адом. Я погрепал DISTINCT и посмотрел вокруг (аккуратно -- чтобы мозг не расплавился)

[identity profile] metaclass.livejournal.com 2011-03-12 12:13 pm (UTC)(link)
Тут слово DISTINCT совершенно в разных контекстах применяется, в плане множеств(в запросах) и в плане значений (у меня).

[identity profile] avnik.livejournal.com 2011-03-12 12:16 pm (UTC)(link)
Ну потому у меня и случился разрыв шаблона, и я полез задавать вопросы и копаться в потрохах SA

[identity profile] gds.livejournal.com 2011-03-12 01:44 pm (UTC)(link)
кроме описанного у ребе (для триггеров), иногда это полезно для легковесной эмуляции типа опциональных значений, который в нормальных языках записывался бы, например, как "type option 'a = [ None | Some of 'a ]", в тех случаях, когда невозможно выделить какое-либо специальное значение для значения None, либо когда специальное значение будет неудобно в других смыслах (это же сраный sql, всё-таки).

[identity profile] ennor.livejournal.com 2011-03-12 11:34 am (UTC)(link)
Что-то синтаксис экзотический какой-то. Ансишные INTERSECT / EXCEPT не реализованы, поди.

[identity profile] metaclass.livejournal.com 2011-03-12 11:36 am (UTC)(link)
А причем здесь операции над множествами записей? Я же пишу про значения полей.

[identity profile] dair-spb.livejournal.com 2011-03-12 11:55 am (UTC)(link)
Ой. А кто здесь поле, а кто таблица?
И какую роль играет здесь DISTINCT?

[identity profile] metaclass.livejournal.com 2011-03-12 12:01 pm (UTC)(link)
И то и другое поля, очевидно.

[identity profile] gsbelarus.livejournal.com 2011-03-12 12:17 pm (UTC)(link)
это не тот DISTINCT, что вы подумали.

[identity profile] gds.livejournal.com 2011-03-12 12:15 pm (UTC)(link)
я со старых mysql, interbase, oracle начинал, там такого не встречал сходу, поэтому... ((a is null and b is null) or a=b) (почему не другие варианты -- оптимизатор такое больше любит обычно). Но вообще -- буду знать на будущее, интересно.

ага

[identity profile] az-from-belarus.livejournal.com 2011-03-12 01:57 pm (UTC)(link)
Порой подобные нюансики дает ОЧЕНЬ существенное увеличение скорости обработки - в разы.

[identity profile] sbj-ss.livejournal.com 2011-03-12 04:47 pm (UTC)(link)
MSSQL2008: Сообщение 156, уровень 15, состояние 1, строка 1
Неправильный синтаксис около ключевого слова "distinct".

Поэтому приходится выкручиваться некрасивыми конструкциями вида
isnull(A, значение_которого_в_БД_быть_не_может) = isnull(B, значение_которого_в_БД_быть_не_может)
(deleted comment)

[identity profile] sbj-ss.livejournal.com 2011-03-13 01:03 am (UTC)(link)
Да, для триггера это верно.

[identity profile] zamotivator.livejournal.com 2011-03-13 03:48 pm (UTC)(link)
/me сразу вспомнил про правила вида: "в hash join null != null, в merge join null < null, в expect/intersect/union null == null".
И это не противоречит определению: "два NULL не являются равным, но также они не являются неравными " :)
Edited 2011-03-13 15:49 (UTC)