Spec-Zone.ru › MySQL 8.4

7.1.11 Режимы SQL сервера

Сервер MySQL может работать в разных режимах SQL и применять эти режимы по-разному для разных клиентов, в зависимости от значения системной переменной sql_mode. Администраторы баз данных могут установить глобальный режим SQL, соответствующий требованиям сайта и сервера, а каждое приложение может установить свой сеансовый режим SQL для собственных потребностей.

Режимы влияют на синтаксис SQL, который поддерживает MySQL, и на проверки валидности данных, которые он выполняет. Это облегчает использование MySQL в различных средах и совместно с другими серверами баз данных.

  • Установка режима SQL

  • Наиболее важные режимы SQL

  • Полный список режимов SQL

  • Комбинированные режимы SQL

  • Строгий режим SQL

  • Сравнение ключевого слова IGNORE и строгого режима SQL

Для ответов на часто задаваемые вопросы о режимах SQL сервера в MySQL см. Приложение A.3, «MySQL 8.4 FAQ: Режим SQL сервера».

При работе с InnoDB таблицами, также обратите внимание на системную переменную innodb_strict_mode. Она включает дополнительные проверки ошибок для InnoDB таблиц.

Установка режима SQL

По умолчанию режим SQL в MySQL 8.4 включает следующие режимы: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO и NO_ENGINE_SUBSTITUTION.

Чтобы установить режим 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 требует привилегии SYSTEM_VARIABLES_ADMIN (или устаревшей привилегии SUPER) и влияет на работу всех клиентов, подключающихся с этого момента. Установка переменной SESSION влияет только на текущего клиента. Каждый клиент может в любое время изменить значение сеансовой переменной sql_mode.

Чтобы определить текущее глобальное или сеансовое значение sql_mode, выберите его значение:

SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
Важно

Режим SQL и пользовательское разбиение на разделы. Изменение режима SQL сервера после создания и вставки данных в таблицы с разбиением на разделы может вызвать существенные изменения в поведении таких таблиц и может привести к потере или повреждению данных. Сильно рекомендуется никогда не менять режим SQL после создания таблиц, использующих пользовательское разбиение на разделы.

При репликации таблиц с разбиением на разделы разные режимы SQL на источнике и реплике также могут привести к проблемам. Для наилучших результатов вы всегда должны использовать одинаковый режим SQL сервера на источнике и реплике.

Дополнительную информацию см. в Разделе 26.6, «Ограничения и пределы разбиения на разделы».

Наиболее важные режимы SQL

Вероятно, наиболее важными значениями sql_mode являются следующие:

  • ANSI

    Этот режим изменяет синтаксис и поведение, чтобы более точно соответствовать стандарту SQL. Это один из специальных комбинированных режимов, перечисленных в конце этого раздела.

  • STRICT_TRANS_TABLES

    Если значение не может быть вставлено в транзакционную таблицу, как указано, прервите выполнение оператора. Для не транзакционной таблицы прервите оператор, если значение встречается в операторе с единственной строкой или в первой строке оператора с множеством строк. Более подробные сведения приведены позже в этом разделе.

  • TRADITIONAL

    Заставьте MySQL работать как “традиционная” система управления базами данных SQL. Простым описанием этого режима является “выдавать ошибку вместо предупреждения” при вставке некорректного значения в столбец. Это один из специальных комбинированных режимов, перечисленных в конце этого раздела.

    Примечание

    При включенном режиме TRADITIONAL, оператор INSERT или UPDATE прерывается как только возникает ошибка. Если вы используете движок хранения, не поддерживающий транзакции, это может быть не то, что вам нужно, потому что изменения данных, внесенные до ошибки, могут не быть отменены, что приведет к “частичному выполнению” обновления.

Когда в этом руководстве упоминается “строгий режим”, это означает режим, в котором включен либо STRICT_TRANS_TABLES, либо STRICT_ALL_TABLES, или оба.

Полный список режимов SQL

В данном списке описаны все поддерживаемые режимы SQL:

  • ALLOW_INVALID_DATES

    Не выполнять полную проверку дат. Проверять только, что месяц находится в диапазоне от 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

    Обрабатывать " как символ кавычек для идентификаторов (как символ кавычек `), а не как символ кавычек для строк. Вы по-прежнему можете использовать ` для выделения идентификаторов при включенном этом режиме. При включенном режиме ANSI_QUOTES, вы не можете использовать двойные кавычки для выделения строковых литералов, поскольку они интерпретируются как идентификаторы.

  • ERROR_FOR_DIVISION_BY_ZERO

    Режим 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 включен без включения строгого режима или наоборот.

    Поскольку ERROR_FOR_DIVISION_BY_ZERO устарел, ожидается, что он будет удален в будущей версии MySQL как отдельный режим, а его эффект будет включен в эффект строгого режима SQL.

  • HIGH_NOT_PRECEDENCE

    Приоритет оператора 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
    
  • IGNORE_SPACE

    Разрешить пробелы между именем функции и символом (. Это заставляет имена встроенных функций обрабатываться как зарезервированные слова. В результате идентификаторы, совпадающие с именами функций, должны быть заключены в кавычки, как описано в Разделе 11.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 см. Раздел 11.2.5, «Разбор и разрешение имён функций».

  • NO_AUTO_VALUE_ON_ZERO

    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.

  • NO_BACKSLASH_ESCAPES

    Включение этого режима отключает использование обратного слэша (\) в качестве символа экранирования внутри строк и идентификаторов. При включенном этом режиме обратный слэш становится обычным символом, как и любой другой, и последовательность экранирования по умолчанию для выражений LIKE изменяется так, что символ экранирования не используется.

  • NO_DIR_IN_CREATE

    При создании таблицы игнорировать все директивы INDEX DIRECTORY и DATA DIRECTORY. Эта опция полезна на серверах репликации.

  • NO_ENGINE_SUBSTITUTION

    Управление автоматической заменой движка хранения по умолчанию, когда оператор, например, CREATE TABLE или ALTER TABLE указывает движок хранения, который отключен или не скомпилирован.

    По умолчанию NO_ENGINE_SUBSTITUTION включен.

    Так как движки хранения могут подключаться во время выполнения, недоступные движки обрабатываются аналогично:

    При отключенном NO_ENGINE_SUBSTITUTION, для CREATE TABLE используется движок по умолчанию, а если нужный движок недоступен, возникает предупреждение. Для ALTER TABLE возникает предупреждение, и таблица не изменяется.

    При включенном NO_ENGINE_SUBSTITUTION, возникает ошибка, и таблица не создается или не изменяется, если нужный движок недоступен.

  • NO_UNSIGNED_SUBTRACTION

    Вычитание между целочисленными значениями, где одно из них имеет тип 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% пригоден во всех контекстах. См. Раздел 14.10, «Функции и операторы преобразования типов».

  • NO_ZERO_DATE

    Режим 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 включен без включения строгого режима или наоборот.

    Поскольку NO_ZERO_DATE устарел, следует ожидать, что он будет удален в будущей версии MySQL как отдельное имя режима, а его эффект будет включен в эффекты строгого режима SQL.

  • NO_ZERO_IN_DATE

    Режим 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 включен без включения строгого режима или наоборот.

    Поскольку NO_ZERO_IN_DATE устарел, следует ожидать, что он будет удален в будущей версии MySQL как отдельное имя режима, а его эффект будет включен в эффекты строгого режима SQL.

  • ONLY_FULL_GROUP_BY

    Отклонять запросы, для которых список select, условие HAVING или список ORDER BY ссылаются на неагрегированные столбцы, которые не указаны в предложении GROUP BY и не функционально зависят (однозначно определяются) от столбцов GROUP BY.

    Расширение MySQL для стандартного SQL допускает ссылки в предложении HAVING на выражения с псевдонимами в списке select. Предложение HAVING может ссылаться на псевдонимы независимо от того, включен ли ONLY_FULL_GROUP_BY.

    Для дополнительного обсуждения и примеров см. Раздел 14.19.3, «Обработка GROUP BY в MySQL».

  • PAD_CHAR_TO_FULL_LENGTH

    По умолчанию, конечные пробелы обрезаются из значений столбцов CHAR при извлечении. Если включен PAD_CHAR_TO_FULL_LENGTH, обрезка не происходит, и извлеченные значения CHAR дополняются до полной длины. Этот режим не применяется к столбцам VARCHAR, для которых конечные пробелы сохраняются при извлечении.

    Примечание

    PAD_CHAR_TO_FULL_LENGTH устарел. Ожидается его удаление в будущей версии MySQL.

    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)
    
  • PIPES_AS_CONCAT

    Рассматривать || как оператор конкатенации строк (то же самое, что и CONCAT()), а не как синоним для OR.

  • REAL_AS_FLOAT

    Рассматривать REAL как синоним для FLOAT. По умолчанию MySQL рассматривает REAL как синоним для DOUBLE.

  • STRICT_ALL_TABLES

    Включить строгий режим SQL для всех движков хранения. Недопустимые значения данных отклоняются. Подробнее см. Строгий режим SQL.

  • STRICT_TRANS_TABLES

    Включить строгий режим SQL для транзакционных движков хранения и, по возможности, для нетранзакционных движков хранения. Подробнее см. Строгий режим SQL.

  • TIME_TRUNCATE_FRACTIONAL

    Управлять тем, происходит ли округление или усечение при вставке значения TIME, DATE или TIMESTAMP с дробной частью секунд в столбец того же типа, но с меньшим количеством дробных разрядов. Поведение по умолчанию — использовать округление. Если этот режим включен, вместо этого происходит усечение. Следующая последовательность операторов иллюстрирует разницу:

    CREATE TABLE t (id INT, tval TIME(1));
    SET sql_mode='';
    INSERT INTO t (id, tval) VALUES(1, 1.55);
    SET sql_mode='TIME_TRUNCATE_FRACTIONAL';
    INSERT INTO t (id, tval) VALUES(2, 1.55);
    

    Результирующее содержимое таблицы выглядит следующим образом, где первое значение было подвергнуто округлению, а второе — усечению:

    mysql> SELECT id, tval FROM t ORDER BY id;
    +------+------------+
    | id   | tval       |
    +------+------------+
    |    1 | 00:00:01.6 |
    |    2 | 00:00:01.5 |
    +------+------------+
    

    См. также Раздел 13.2.6, «Дробные секунды в значениях времени».

Комбинации режимов SQL

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

  • ANSI

    Эквивалентно REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE и 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).

    См. Раздел 1.7, «Соответствие стандартам MySQL».

  • TRADITIONAL

    TRADITIONAL эквивалентно STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO и NO_ENGINE_SUBSTITUTION.

Жесткий режим SQL

Жесткий режим контролирует, как MySQL обрабатывает недопустимые или отсутствующие значения в операциях изменения данных, таких как INSERT или UPDATE. Значение может быть недопустимым по нескольким причинам. Например, оно может иметь неверный тип данных для столбца или выходить за пределы допустимого диапазона. Значение отсутствует, когда новая строка, подлежащая вставке, не содержит значения для столбца, не являющегося NULL, который не имеет явного DEFAULT в своем определении. (Для столбца NULL вставляется NULL, если значение отсутствует.) Жесткий режим также влияет на операторы DDL, такие как CREATE TABLE.

Если жесткий режим неактивен, MySQL вставляет скорректированные значения для недопустимых или отсутствующих значений и генерирует предупреждения (см. Раздел 15.7.7.42, «Оператор SHOW WARNINGS»). В жестком режиме вы можете получить такое поведение, используя INSERT IGNORE или UPDATE IGNORE.

Для операторов, таких как SELECT, которые не изменяют данные, недопустимые значения генерируют предупреждение в жестком режиме, а не ошибку.

Жесткий режим генерирует ошибку при попытке создать ключ, длина которого превышает максимальную длину ключа. При отключенном жестком режиме это приводит к предупреждению и усечению ключа до максимальной длины.

Жесткий режим не влияет на проверку ограничений внешнего ключа. Для этого можно использовать foreign_key_checks. (См. Раздел 7.1.8, «Системные переменные сервера».)

Жесткий режим SQL активен, если включены либо STRICT_ALL_TABLES, либо STRICT_TRANS_TABLES, хотя их воздействие несколько различается:

  • Для транзакционных таблиц при включении STRICT_ALL_TABLES или STRICT_TRANS_TABLES возникает ошибка для недопустимых или отсутствующих значений в операторе изменения данных. Оператор прерывается и отменяется.

  • Для не транзакционных таблиц поведение одинаково для обоих режимов, если некорректное значение встречается в первой строке, подлежащей вставке или обновлению: оператор прерывается, и таблица остаётся без изменений. Если оператор вставляет или изменяет несколько строк, а некорректное значение встречается во второй или последующей строке, результат зависит от того, какой режим жесткости включён:

    • Для STRICT_ALL_TABLES MySQL возвращает ошибку и игнорирует остальные строки. Однако, так как предыдущие строки были вставлены или обновлены, результатом является частичное обновление. Для избежания этого используйте операторы с одной строкой, которые могут быть прерваны без изменения таблицы.

    • Для STRICT_TRANS_TABLES MySQL преобразует недопустимое значение в ближайшее допустимое значение для столбца и вставляет скорректированное значение. Если значение отсутствует, MySQL вставляет неявное значение по умолчанию для типа данных столбца. В любом случае MySQL генерирует предупреждение, а не ошибку, и продолжает обработку оператора. Неявные значения по умолчанию описаны в Разделе 13.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.

Жесткий режим влияет на обработку деления на ноль, нулевых дат и нулей в датах в сочетании с режимами ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE и NO_ZERO_IN_DATE.

Сравнение ключевого слова IGNORE и строгого режима SQL

В этом разделе сравнивается влияние ключевого слова IGNORE (которое понижает ошибки до предупреждений) и строгого режима SQL (который повышает предупреждения до ошибок) на выполнение операторов. В нём описывается, какие операторы они затрагивают и к каким ошибкам они применяются.

В следующей таблице представлено сравнение поведения операторов, когда по умолчанию возникает ошибка и когда по умолчанию возникает предупреждение. Пример, когда по умолчанию возникает ошибка — вставка NULL в столбец типа NOT NULL. Пример, когда по умолчанию возникает предупреждение — вставка значения неправильного типа данных в столбец (например, вставка строки 'abc' в столбец целого типа).

Режим работы Когда по умолчанию возникает ошибка Когда по умолчанию возникает предупреждение
Без ключевого слова IGNORE или строгого режима SQL Ошибка Предупреждение
С ключевым словом IGNORE Предупреждение Предупреждение (так же, как и без IGNORE или строгого режима SQL)
Со строгим режимом SQL Ошибка (так же, как и без IGNORE или строгого режима SQL) Ошибка
С ключевым словом IGNORE и строгим режимом SQL Предупреждение Предупреждение

Вывод из таблицы состоит в том, что когда ключевое слово IGNORE и строгий режим SQL оба активны, приоритет имеет IGNORE. Это означает, что, хотя ключевое слово IGNORE и строгий режим SQL могут считаться имеющими противоположное влияние на обработку ошибок, они не отменяют друг друга при совместном использовании.

  • Влияние ключевого слова 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 't.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 't.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 см. в разделе 7.1.11 «Режим SQL сервера».

Строгий режим SQL применяется к следующим операторам в условиях, когда некоторое значение может быть вне диапазона или некорректная строка вставляется или удаляется из таблицы:

  • ALTER TABLE

  • CREATE TABLE

  • CREATE TABLE ... SELECT

  • DELETE (как для одной таблицы, так и для нескольких)

  • INSERT

  • LOAD DATA

  • LOAD XML

  • SELECT SLEEP()

  • UPDATE (как для одной таблицы, так и для нескольких)

В хранимых процедурах отдельные операторы перечисленных типов выполняются в строгом режиме SQL, если процедура была определена, когда был включен строгий режим.

Строгий режим SQL применяется к следующим ошибкам, которые представляют класс ошибок, в которых входное значение является либо недопустимым, либо отсутствует. Значение считается недопустимым, если оно имеет неправильный тип данных для столбца или может быть вне диапазона. Значение считается отсутствующим, если новая строка, подлежащая вставке, не содержит значения для столбца NOT NULL, у которого нет явного DEFAULT-пункта в его определении.

Примечание

Поскольку дальнейшее развитие MySQL определяет новые ошибки, могут быть ошибки, не включенные в предыдущий список, к которым применяется строгий режим SQL.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/sql-mode.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API