|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Простейший демо-триггер, обеспечивающий уникальность с учётом NULL: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Однако по какой-то причине оператор <=> неверно отрабатывает в триггере. DEMO fiddle Триггер позволяет вставить дублирующуюся запись, хотя даже предварительно выполненная проверка показывает, что запись этим запросом должна найтись, и во вставке должно быть отказано. Что я упускаю? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2022, 13:20 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
какая то фича MySQL при работе с TIMESTAMP в MariaDB поле типа TIMESTAMP не может быть без DEFAULT как то так. поле делается как Код: sql 1.
и все работает DEMO MariaDB ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2022, 17:00 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
MariaDB при создании таблицы делает это поле Код: sql 1. 2. 3. 4.
в MariaDB поле типа TIMESTAMP не может быть без DEFAULT `ts` TIMESTAMP NULL тоже работает ! и в MySQL 5.6 и в 5.7 ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2022, 17:12 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
В MySQL 5.5 - 5.7 работает и без NULL. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2022, 22:20 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
OlegROA, перейди по ссылке в посте Akina и посмотри что там вставляется. И сделай еще один инсерт ручками ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2022, 13:02 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Akina, в 8.0 @@SESSION.sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES, NO_ZERO_IN_DATE,NO_ZERO_DATE ,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION в 5.6 5.7 MariaDB @@SESSION.sql_mode STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2022, 13:09 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2022, 15:53 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Akina, ну глюк такой явно в 8.0 при явной проверке значений отрабатывает как надо а в таблице хранится не NULL, нам просто показывает NULL MariaDB (добавлено show create table test; ) `ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() ) если переключить на 8.0 - видим в show create table - `ts` timestamp NULL DEFAULT NULL, хотя мы не указывали NULL БАГ 8.0 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2022, 13:04 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
сделать влоб, работает везде и всегда Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
sql_mode в 8.0 надо менять иначе будет чехарда и в CREATE TABLE явно указать что может быть NULL Код: sql 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2022, 14:30 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
интересно, как может оператор <=> работать, но иногда не работать в триггере условия работают test.ts <=> NULL NEW.ts <=> NULL а test.ts <=> NEW.ts нет на багтрекере ничего похожего нет ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2022, 16:12 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Alex_Ustinov в таблице хранится не NULL, нам просто показывает NULL Этой фразы не понял от слова "совсем". Структура хранения такова, что NULL-поле имеет дополнительный байт признака NULL. Если он установлен, то поле имеет значение NULL, и то, что хранится в содержательной части значения, игнорируется. Если он не установлен, значение берётся из содержательной части. MariaDB тут вообще не рассматривается. Она многое обрабатывает по-другому. Например, MySQL, если поле определить как NOT NULL, в принципе не рассматривает набор значений как валидный - он перед/между/после любого этапа обработки выполняет контроль значений на ограничения, т.е. "поле не может быть NULL" будет выдано ещё до выполнения триггера. Тогда как MariaDB выполняет подобный контроль только при помещении значения в хранилище. Что до SQL Mode, то NO_ZERO_IN_DATE,NO_ZERO_DATE ограничивают на нули и никак не реагируют на NULL. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 08:11 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Akina, Этой фразы не понял от слова "совсем".никто не понял как продукт Оракла "здесь читает, а здесь не читает" я лишь накидываю мысли. В вопросе - "Что я упускаю" ни капли мысли. MariaDB при том, что это флагман, там правят баги а не добавляют их. Именно в MariaDB находится Видениус (Monty), основной разработчик MySQL. Я явно указал глюки MySQL в отличие от MariaDB. Спрашивать "что я упускаю?", а затем включать лектора не надо. Вы эта... давайте не путайте тёплое с мягким. Ваш путь в исходники или на BUGs.mysql.com ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 11:52 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
тут же покажу еще прикол MySQL MySQL 8.0 - в триггер Добавлена инициализация переменных @tts @nts -- SET @tts:=test.ts; -- SET @nts:=new.ts; если эти строки раскомментировать - то все заработает. ПРЕДПОЛОЖУ (не надо писать что непонятно от слова СОВСЕМ) значение NEW. в 8.0 не определено до первого использования или определено как фиг знает что (CURRENT_TIMESTAMP судя по MariaDB или 5.6 5.7) до первого использования. Хотя при создании табл с полем ts TIMESTAMP (мы не говорим что там возможен NULL) в show cteate table `ts` timestamp NULL DEFAULT NULL Поэтому я и ПРЕДПОЛОЖИЛ, что ТАМ не NULL Чтобы это "понять" - необходимо перещелкнуть версию ДБ на 5.7 и посмотреть что там на самом деле в show create table (выше) Долой лекции, в MySQL нужны эксперименты Благо в fiddle это удобно. И еще раз - чтобы найти БАГоГЛЮК в MariaDB - надо просто посмотреть как это работает в MariaDB. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 12:21 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
** И еще раз - чтобы найти БАГоГЛЮК в MariaDB MySQL - надо просто посмотреть как это работает в MariaDB. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 12:43 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
автор-- SET @tts:=test.ts; -- SET @nts:=new.ts; если эти строки раскомментировать - то все заработает. ёмоё, так ошибка в триггере, SET @tts:=ts; ошибка OLD нельзя в BEFORE та это замкнутый круг аля MySQL Но все равно все завязано на непонятном значении NEW в триггере (там не может содержаться NULL, и там не нулл) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 13:01 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Alex_Ustinov -- SET @tts:=test.ts; -- SET @nts:=new.ts; если эти строки раскомментировать - то все заработает. Да, копирование NEW.ts в UDV делает код работоспособным: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=d63f5e37530de27f0fd463f16d7c452e ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 15:23 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
вот это определение не является правильным ts TIMESTAMP); в этом вся беда правильным будет явное указание ts TIMESTAMP NULL DEFAULT NULL); иначе боюсь после исправления этого бага работать опять не будет ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 17:07 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Alex_Ustinov вот это определение не является правильным ts TIMESTAMP); в этом вся беда правильным будет явное указание ts TIMESTAMP NULL DEFAULT NULL); https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=afd55907a878a79dce404590c61fc2e2 ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 20:57 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Akina, это и есть нонсенс. ВСЕ остальные версии генерируют `ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() об этом я писал выше. в исходниках mysql-8.0.28\sql\sql_table.cc (строка 4158) И mysql-5.7.36\sql\sql_table.cc (и в MariaDB) (строка 3307) видна разница именно в генерации поля(с NULL и без NULL) это только одно "место" кода которое я посмотрел. Причем в 8-ке перешли на nullptr, а в 5.7 и MrDB NULL. в таком случае лишь одна директива компилятора С/С++ могла перевернуть логику с ног на голову. Еще могли в одном месте поменять код, а в другом просто не знать. В триггере значение NEW. это же не всегда то что передаем в Инсерте, но и значение по дефолту, типа insert test(id) values(3). То есть там тоже много "если-то-иначе 55 раз". "Умные изречения" гипотетически возможно что в 8.0 и сравнивается ерунда в операторе типа 'NULL' <=> (nullptr *)0 указатель на 0. Но после каких то операций подключается директива типа #define NULL 0 или #define NULL (void*)0 и сравнивается как надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 21:58 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Далее, смотрим в том месте кода, что я указал; mysql-8.0.28\sql\sql_table.cc (строка 4158) И mysql-5.7.36\sql\sql_table.cc/** Modifies the first column definition whose SQL type is TIMESTAMP Изменяем определение первого столбца с типом SQL TIMESTAMP. by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. @param column_definitions The list of column definitions, in the physical order in which they appear in the table. */почему только первого??? наверное прикол какой-то..... Проверяем fiddle (пощелкать версии) Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
можно посмотреть также и с NULL в определении каждого поля. Наверное тоже весело ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 22:18 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
Alex_Ustinov ВСЕ остальные версии генерируют `ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() Это - расширение, явно описанное в документации. https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html TIMESTAMP and DATETIME columns have no automatic properties unless they are specified explicitly, with this exception: If the explicit_defaults_for_timestamp system variable is disabled, the first TIMESTAMP column has both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP if neither is specified explicitly. Соответственно различия, наблюдаемые для версий - всего лишь различия в конфигурации. Alex_Ustinov В триггере значение NEW. это же не всегда то что передаем в Инсерте, но и значение по дефолту, типа insert test(id) values(3). В триггере значение NEW. должно быть значением, которое на текущий момент должно быть присвоено полю. Откуда оно взято - из текста запроса (если указано) или из дефолтного значения поля (если не указано), разницы быть не должно. Формирование значений для записи, которые должны быть использованы для вставки либо обновления, должно быть выполнено ещё до срабатывания первого триггера. Косвенно это подтверждается тем, что если явно присваиваемое значение не соответствует требованиям на значение (неверный тип данных, NULL для NOT NULL поля), то этот факт детектируется как ошибка ещё до вызова триггера. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 22:53 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
ниже в коде комментарий ~второе значение CURRENT_TIMESTAMP по умолчанию из-за неявного продвижения секунды удаляется ... |
|||
:
Нравится:
Не нравится:
|
|||
24.01.2022, 23:04 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
авторявно описанное в документации.описано значит воспользуемся в 8,0 поставим set @@explicit_defaults_for_timestamp=0; получаем смесь 5.7/MariaDB - CREATE TABLE test (id INT, ts TIMESTAMP , ts2 TIMESTAMP NULL); (Без NULL ошибка, для второго TIMESTAMP необходимо дефолтное значение) --> `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ts2` timestamp NULL DEFAULT NULL fiddle8.0+errorMessage но это все лирика. и так и сяк в 8.0 test.ts <=> NEW.ts не работает ... |
|||
:
Нравится:
Не нравится:
|
|||
25.01.2022, 00:35 |
|
Оператор <=> в триггере - что я упускаю?
|
|||
---|---|---|---|
#18+
можно было просто обернуть COALESCE(NEW.ts,NULL) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.01.2022, 15:42 |
|
|
start [/forum/topic.php?fid=47&msg=40129313&tid=1827769]: |
0ms |
get settings: |
16ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
42ms |
get topic data: |
8ms |
get forum data: |
3ms |
get page messages: |
441ms |
get tp. blocked users: |
1ms |
others: | 13ms |
total: | 541ms |
0 / 0 |