Spec-Zone.ru › MySQL 9.2

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

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

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

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

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

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

  • Режимы SQL комбинации

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

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

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

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

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

По умолчанию режим SQL в MySQL 9.2 включает следующие режимы: 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-9.2-en/sql-mode.html

Spec-Zone.ru

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