Spec-Zone.ru › MySQL 5.7

5.1.10 Серверные режимы SQL

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

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

  • Настройка режима SQL

  • Самые важные режимы SQL

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

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

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

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

  • Изменения режима SQL в MySQL 5.7

Ответы на часто задаваемые вопросы о серверных режимах 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 являются следующие:

  • ANSI

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

  • STRICT_TRANS_TABLES

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

    Начиная с MySQL 5.7.5, в режим 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 включено без одновременного включения строгого режима или наоборот. Дополнительные сведения см. в разделе Изменения в режиме SQL в MySQL 5.7.

    Поскольку 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

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

  • NO_AUTO_CREATE_USER

    Предотвращает автоматическое создание новых учетных записей пользователей оператором 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

    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_FIELD_OPTIONS

    Не печатать параметры столбцов, специфичные для MySQL, в выводе SHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.

    Note

    Начиная с MySQL 5.7.22, NO_FIELD_OPTIONS устарел. Он удален в MySQL 8.0.

  • NO_KEY_OPTIONS

    Не печатать параметры индекса, специфичные для MySQL, в выводе SHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.

    Note

    Начиная с MySQL 5.7.22, NO_KEY_OPTIONS устарел. Он удален в MySQL 8.0.

  • NO_TABLE_OPTIONS

    Не печатать параметры таблицы, специфичные для MySQL (например, ENGINE), в выводе SHOW CREATE TABLE. Этот режим используется mysqldump в режиме переносимости.

    Note

    Начиная с MySQL 5.7.22, NO_TABLE_OPTIONS устарел. Он удален в MySQL 8.0.

  • 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% пригоден во всех контекстах. См. Раздел 12.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 включен без включения строгого режима или наоборот. Для дополнительного обсуждения см. Изменения режима SQL в MySQL 5.7.

    Поскольку 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 включен без включения строгого режима или наоборот. Для дополнительного обсуждения см. Изменения режима SQL в MySQL 5.7.

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

  • ONLY_FULL_GROUP_BY

    Отклонять запросы, для которых список 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».

  • PAD_CHAR_TO_FULL_LENGTH

    По умолчанию, хвостовые пробелы обрезаются из значений столбцов 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)
    
  • PIPES_AS_CONCAT

    Обрабатывать || как оператор конкатенации строк (так же, как CONCAT()), а не как синоним OR.

  • REAL_AS_FLOAT

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

  • STRICT_ALL_TABLES

    Включить строгий режим 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.

  • STRICT_TRANS_TABLES

    Включить строгий режим 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

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

  • ANSI

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

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

  • DB2

    Эквивалентно PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

    Примечание

    Начиная с MySQL 5.7.22, DB2 устарел. Он удален в MySQL 8.0.

  • MAXDB

    Эквивалентно 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.

  • MSSQL

    Эквивалентно 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

    Эквивалентно MYSQL323, HIGH_NOT_PRECEDENCE. Это означает HIGH_NOT_PRECEDENCE плюс некоторые особенности поведения SHOW CREATE TABLE, специфичные для MYSQL323:

    • отображение столбца TIMESTAMP не включает атрибуты DEFAULT или ON UPDATE.

    • отображение строкового столбца не включает атрибуты кодировки и сортировки. Для столбцов CHAR и VARCHAR, если сортировка бинарная, к типу столбца добавляется BINARY.

    • параметр таблицы ENGINE=engine_name отображается как TYPE=engine_name.

    • Для таблиц MEMORY механизм хранения отображается как HEAP.

    Примечание

    Начиная с MySQL 5.7.22, MYSQL323 устарел. Он удален в MySQL 8.0.

  • MYSQL40

    Эквивалентно MYSQL40, HIGH_NOT_PRECEDENCE. Это означает HIGH_NOT_PRECEDENCE плюс некоторые особенности поведения, специфичные для MYSQL40. Они такие же, как и для MYSQL323, за исключением того, что SHOW CREATE TABLE не отображает HEAP в качестве механизма хранения для таблиц MEMORY.

    Примечание

    Начиная с MySQL 5.7.22, MYSQL40 устарел. Он удален в MySQL 8.0.

  • ORACLE

    Эквивалентно 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.

  • POSTGRESQL

    Эквивалентно PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

    Примечание

    Начиная с MySQL 5.7.22, POSTGRESQL устарел. Он удален в MySQL 8.0.

  • TRADITIONAL

    Перед 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_TABLES MySQL возвращает ошибку и игнорирует остальные строки. Однако, поскольку предыдущие строки были вставлены или обновлены, результат представляет собой частичное обновление. Чтобы избежать этого, используйте операторы для обработки одной строки, которые могут быть прерваны без изменения таблицы.

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

  • Эффект строгого режима 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 применяется к следующим операторам в условиях, когда некоторые значения могут быть вне диапазона или недействительная строка вставляется в таблицу или удаляется из нее:

  • ALTER TABLE

  • CREATE TABLE

  • CREATE TABLE ... SELECT

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

  • INSERT

  • LOAD DATA

  • LOAD XML

  • SELECT SLEEP()

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

Внутри хранимых программ отдельные операторы перечисленных типов выполняются в строгом режиме 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.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/sql-mode.html

Spec-Zone.ru

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