Какая проверка делает MySQL, когда включен строгий режим?
Я был очень удивлен, когда MySQL разрешил мне вставить NULL
в поле, созданное с помощью NOT NULL
. Я провел некоторое исследование и обнаружил, как включить строгий режим. Тем не менее, я не совсем уверен, какая проверка MySQL делает, когда STRICT_ALL_TABLES
включен.
В руководстве написано:
Строгий режим определяет, как MySQL обрабатывает недопустимые или отсутствующие входные значения. Значение может быть недопустимым по нескольким причинам. (выделение мое) Например, у него может быть неправильный тип данных для столбца, или он может быть вне допустимого диапазона.
Я понимаю, что он считает отсутствующим, и как он справляется с этим. Я не понимаю, что он считает недействительным. Я провел некоторое тестирование и обнаружил следующее:
-
Строки
- которые слишком длинны, недействительны.
- недопустимые номера
-
NULL
для столбца не NULL
недействительны
-
TRUE
и FALSE
всегда кажутся действительными (они становятся равными 1 и 0 соответственно)
- неверные даты недействительны
- нулевые даты действительны (для изменения этого поведения могут быть разрешены дополнительные режимы)
- float в целочисленном поле действительны (они округляются)
- буквы в поле числа недействительны
Выполняет ли MySQL другие проверки валидации, отличные от того, что упоминалось выше?
В руководстве написано "неправильный тип данных для столбца", но единственная ситуация, когда я вижу, что это фактически входит в игру, - это буквы в поле чисел. Существуют ли другие примеры ошибок типа данных?
Есть ли список где-то точно, какие проверки MySQL выполняет?
РЕДАКТИРОВАТЬ:. Для записи мое приложение уже проводит обширную проверку. Я использую строгий режим как последний шанс, только в случае проверки. Если я забуду что-то проверить, я хочу, чтобы он быстро сработал, а не "молчал какими-то моими данными".
Ответы
Ответ 1
Хорошим ресурсом является проверка источника MySQL и чтение mysql-test/t/strict.test
для просмотра всех случаев, которые они тестируют после установки режима STRICT или TRADITIONAL (что является надстрокой STRICT).
Вы отлично провели исследования и испытания, но есть еще несколько случаев, таких как:
- Попытка вставить значение undefined ENUM.
- Попытка вставить значение по умолчанию для столбца NOT NULL без определения DEFAULT.
- Попытка использовать CAST() для преобразования строк в целые числа и т.д.
- Преобразование VARCHAR в MEDIUMTEXT или LONGTEXT, если вы даете длину больше 65536.
- Усечение строк COMMENT для таблиц и столбцов.
- Преобразование строки в тип YEAR.
- Определение столбца SET или ENUM с повторяющимися записями.
Также mysql-test/include/strict_autoinc.inc
, потому что он проверяет переполнение, когда значение auto-inc становится слишком большим.
Есть несколько других тестовых файлов, которые используют STRICT-режим для определенных тестов, но я не рассматривал их.
Ответ 2
Я скопировал исходный код MySQL 5.5.28 (Community Server Edition), чтобы найти экземпляры используемых STRICT_ALL_TABLES.
Из того, что я увидел, похоже, что ваш список уже довольно полный, но ниже есть еще несколько вещей, которые я узнал об использовании STRICT_ALL_TABLES. Первая - это еще одна проверка, в то время как все остальные имеют дело с ошибками и предупреждениями.
- В столбцах геометрии не может быть значения по умолчанию. (SQL/field.cc: 9394)
- Если комментарий таблицы длиннее 2048 символов, MySQL создает ошибку, а не усекает комментарий с предупреждением. (SQL/unireg.cc: 231)
- Если комментарий поля длиннее 1024 символов, MySQL выдает ошибку, а не усекает комментарий с предупреждением. (SQL/unireg.cc: 739)
- При вставке или обновлении, если дублирующее значение существует в SET или ENUM MySQL, выдается ошибка, а не предупреждение. (SQL/sql_table.cc: 2503)
- Существует множество операций, которые будут прерваны при предупреждении с помощью STRICT_ALL_TABLES, а не просто с предупреждением. Это слишком много для меня, чтобы список, и установка флага abort_on_warning слишком далека от кода, который создает предупреждения для меня, чтобы легко документировать (или даже понимать) все из них. Но если кто-то хочет замарать руки в исходном коде, несколько начальных мест будут sql/sql_update.cc: 630 и sql/sql_insert.cc: 841