5.1.10 Серверные режимы SQL
Сервер MySQL может работать в различных режимах SQL и применять эти режимы по-разному для разных клиентов в зависимости от значения системной переменной sql_mode. Администраторы баз данных могут установить глобальный режим SQL, соответствующий требованиям операционной среды сервера сайта, а каждое приложение может установить свой сессионный режим SQL в соответствии со своими требованиями.
Режимы влияют на синтаксис SQL, поддерживаемый MySQL, и проверки валидности данных, которые он выполняет. Это упрощает использование MySQL в разных средах и совместно с другими серверами баз данных.
Ответы на часто задаваемые вопросы о серверных режимах SQL в MySQL см. в Разделе A.3, «MySQL 5.7 FAQ: Серверный режим SQL».
При работе с InnoDB таблицами также следует учесть системную переменную innodb_strict_mode. Она включает дополнительные проверки ошибок для InnoDB таблиц.
Настройка режима SQL
По умолчанию в MySQL 5.7 включены эти режимы: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER и NO_ENGINE_SUBSTITUTION.
В MySQL 5.7 к этим режимам по умолчанию были добавлены: режимы ONLY_FULL_GROUP_BY и STRICT_TRANS_TABLES были добавлены в MySQL 5.7.5, режим NO_AUTO_CREATE_USER — в MySQL 5.7.7, режимы ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE и NO_ZERO_IN_DATE — в MySQL 5.7.8. Дополнительные сведения об этих изменениях значения по умолчанию режима SQL см. в разделе «Изменения режима SQL в MySQL 5.7».
Для установки режима SQL при запуске сервера используйте опцию --sql-mode=" в командной строке или modes"sql-mode=" в файле опций, таком как modes"my.cnf (Unix) или my.ini (Windows). modes — это список различных режимов, разделенных запятыми. Чтобы явно очистить режим SQL, установите его в пустую строку, используя --sql-mode="" в командной строке или sql-mode="" в файле опций.
Программы установки MySQL могут настроить режим SQL во время установки. Если режим SQL отличается от значения по умолчанию или от ожидаемого, проверьте настройку в файле опций, который считывает сервер при запуске.
Для изменения режима SQL во время работы установите глобальную или сессионную системную переменную sql_mode с помощью оператора SET:
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
Установка переменной GLOBAL требует привилегии SUPER и влияет на работу всех клиентов, подключающихся с этого момента. Установка переменной SESSION влияет только на текущего клиента. Каждый клиент может изменить значение своей сессионной переменной sql_mode в любое время.
Чтобы определить текущее значение глобальной или сессионной настройки sql_mode, выберите его значение:
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
Режим SQL и пользовательское разбиение. Изменение серверного режима SQL после создания и вставки данных в разделяемые таблицы может привести к существенным изменениям в поведении таких таблиц и может привести к потере или повреждению данных. Крайне не рекомендуется изменять режим SQL после создания таблиц с пользовательским разбиением.
При репликации разделяемых таблиц различные режимы SQL на источнике и реплике также могут привести к проблемам. Для наилучших результатов следует всегда использовать один и тот же серверный режим SQL на источнике и реплике.
Дополнительную информацию см. в разделе 22.6, «Ограничения на разбиение».
Самые важные режимы SQL
Вероятно, наиболее важными значениями sql_mode являются следующие:
-
Этот режим изменяет синтаксис и поведение, чтобы более точно соответствовать стандарту SQL. Это один из специальных комбинированных режимов, указанных в конце этого раздела.
-
Если значение не может быть вставлено в транзакционную таблицу, прервать выполнение оператора. Для нетранзакционной таблицы прервать оператор, если значение встречается в операторе с одной строкой или в первой строке оператора с несколькими строками. Более подробные сведения приведены позже в этом разделе.
Начиная с MySQL 5.7.5, в режим SQL по умолчанию включен режим
STRICT_TRANS_TABLES. -
Заставить MySQL работать как «традиционная» система управления базами данных SQL. Простым описанием этого режима является «выдавать ошибку вместо предупреждения» при вставке некорректного значения в столбец. Это один из специальных комбинированных режимов, указанных в конце этого раздела.
ПримечаниеПри включенном режиме
TRADITIONALоператорINSERTилиUPDATEпрерывается сразу после появления ошибки. Если вы используете движок хранения данных без транзакций, это может быть нежелательно, поскольку изменения данных, произведённые до ошибки, могут не быть отменены, что приведёт к «частичному» обновлению.
Когда в этом руководстве используется термин «строгий режим», это означает режим с включённым либо STRICT_TRANS_TABLES, либо STRICT_ALL_TABLES (или обоими).
Полный список режимов SQL
Следующий список описывает все поддерживаемые режимы SQL:
-
Не выполнять полную проверку дат. Проверять только, что месяц находится в диапазоне от 1 до 12, а день — от 1 до 31. Это может быть полезно для веб-приложений, которые получают год, месяц и день в трех отдельных полях и сохраняют введенные пользователем значения без проверки даты. Этот режим применяется к столбцам типа
DATEиDATETIME. Он не применяется к столбцам типаTIMESTAMP, для которых всегда требуется корректная дата.При отключенном
ALLOW_INVALID_DATESсервер требует, чтобы значения месяца и дня были корректными, а не просто находились в диапазоне от 1 до 12 и от 1 до 31 соответственно. При отключенном строгом режиме некорректные даты, такие как'2004-04-31', преобразуются в'0000-00-00', и генерируется предупреждение. При включенном строгом режиме некорректные даты приводят к ошибке. Чтобы разрешить такие даты, включитеALLOW_INVALID_DATES. -
Обрабатывать
"как символ кавычек для идентификаторов (как и символ кавычек`), а не как символ кавычек для строк. Вы по-прежнему можете использовать`для выделения идентификаторов при включенном этом режиме. При включенномANSI_QUOTESнельзя использовать двойные кавычки для выделения литеральных строк, так как они интерпретируются как идентификаторы. -
Режим
ERROR_FOR_DIVISION_BY_ZEROвлияет на обработку деления на ноль, включаяMOD(. Для операций изменения данных (N,0)INSERT,UPDATE) его эффект также зависит от того, включен ли строгий SQL-режим.Если этот режим не включен, деление на ноль вставляет
NULLи не генерирует предупреждение.Если этот режим включен, деление на ноль вставляет
NULLи генерирует предупреждение.Если этот режим и строгий режим включены, деление на ноль вызывает ошибку, если не задано также
IGNORE. ДляINSERT IGNOREиUPDATE IGNOREделение на ноль вставляетNULLи генерирует предупреждение.
Для
SELECTделение на ноль возвращаетNULL. ВключениеERROR_FOR_DIVISION_BY_ZEROтакже приводит к генерации предупреждения независимо от того, включен ли строгий режим.ERROR_FOR_DIVISION_BY_ZEROустарело.ERROR_FOR_DIVISION_BY_ZEROне является частью строгого режима, но должно использоваться совместно со строгим режимом и включено по умолчанию. Возникает предупреждение, еслиERROR_FOR_DIVISION_BY_ZEROвключено без одновременного включения строгого режима или наоборот. Дополнительные сведения см. в разделе Изменения в режиме SQL в MySQL 5.7.Поскольку
ERROR_FOR_DIVISION_BY_ZEROустарело, ожидается, что оно будет удалено в будущих версиях MySQL как отдельное имя режима, а его эффект будет включен в эффекты строгого SQL-режима. -
Приоритет оператора
NOTтаков, что выражения, такие какNOT a BETWEEN b AND c, анализируются какNOT (a BETWEEN b AND c). В некоторых старых версиях MySQL выражение анализировалось как(NOT a) BETWEEN b AND c. Старое поведение с более высоким приоритетом можно получить, включив SQL-режимHIGH_NOT_PRECEDENCE.mysql>
SET sql_mode = '';mysql>SELECT NOT 1 BETWEEN -5 AND 5;-> 0 mysql>SET sql_mode = 'HIGH_NOT_PRECEDENCE';mysql>SELECT NOT 1 BETWEEN -5 AND 5;-> 1 -
Разрешить пробелы между именем функции и символом
(. Это приводит к тому, что имена встроенных функций обрабатываются как зарезервированные слова. В результате идентификаторы, совпадающие с именами функций, должны быть выделены кавычками, как описано в разделе 9.2, «Имена объектов схемы». Например, поскольку существует функцияCOUNT(), использованиеcountв качестве имени таблицы в следующем операторе приведет к ошибке:mysql>
CREATE TABLE count (i INT);ERROR 1064 (42000): You have an error in your SQL syntaxИмя таблицы должно быть выделено кавычками:
mysql>
CREATE TABLE `count` (i INT);Query OK, 0 rows affected (0.00 sec)SQL-режим
IGNORE_SPACEприменяется к встроенным функциям, а не к загружаемым или хранимым функциям. В случае загружаемых или хранимых функций всегда разрешено размещать пробелы после имени функции, независимо от того, включен лиIGNORE_SPACE.Для более подробного обсуждения
IGNORE_SPACEсм. раздел 9.2.5, «Разбор и разрешение имен функций». -
Предотвращает автоматическое создание новых учетных записей пользователей оператором
GRANT, если это не предусмотрено, за исключением случаев, когда указаны данные аутентификации. Оператор должен указать непустой пароль с помощьюIDENTIFIED BYили механизм аутентификации с помощьюIDENTIFIED WITH.Предпочтительно создавать учетные записи MySQL с помощью
CREATE USER, а неGRANT.NO_AUTO_CREATE_USERустарело, и в режиме SQL по умолчанию включенNO_AUTO_CREATE_USER. Присвоения переменнойsql_mode, изменяющие состояниеNO_AUTO_CREATE_USER, генерируют предупреждение, за исключением присвоений, которые устанавливаютsql_modeв значениеDEFAULT. Ожидается, чтоNO_AUTO_CREATE_USERбудет удалено в будущих версиях MySQL, а его эффект будет включен всегда (иGRANTбольше не будет создавать учетные записи).Ранее, до того, как
NO_AUTO_CREATE_USERбыло устаревшим, одной из причин не включать его было то, что оно не было безопасным для репликации. Теперь его можно включить и выполнять безопасное управление пользователями при репликации с помощьюCREATE USER IF NOT EXISTS,DROP USER IF EXISTSиALTER USER IF EXISTS, а неGRANT. Эти операторы обеспечивают безопасную репликацию, когда реплики могут иметь разные разрешения, чем у источника. См. раздел 13.7.1.2, «Оператор CREATE USER», раздел 13.7.1.3, «Оператор DROP USER» и раздел 13.7.1.1, «Оператор ALTER USER». -
NO_AUTO_VALUE_ON_ZEROвлияет на обработку столбцов типаAUTO_INCREMENT. Обычно для генерации следующего порядкового номера столбца вы вставляете либоNULL, либо0в него.NO_AUTO_VALUE_ON_ZEROподавляет это поведение для столбцов0, так что толькоNULLгенерирует следующий порядковый номер.Этот режим может быть полезен, если
0было сохранено в столбцеAUTO_INCREMENTтаблицы. (Сохранение0— не рекомендуемая практика.) Например, если вы экспортируете таблицу с помощью mysqldump, а затем импортируете её, MySQL обычно генерирует новые порядковые номера при встрече значений0, что приводит к таблице с содержимым, отличным от экспортированной. ВключениеNO_AUTO_VALUE_ON_ZEROперед повторным импортом файла экспорта решает эту проблему. По этой причине mysqldump автоматически включает в свой вывод оператор, который включаетNO_AUTO_VALUE_ON_ZERO. -
Включение этого режима отключает использование символа обратного слэша (
\) в качестве символа экранирования внутри строк и идентификаторов. При включенном этом режиме обратный слэш становится обычным символом, как и любой другой, и последовательность экранирования по умолчанию для выраженийLIKEизменяется, чтобы не использовать символ экранирования.
-
При создании таблицы игнорируйте все директивы
INDEX DIRECTORYиDATA DIRECTORY. Этот параметр полезен на серверах репликации реплик. -
Управление автоматической заменой движка хранения по умолчанию, когда в операторе, таком как
CREATE TABLEилиALTER TABLE, указан движок хранения, который отключен или не скомпилирован.По умолчанию
NO_ENGINE_SUBSTITUTIONвключен.Поскольку движки хранения могут быть подключаемыми во время выполнения, недоступные движки обрабатываются одинаково:
Если
NO_ENGINE_SUBSTITUTIONотключен, дляCREATE TABLEиспользуется движок по умолчанию, и возникает предупреждение, если нужный движок недоступен. ДляALTER TABLEвозникает предупреждение, и таблица не изменяется.Если
NO_ENGINE_SUBSTITUTIONвключен, возникает ошибка, и таблица не создается или не изменяется, если нужный движок недоступен. -
Не печатать параметры столбцов, специфичные для MySQL, в выводе
SHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.NoteНачиная с MySQL 5.7.22,
NO_FIELD_OPTIONSустарел. Он удален в MySQL 8.0. -
Не печатать параметры индекса, специфичные для MySQL, в выводе
SHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.NoteНачиная с MySQL 5.7.22,
NO_KEY_OPTIONSустарел. Он удален в MySQL 8.0. -
Не печатать параметры таблицы, специфичные для MySQL (например,
ENGINE), в выводеSHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.NoteНачиная с MySQL 5.7.22,
NO_TABLE_OPTIONSустарел. Он удален в MySQL 8.0. -
Вычитание между целочисленными значениями, где одно имеет тип
UNSIGNED, по умолчанию дает беззнаковый результат. Если результат в противном случае был бы отрицательным, возникает ошибка:mysql>
SET sql_mode = '';Query OK, 0 rows affected (0.00 sec) mysql>SELECT CAST(0 AS UNSIGNED) - 1;ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'Если режим SQL
NO_UNSIGNED_SUBTRACTIONвключен, результат будет отрицательным:mysql>
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';mysql>SELECT CAST(0 AS UNSIGNED) - 1;+-------------------------+ | CAST(0 AS UNSIGNED) - 1 | +-------------------------+ | -1 | +-------------------------+Если результат такой операции используется для обновления столбца целого числа
UNSIGNED, результат усекается до максимального значения для типа столбца или усекается до 0, если включенNO_UNSIGNED_SUBTRACTION. При включенном строгом режиме SQL возникает ошибка, и столбец остается неизменным.Когда включен
NO_UNSIGNED_SUBTRACTION, результат вычитания является знаковым, даже если любой операнд является беззнаковым. Например, сравните тип столбцаc2в таблицеt1с типом столбцаc2в таблицеt2:mysql>
SET sql_mode='';mysql>CREATE TABLE test (c1 BIGINT UNSIGNED NOT NULL);mysql>CREATE TABLE t1 SELECT c1 - 1 AS c2 FROM test;mysql>DESCRIBE t1;+-------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+-------+ | c2 | bigint(21) unsigned | NO | | 0 | | +-------+---------------------+------+-----+---------+-------+ mysql>SET sql_mode='NO_UNSIGNED_SUBTRACTION';mysql>CREATE TABLE t2 SELECT c1 - 1 AS c2 FROM test;mysql>DESCRIBE t2;+-------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------+------+-----+---------+-------+ | c2 | bigint(21) | NO | | 0 | | +-------+------------+------+-----+---------+-------+Это означает, что
BIGINT UNSIGNEDне на 100% пригоден во всех контекстах. См. Раздел 12.10, «Функции и операторы преобразования типов». -
Режим
NO_ZERO_DATEвлияет на то, разрешает ли сервер'0000-00-00'в качестве допустимой даты. Его действие также зависит от того, включен ли строгий режим SQL.Если этот режим не включен,
'0000-00-00'разрешен, и вставки не выдают предупреждений.Если этот режим включен,
'0000-00-00'разрешен, и вставки выдают предупреждение.Если включены этот режим и строгий режим,
'0000-00-00'не разрешен, и вставки выдают ошибку, если только не указан такжеIGNORE. ДляINSERT IGNOREиUPDATE IGNORE,'0000-00-00'разрешен, и вставки выдают предупреждение.
NO_ZERO_DATEустарел.NO_ZERO_DATEне является частью строгого режима, но должен использоваться вместе со строгим режимом и включен по умолчанию. Предупреждение возникает, еслиNO_ZERO_DATEвключен без включения строгого режима или наоборот. Для дополнительного обсуждения см. Изменения режима SQL в MySQL 5.7.Поскольку
NO_ZERO_DATEустарел; ожидается, что он будет удален в будущей версии MySQL как отдельное имя режима, а его эффект будет включен в эффекты строгого режима SQL. -
Режим
NO_ZERO_IN_DATEвлияет на то, разрешает ли сервер даты, в которых год отличен от нуля, но месяц или день равны 0. (Этот режим влияет на даты, такие как'2010-00-01'или'2010-01-00', но не на'0000-00-00'. Чтобы управлять тем, разрешает ли сервер'0000-00-00', используйте режимNO_ZERO_DATE.) ДействиеNO_ZERO_IN_DATEтакже зависит от того, включен ли строгий режим SQL.Если этот режим не включен, даты с нулевыми частями разрешены, и вставки не выдают предупреждений.
Если этот режим включен, даты с нулевыми частями вставляются как
'0000-00-00'и выдают предупреждение.Если включены этот режим и строгий режим, даты с нулевыми частями не разрешены, и вставки выдают ошибку, если только не указан также
IGNORE. ДляINSERT IGNOREиUPDATE IGNOREдаты с нулевыми частями вставляются как'0000-00-00'и выдают предупреждение.
NO_ZERO_IN_DATEустарел.NO_ZERO_IN_DATEне является частью строгого режима, но должен использоваться вместе со строгим режимом и включен по умолчанию. Предупреждение возникает, еслиNO_ZERO_IN_DATEвключен без включения строгого режима или наоборот. Для дополнительного обсуждения см. Изменения режима SQL в MySQL 5.7.Поскольку
NO_ZERO_IN_DATEустарел; ожидается, что он будет удален в будущей версии MySQL как отдельное имя режима, а его эффект будет включен в эффекты строгого режима SQL. -
Отклонять запросы, для которых список select, условие
HAVINGили списокORDER BYссылаются на неагрегированные столбцы, которые не указаны в предложенииGROUP BYи не функционально зависят (однозначно определяются) от столбцовGROUP BY.Начиная с MySQL 5.7.5, режим SQL по умолчанию включает
ONLY_FULL_GROUP_BY. (До 5.7.5 MySQL не обнаруживает функциональную зависимость, иONLY_FULL_GROUP_BYне включен по умолчанию.)Расширение MySQL для стандартного SQL допускает ссылки в предложении
HAVINGна выражения с псевдонимами в списке select. До MySQL 5.7.5 включениеONLY_FULL_GROUP_BYотключает это расширение, требуя, таким образом, чтобы предложениеHAVINGбыло написано с использованием выражений без псевдонимов. Начиная с MySQL 5.7.5, это ограничение снято, так что предложениеHAVINGможет ссылаться на псевдонимы независимо от того, включен лиONLY_FULL_GROUP_BY.Для дополнительного обсуждения и примеров см. Раздел 12.19.3, «Обработка GROUP BY в MySQL».
-
По умолчанию, хвостовые пробелы обрезаются из значений столбцов
CHARпри извлечении. ЕслиPAD_CHAR_TO_FULL_LENGTHвключено, обрезка не происходит, и извлеченные значенияCHARзаполняются до их полной длины. Этот режим не применяется к столбцамVARCHAR, для которых хвостовые пробелы сохраняются при извлечении.mysql>
CREATE TABLE t1 (c1 CHAR(10));Query OK, 0 rows affected (0.37 sec) mysql>INSERT INTO t1 (c1) VALUES('xy');Query OK, 1 row affected (0.01 sec) mysql>SET sql_mode = '';Query OK, 0 rows affected (0.00 sec) mysql>SELECT c1, CHAR_LENGTH(c1) FROM t1;+------+-----------------+ | c1 | CHAR_LENGTH(c1) | +------+-----------------+ | xy | 2 | +------+-----------------+ 1 row in set (0.00 sec) mysql>SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';Query OK, 0 rows affected (0.00 sec) mysql>SELECT c1, CHAR_LENGTH(c1) FROM t1;+------------+-----------------+ | c1 | CHAR_LENGTH(c1) | +------------+-----------------+ | xy | 10 | +------------+-----------------+ 1 row in set (0.00 sec) -
Обрабатывать
||как оператор конкатенации строк (так же, какCONCAT()), а не как синонимOR. -
Обрабатывать
REALкак синоним дляFLOAT. По умолчанию MySQL обрабатываетREALкак синоним дляDOUBLE. -
Включить строгий режим SQL для всех хранилищ данных. Недопустимые значения данных будут отклоняться. Подробнее см. Строгий режим SQL.
С MySQL 5.7.4 по 5.7.7,
STRICT_ALL_TABLESвключает эффект режимовERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATEиNO_ZERO_IN_DATE. Дополнительные сведения см. в Изменения режима SQL в MySQL 5.7. -
Включить строгий режим SQL для транзакционных хранилищ данных, а при возможности и для не транзакционных хранилищ данных. Подробнее см. Строгий режим SQL.
С MySQL 5.7.4 по 5.7.7,
STRICT_TRANS_TABLESвключает эффект режимовERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATEиNO_ZERO_IN_DATE. Дополнительные сведения см. в Изменения режима SQL в MySQL 5.7.
Комбинированные режимы SQL
Следующие специальные режимы предоставляются в качестве сокращенной записи для комбинаций значений режимов из предыдущего списка.
-
Эквивалентно
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE, и (начиная с MySQL 5.7.5)ONLY_FULL_GROUP_BY.Режим
ANSIтакже приводит к тому, что сервер возвращает ошибку для запросов, где набор функцийSс внешней ссылкойне может быть агрегирован во внешнем запросе, относительно которого была разрешена внешняя ссылка. Это такой запрос:S(outer_ref)SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);
Здесь,
MAX(t1.b)не может быть агрегирован во внешнем запросе, поскольку он появляется в предложенииWHEREэтого запроса. Стандартный SQL требует ошибки в этой ситуации. Если режимANSIне включен, сервер обрабатываетв таких запросах так же, как он интерпретировал быS(outer_ref).S(const) -
Эквивалентно
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS.ПримечаниеНачиная с MySQL 5.7.22,
DB2устарел. Он удален в MySQL 8.0. -
Эквивалентно
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER.ПримечаниеНачиная с MySQL 5.7.22,
MAXDBустарел. Он удален в MySQL 8.0. -
Эквивалентно
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS.ПримечаниеНачиная с MySQL 5.7.22,
MSSQLустарел. Он удален в MySQL 8.0. -
Эквивалентно
MYSQL323,HIGH_NOT_PRECEDENCE. Это означаетHIGH_NOT_PRECEDENCEплюс некоторые особенности поведенияSHOW CREATE TABLE, специфичные дляMYSQL323:отображение столбца
TIMESTAMPне включает атрибутыDEFAULTилиON UPDATE.отображение строкового столбца не включает атрибуты кодировки и сортировки. Для столбцов
CHARиVARCHAR, если сортировка бинарная, к типу столбца добавляетсяBINARY.параметр таблицы
ENGINE=отображается какengine_nameTYPE=.engine_nameДля таблиц
MEMORYмеханизм хранения отображается какHEAP.
ПримечаниеНачиная с MySQL 5.7.22,
MYSQL323устарел. Он удален в MySQL 8.0. -
Эквивалентно
MYSQL40,HIGH_NOT_PRECEDENCE. Это означаетHIGH_NOT_PRECEDENCEплюс некоторые особенности поведения, специфичные дляMYSQL40. Они такие же, как и дляMYSQL323, за исключением того, чтоSHOW CREATE TABLEне отображаетHEAPв качестве механизма хранения для таблицMEMORY.ПримечаниеНачиная с MySQL 5.7.22,
MYSQL40устарел. Он удален в MySQL 8.0. -
Эквивалентно
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER.ПримечаниеНачиная с MySQL 5.7.22,
ORACLEустарел. Он удален в MySQL 8.0. -
Эквивалентно
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS.ПримечаниеНачиная с MySQL 5.7.22,
POSTGRESQLустарел. Он удален в MySQL 8.0.
-
Перед MySQL 5.7.4, а также в MySQL 5.7.8 и более поздних версиях,
TRADITIONALэквивалентенSTRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USERиNO_ENGINE_SUBSTITUTION.С MySQL 5.7.4 до 5.7.7,
TRADITIONALэквивалентенSTRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_AUTO_CREATE_USERиNO_ENGINE_SUBSTITUTION. РежимыNO_ZERO_IN_DATE,NO_ZERO_DATEиERROR_FOR_DIVISION_BY_ZEROне имеют отдельных названий, так как в этих версиях их влияние включено в действие строгого режима SQL (STRICT_ALL_TABLESилиSTRICT_TRANS_TABLES). Таким образом, влияниеTRADITIONALодинаково во всех версиях MySQL 5.7 (и такое же, как в MySQL 5.6). Для дополнительной информации см. Изменения в режиме SQL в MySQL 5.7.
Строгий режим SQL
Строгий режим контролирует, как MySQL обрабатывает некорректные или отсутствующие значения в операциях изменения данных, таких как INSERT или UPDATE. Значение может быть некорректным по нескольким причинам. Например, оно может иметь неверный тип данных для столбца или выходить за пределы допустимого диапазона. Значение отсутствует, когда новая строка, которую нужно вставить, не содержит значения для столбца, не имеющего явного NULL условия, не указанного в его определении. (Для NULL столбца, если значение отсутствует, вставляется NULL). Строгий режим также влияет на операторы DDL, такие как CREATE TABLE.
Если строгий режим не активен, MySQL вставляет скорректированные значения для некорректных или отсутствующих значений и выводит предупреждения (см. Раздел 13.7.5.40, «Оператор SHOW WARNINGS»). В строгом режиме вы можете получить это поведение с помощью INSERT IGNORE или UPDATE
IGNORE.
Для операторов, таких как SELECT, которые не изменяют данные, некорректные значения вызывают предупреждение в строгом режиме, а не ошибку.
Строгий режим приводит к ошибке при попытке создать ключ, длина которого превышает максимальную. При отключенном строгом режиме это приводит к предупреждению и усечению ключа до максимальной длины.
Строгий режим не влияет на проверку ограничений внешних ключей. Для этого можно использовать foreign_key_checks. (См. Раздел 5.1.7, «Системные переменные сервера».)
Строгий режим SQL активен, если включен либо STRICT_ALL_TABLES, либо STRICT_TRANS_TABLES, хотя их влияние несколько отличается:
Для транзакционных таблиц при включении либо
STRICT_ALL_TABLES, либоSTRICT_TRANS_TABLESвозникает ошибка для некорректных или отсутствующих значений в операторе изменения данных. Оператор прерывается и отменяется.-
Для нетранзакционных таблиц поведение одинаково для обоих режимов, если некорректное значение встречается в первой строке для вставки или обновления: оператор прерывается, а таблица остается неизменной. Если оператор вставляет или изменяет несколько строк, и некорректное значение встречается во второй или последующей строке, результат зависит от включенного режима строгости:
Для
STRICT_ALL_TABLESMySQL возвращает ошибку и игнорирует остальные строки. Однако, поскольку предыдущие строки были вставлены или обновлены, результат представляет собой частичное обновление. Чтобы избежать этого, используйте операторы для обработки одной строки, которые могут быть прерваны без изменения таблицы.Для
STRICT_TRANS_TABLESMySQL преобразует некорректное значение в ближайшее корректное значение для столбца и вставляет скорректированное значение. Если значение отсутствует, MySQL вставляет неявное значение по умолчанию для типа данных столбца. В любом случае MySQL генерирует предупреждение вместо ошибки и продолжает обработку оператора. Неявные значения по умолчанию описаны в Разделе 11.6, «Значения по умолчанию типов данных».
Строгий режим влияет на обработку деления на ноль, нулевых дат и нулей в датах следующим образом:
-
Строгий режим влияет на обработку деления на ноль, включая
MOD(:N,0)Для операций изменения данных (
INSERT,UPDATE):Если строгий режим не включен, деление на ноль вставляет
NULLи не выводит предупреждение.Если строгий режим включен, деление на ноль вызывает ошибку, если также не указано
IGNORE. ДляINSERT IGNOREиUPDATE IGNOREделение на ноль вставляетNULLи выводит предупреждение.
Для
SELECTделение на ноль возвращаетNULL. Включение строгого режима также вызывает вывод предупреждения. -
Строгий режим влияет на то, допускает ли сервер
'0000-00-00'как корректную дату:Если строгий режим не включен,
'0000-00-00'допускается, и вставки не вызывают предупреждений.Если строгий режим включен,
'0000-00-00'не допускается, и вставки вызывают ошибку, если также не указаноIGNORE. ДляINSERT IGNOREиUPDATE IGNORE,'0000-00-00'допускается, и вставки вызывают предупреждение.
-
Строгий режим влияет на то, допускает ли сервер даты, в которых год не равен нулю, но месяц или день равны 0 (например, даты типа
'2010-00-01'или'2010-01-00'):Если строгий режим не включен, даты с нулевыми частями допускаются, и вставки не вызывают предупреждений.
Если строгий режим включен, даты с нулевыми частями не допускаются, и вставки вызывают ошибку, если также не указано
IGNORE. ДляINSERT IGNOREиUPDATE IGNORE, даты с нулевыми частями вставляются как'0000-00-00'(что считается корректным сIGNORE) и вызывают предупреждение.
Для получения дополнительной информации о строгом режиме в отношении IGNORE, см. Сравнение ключевого слова IGNORE и строгого режима SQL.
Перед MySQL 5.7.4, а также в MySQL 5.7.8 и более поздних версиях, строгий режим влияет на обработку деления на ноль, нулевых дат и нулей в датах в сочетании с режимами ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE и NO_ZERO_IN_DATE. С MySQL 5.7.4 по 5.7.7, режимы ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE и NO_ZERO_IN_DATE не выполняют никаких действий, когда они явно указаны, и их влияние включено в действие строгого режима. Для дополнительной информации см. Изменения в режиме SQL в MySQL 5.7.
Сравнение ключевого слова IGNORE и строгого режима SQL
В этом разделе сравниваются эффекты ключевого слова IGNORE (которое понижает ошибки до предупреждений) и строгого режима SQL (который повышает предупреждения до ошибок) на выполнение запросов. Здесь описывается, к каким операторам они применяются и к каким ошибкам.
В следующей таблице представлено сравнение поведения операторов, когда по умолчанию ожидается ошибка против предупреждения. Пример ошибки по умолчанию — вставка NULL в колонку типа NOT
NULL. Пример предупреждения — вставка значения неверного типа данных в колонку (например, вставка строки 'abc' в колонку целого типа).
| Режим работы | Когда оператор по умолчанию генерирует ошибку | Когда оператор по умолчанию генерирует предупреждение |
|---|---|---|
Без ключевого слова IGNORE или строгого режима SQL | Ошибка | Предупреждение |
С ключевым словом IGNORE
| Предупреждение | Предупреждение (то же, что и без IGNORE или строгого режима SQL) |
| Со строгим режимом SQL | Ошибка (то же, что и без IGNORE или строгого режима SQL) | Ошибка |
С ключевым словом IGNORE и строгим режимом SQL | Предупреждение | Предупреждение |
Один из выводов из таблицы состоит в том, что когда ключевое слово IGNORE и строгий режим SQL действуют одновременно, IGNORE имеет приоритет. Это означает, что, хотя IGNORE и строгий режим SQL могут считаться иметь противоположные эффекты на обработку ошибок, они не отменяют друг друга при совместном использовании.
Эффект ключевого слова IGNORE на выполнение операторов
Некоторые операторы в MySQL поддерживают необязательное ключевое слово IGNORE. Это ключевое слово заставляет сервер понижать определенные типы ошибок до предупреждений. Для операторов, охватывающих несколько строк, понижение ошибки до предупреждения может позволить обработать строку. В противном случае IGNORE заставляет оператор перейти к следующей строке вместо прерывания. (Для неопускаемых ошибок ошибка возникает независимо от ключевого слова IGNORE).
Пример: если таблица t имеет колонку первичного ключа i, содержащую уникальные значения, попытка вставить одно и то же значение i в несколько строк обычно приводит к ошибке дублирования ключа:
mysql> CREATE TABLE t (i INT NOT NULL PRIMARY KEY);
mysql> INSERT INTO t (i) VALUES(1),(1);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
С использованием IGNORE, строка с дублирующимся ключом всё равно не вставляется, но вместо ошибки появляется предупреждение:
mysql> INSERT IGNORE INTO t (i) VALUES(1),(1);
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 2 Duplicates: 1 Warnings: 1
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------+
| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |
+---------+------+---------------------------------------+
1 row in set (0.00 sec)
Пример: если таблица t2 имеет колонку NOT
NULL типа id, попытка вставить NULL приводит к ошибке в строгом режиме SQL:
mysql> CREATE TABLE t2 (id INT NOT NULL);
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
ERROR 1048 (23000): Column 'id' cannot be null
mysql> SELECT * FROM t2;
Empty set (0.00 sec)
Если режим SQL не строгий, IGNORE заставляет сервер вставить NULL в колонку в качестве неявного значения по умолчанию (0 в данном случае), что позволяет обработать строку без пропуска:
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
mysql> SELECT * FROM t2;
+----+
| id |
+----+
| 1 |
| 0 |
| 3 |
+----+
Эти операторы поддерживают ключевое слово IGNORE:
CREATE TABLE ... SELECT:IGNOREне относится к частямCREATE TABLEилиSELECTоператора, но к вставкам в таблицу строк, полученных изSELECT. Строки, дублирующие существующую строку по значению уникального ключа, отбрасываются.DELETE:IGNOREзаставляет MySQL игнорировать ошибки во время удаления строк.-
INSERT: СIGNORE, строки, дублирующие существующую строку по значению уникального ключа, отбрасываются. Строки, заданные значениями, которые вызывают ошибки преобразования данных, устанавливаются на ближайшие допустимые значения.Для разнесенных таблиц, где не найдено разбиение, соответствующее заданному значению,
IGNOREзаставляет операцию вставки замолчать для строк, содержащих несовпадающее значение. LOAD DATA,LOAD XML: СIGNORE, строки, дублирующие существующую строку по значению уникального ключа, отбрасываются.UPDATE: СIGNORE, строки, для которых возникают конфликты дублирования ключей по уникальному значению ключа, не обновляются. Строки, обновленные до значений, которые вызывают ошибки преобразования данных, обновляются до ближайших допустимых значений вместо этого.
Ключевое слово IGNORE применяется к следующим ошибкам, которые можно игнорировать:
Эффект строгого режима SQL на выполнение операторов
MySQL-сервер может работать в разных режимах SQL, и применять эти режимы по-разному для разных клиентов, в зависимости от значения системной переменной sql_mode. В режиме “строгий” SQL сервер повышает некоторые предупреждения до ошибок.
Например, в нестрогом режиме SQL вставка строки 'abc' в колонку целого типа приводит к преобразованию значения в 0 и предупреждению:
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t (i) VALUES('abc');
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'abc' for column 'i' at row 1 |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)
В строгом режиме SQL недопустимое значение отбрасывается с ошибкой:
mysql> SET sql_mode = 'STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t (i) VALUES('abc');
ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'i' at row 1
Для получения дополнительной информации о возможных значениях системной переменной sql_mode см. Раздел 5.1.10, «Режимы SQL сервера».
Строгий режим SQL применяется к следующим операторам в условиях, когда некоторые значения могут быть вне диапазона или недействительная строка вставляется в таблицу или удаляется из нее:
Внутри хранимых программ отдельные операторы перечисленных типов выполняются в строгом режиме SQL, если программа была определена при включенном строгом режиме.
Строгий режим SQL применяется к следующим ошибкам, которые представляют класс ошибок, в которых входное значение недействительно или отсутствует. Значение недействительно, если оно имеет неверный тип данных для колонки или может быть вне диапазона. Значение отсутствует, если новая строка, которая должна быть вставлена, не содержит значения для колонки NOT
NULL, которая не имеет явного DEFAULT-описания.
Поскольку дальнейшее развитие MySQL определяет новые ошибки, могут быть ошибки, отсутствующие в предыдущем списке, к которым применяется строгий режим SQL.
Изменения в режиме SQL в MySQL 5.7
В MySQL 5.7.22 эти режимы SQL устарели и удалены в MySQL 8.0: DB2, MAXDB, MSSQL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTIONS, NO_TABLE_OPTIONS.
В MySQL 5.7 по умолчанию включен режим SQL ONLY_FULL_GROUP_BY, так как обработка GROUP BY стала более сложной, включив обнаружение функциональных зависимостей. Однако, если вы обнаружите, что включение ONLY_FULL_GROUP_BY приводит к отклонению запросов существующих приложений, выполните одно из следующих действий:
Если возможно, измените проблемный запрос, чтобы столбцы, не являющиеся агрегированными, зависели функционально от
GROUP BYстолбцов, или сослайтесь на столбцы, не являющиеся агрегированными, используяANY_VALUE().Если изменить проблемный запрос невозможно (например, если он генерируется приложением стороннего производителя), установите системную переменную
sql_modeпри запуске сервера, чтобы не включатьONLY_FULL_GROUP_BY.
В MySQL 5.7 режимы SQL ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE и NO_ZERO_IN_DATE устарели. Планируется, что эти три режима будут включены в строгий режим SQL и удалены в качестве отдельных режимов в будущих версиях MySQL. Для совместимости MySQL 5.7 с режимом строгого SQL MySQL 5.6 и для предоставления дополнительного времени для изменения затронутых приложений применяются следующие правила:
ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATEиNO_ZERO_IN_DATEне являются частью строгого режима SQL, но предполагается, что они используются вместе со строгим режимом. Напоминаем, что появляется предупреждение, если они включены без включения строгого режима или наоборот.ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATEиNO_ZERO_IN_DATEвключены по умолчанию.
С указанными изменениями более строгая проверка данных по-прежнему включена по умолчанию, но отдельные режимы могут быть отключены в средах, где это в настоящее время желательно или необходимо.
© 2025 Oracle
Licensed under the GPLv2 License.