Глава 14. Синтаксис SQL

Эта глава описывает синтаксис для запросов SQL в MySQL.

14.1. Запросы определения данных

14.1.1. ALTER DATABASE

ALTER {DATABASE | SCHEMA} [db_name]
alter_specification ...

alter_specification:
[DEFAULT] CHARACTER SET [=] charset_name
    | [DEFAULT] COLLATE [=] collation_name
ALTER DATABASE позволяет Вам изменить полные характеристики базы данных. Эти характеристики сохранены в словаре данных. Чтобы использовать ALTER DATABASE, нужна привилегия ALTER на базе данных. ALTER SCHEMA синоним ALTER DATABASE .

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

Национальные языковые характеристики

CHARACTER SET изменяет набор символов базы данных по умолчанию. COLLATE изменяет сопоставление базы данных по умолчанию. Раздел 11.1 обсуждает имена сопоставления и набор символов.

Вы можете видеть, какие наборы символов и сопоставления доступны, соответственно, через SHOW CHARACTER SET и SHOW COLLATION. См. разделы 14.7.5.3 и 14.7.5.4.

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

14.1.2. ALTER EVENT

ALTER
[DEFINER = { user | CURRENT_USER }]
EVENT event_name
[ON SCHEDULE schedule]
[ON COMPLETION [NOT] PRESERVE]
[RENAME TO new_event_name]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
[DO event_body]
ALTER EVENT изменяет одну или больше характеристик существующего события без потребности обновить это. Синтаксис для DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE / DISABLE и DO точно тот же самый, как с CREATE EVENT. См. раздел 14.1.10.

Любой пользователь может изменить событие, определенное в базе данных, для которой этот пользователь имеет привилегию EVENT. Когда пользователь выполняет успешный запрос ALTER EVENT, этот пользователь становится определителем для затронутого события.

ALTER EVENT работает только с существующим событием:

mysql> ALTER EVENT no_such_event
     > ON SCHEDULE
     >    EVERY '2:3' DAY_HOUR;
ERROR 1517 (HY000): Unknown event 'no_such_event'
В каждом из следующих примеров, предположите, что событие называется myevent и определено, как показано здесь:
CREATE EVENT myevent ON SCHEDULE EVERY 6 HOUR
       COMMENT 'A sample comment.' DO
       UPDATE myschema.mytable SET mycol = mycol + 1;
Следующий запрос изменяет график для myevent с однажды каждые шесть часов с немедленным стартом на однажды каждые двенадцать часов, запускаясь четыре часа со времени выполнения запроса:
ALTER EVENT myevent ON SCHEDULE EVERY 12 HOUR
      STARTS CURRENT_TIMESTAMP + INTERVAL 4 HOUR;
Возможно изменить многократные характеристики в единственном запросе. Этот пример изменяет запрос SQL, выполненный myevent к тому, который удаляет все записи из mytable, это также изменяет график, таким образом, что это выполняется однажды, спустя один день после этого ALTER EVENT.
ALTER EVENT myevent ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
      DO TRUNCATE TABLE myschema.mytable;
Определите опции в ALTER EVENT только для тех характеристик, которые Вы хотите изменить, пропущенные опции сохраняют свои существующие значения. Это включает любые значения по умолчанию для CREATE EVENT, например, ENABLE.

Чтобы выключить myevent, используйте ALTER EVENT:

ALTER EVENT myevent DISABLE;
ON SCHEDULE может использовать выражения, вовлекающие встроенные функции MySQL и пользовательские переменные, чтобы получить любое из значений timestamp или interval, которые это содержит. Вы не можете использовать сохраненные подпрограммы или определяемые пользователем функции в таких выражениях, и Вы не можете использовать табличные ссылки, однако, Вы можете использовать SELECT FROM DUAL. Это верно для ALTER EVENT и CREATE EVENT. Ссылки на сохраненные подпрограммы, определяемые пользователем функции и таблицы в таких случаях определенно не разрешены и терпят неудачу с ошибкой (см. Bug #22830).

Хотя ALTER EVENT, который содержит другой ALTER EVENT в DO, кажется, преуспевает, когда сервер пытается запустить получающееся запланированное событие, выполнение терпит неудачу с ошибкой.

Чтобы переименовать событие, используйте ALTER EVENT RENAME TO. Это запрос переименовывает myevent в yourevent:

ALTER EVENT myevent RENAME TO yourevent;
Вы можете также переместить событие в иную базу данных через ALTER EVENT ... RENAME TO ... с db_name.event_name:
ALTER EVENT olddb.myevent RENAME TO newdb.myevent;
Чтобы выполнить предыдущий запрос, пользователь, выполняющий это, должен иметь привилегию EVENT на обоих базах данных olddb и newdb.

Запроса RENAME EVENT нет.

DISABLE ON SLAVE используется на ведомом устройстве вместо ENABLE или DISABLE, чтобы указать на событие, которое создавалось на ведущем устройстве и копировалось к ведомому устройству, но это не выполнено на ведомом устройстве. Обычно DISABLE ON SLAVE установлен автоматически как требуется, однако, есть некоторые обстоятельства, при которых Вы можете хотеть или должны изменить это вручную. См. раздел 19.4.1.12.

14.1.3. ALTER FUNCTION

ALTER FUNCTION func_name [characteristic ...]
characteristic:
COMMENT 'string'
  | LANGUAGE SQL
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
Это запрос может использоваться, чтобы изменить характеристики сохраненной функции. Больше чем одно изменение может быть определено в ALTER FUNCTION. Однако, Вы не можете изменить параметры или тело сохраненной функции, используя это запрос, чтобы произвести такие изменения, Вы должны обновить функцию через DROP FUNCTION и CREATE FUNCTION.

Вы должны иметь привилегию ALTER ROUTINE для функции (предоставляется автоматически создателю). Если двоичное журналирование включено, ALTER FUNCTION может также потребовать привилегию SUPER, см. раздел 21.7.

14.1.4. ALTER INSTANCE

ALTER INSTANCE ROTATE INNODB MASTER KEY
ALTER INSTANCE определяет действия, применимые к серверу MySQL. Требует привилегии SUPER .

ALTER INSTANCE ROTATE INNODB MASTER KEY используется для ротации основного ключа шифрования, используемого для InnoDB. Плагин keyring должен быть загружен, чтобы использовать этот запрос. По умолчанию сервер MySQL загружает плагин keyring_file.

ALTER INSTANCE ROTATE INNODB MASTER KEY поддерживает параллельный DML. Однако, это не может быть выполнено одновременно с CREATE TABLE ... ENCRYPTION или ALTER TABLE ... ENCRYPTION, и блокировки взяты, чтобы предотвратить конфликты, которые могли явиться результатом параллельного выполнения этих запросов. Если один из противоречивых запросов работает, он должен завершиться прежде, чем другой может продолжиться.

ALTER INSTANCE записан в двоичный журнал так, чтобы он мог быть выполнен на копируемых серверах.

14.1.5. ALTER PROCEDURE

ALTER PROCEDURE proc_name [characteristic ...]
characteristic:
COMMENT 'string'
  | LANGUAGE SQL
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
Этот запрос может использоваться, чтобы изменить характеристики хранимой процедуры. Больше чем одно изменение может быть определено в ALTER PROCEDURE. Однако, Вы не можете изменить параметры или тело хранимой процедуры, используя этот запрос, здесь нужно применить DROP PROCEDURE и CREATE PROCEDURE.

Вы должны иметь привилегию ALTER ROUTINE для процедуры. По умолчанию эту привилегию предоставляют автоматически создателю процедуры. Это поведение может быть изменено, отключая automatic_sp_privileges. См. раздел 21.2.2.

14.1.6. ALTER SERVER

ALTER SERVER  server_name
OPTIONS (option [, option] ...)
Меняет информацию сервера для server_name, корректируя любую из опций, разрешенных в CREATE SERVER. Соответствующие области в mysql.servers обновлены соответственно. Этот запрос требует привилегии SUPER.

Например, чтобы обновить USER:

ALTER SERVER s OPTIONS (USER 'sally');
ALTER SERVER не вызывает автоматическое завершение транзакции.

В MySQL 8.0 ALTER SERVER не записан в двоичный журнал, независимо от формата журналирования, который используется.

14.1.7. ALTER TABLE

ALTER TABLE tbl_name
[alter_specification [, alter_specification] ...]
[partition_options]

alter_specification:
table_options
  | ADD [COLUMN] col_name column_definition
[FIRST | AFTER col_name ]
  | ADD [COLUMN] (col_name column_definition,...)
  | ADD {INDEX|KEY} [index_name]
[index_type] (index_col_name,...) [index_option] ...
  | ADD [CONSTRAINT [symbol]] PRIMARY KEY
[index_type] (index_col_name,...) [index_option] ...
  | ADD [CONSTRAINT [symbol]]
UNIQUE [INDEX|KEY] [index_name]
[index_type] (index_col_name,...) [index_option] ...
  | ADD FULLTEXT [INDEX|KEY] [index_name]
(index_col_name,...) [index_option] ...
  | ADD SPATIAL [INDEX|KEY] [index_name]
(index_col_name,...) [index_option] ...
  | ADD [CONSTRAINT [symbol]]
FOREIGN KEY [index_name] (index_col_name,...)
reference_definition
  | ALGORITHM [=] {DEFAULT|INPLACE|COPY}
  | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  | CHANGE [COLUMN] old_col_name new_col_name column_definition
[FIRST|AFTER col_name]
  | LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
  | MODIFY [COLUMN] col_name column_definition
[FIRST | AFTER col_name]
  | DROP [COLUMN] col_name
  | DROP PRIMARY KEY
  | DROP {INDEX|KEY} index_name
  | DROP FOREIGN KEY fk_symbol
  | ALTER INDEX index_name {VISIBLE | INVISIBLE}
  | DISABLE KEYS
  | ENABLE KEYS
  | RENAME [TO|AS] new_tbl_name
  | RENAME {INDEX|KEY} old_index_name TO new_index_name
  | ORDER BY col_name [, col_name] ...
  | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
  | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]
  | DISCARD TABLESPACE
  | IMPORT TABLESPACE
  | FORCE
  | {WITHOUT|WITH} VALIDATION
  | ADD PARTITION (partition_definition)
  | DROP PARTITION partition_names
  | DISCARD PARTITION {partition_names | ALL} TABLESPACE
  | IMPORT PARTITION {partition_names | ALL} TABLESPACE
  | TRUNCATE PARTITION {partition_names | ALL}
  | COALESCE PARTITION number
  | REORGANIZE PARTITION partition_names INTO (partition_definitions)
  | EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH|WITHOUT} VALIDATION]
  | ANALYZE PARTITION {partition_names | ALL}
  | CHECK PARTITION {partition_names | ALL}
  | OPTIMIZE PARTITION {partition_names | ALL}
  | REBUILD PARTITION {partition_names | ALL}
  | REPAIR PARTITION {partition_names | ALL}
  | REMOVE PARTITIONING
  | UPGRADE PARTITIONING

index_col_name:
col_name [(length)] [ASC | DESC]

index_type:
USING {BTREE | HASH}

index_option:
KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}

table_options:
table_option [[,] table_option] ...
(см. опции CREATE TABLE)

partition_options:
(см. опции CREATE TABLE)
ALTER TABLE изменяет структуру таблицы. Например, Вы можете добавить или удалить столбцы, создать или разрушить индекс, изменить тип существующих столбцов, переименовать столбцы или таблицу непосредственно. Вы можете также изменить характеристики, такие как механизм хранения, используемый для таблицы или табличного комментария.

После имени таблицы, определите изменения, которые будут сделаны. Если ни одно не дано, ALTER TABLE ничего не делает.

Синтаксис для многих из допустимых изменений подобен параметрам CREATE TABLE. См. раздел 14.1.15.

table_options показывает табличные опции вида, который может использоваться в CREATE TABLE, например, ENGINE, AUTO_INCREMENT, AVG_ROW_LENGTH, MAX_ROWS, ROW_FORMAT или TABLESPACE. Для списка всех табличных опций и описания каждой см. раздел 14.1.15. Однако, ALTER TABLE игнорирует опции DATA DIRECTORY и INDEX DIRECTORY.

Использование табличных опций с ALTER TABLE обеспечивает удобный способ изменить единственные табличные характеристики. Например, если t1 сейчас не таблица InnoDB, этот запрос изменяет механизм хранения на InnoDB:

ALTER TABLE t1 ENGINE = InnoDB;
Изменить InnoDB, чтобы использовать на сжатый формат хранения строки:
ALTER TABLE t1 ROW_FORMAT = COMPRESSED;
Если опция шифрования табличного пространства активирована (см. раздел 16.7.10), шифрование для t1 может быть включено или отключено:
ALTER TABLE t1 ENCRYPTION='Y';
ALTER TABLE t1 ENCRYPTION='N';
Чтобы отключить шифрование для InnoDB, установите ENCRYPTION='N', используя ALTER TABLE.

Сбрасывать текущее значение auto-increment:

ALTER TABLE t1 AUTO_INCREMENT = 13;
Изменить табличный набор символов по умолчанию:
ALTER TABLE t1 CHARACTER SET = utf8;
Добавить (или изменить) табличный комментарий:
ALTER TABLE t1 COMMENT = 'New table comment';
Чтобы проверить, что табличные опции были изменены, удобно использовать SHOW CREATE TABLE.

partition_options показывает опции, которые могут использоваться с разделенными таблицами для того, чтобы повторно разделить, добавить, удалить, импортировать, слить и разделить разделение, и для того, чтобы выполнить обслуживание разделения. Это возможно для ALTER TABLE, который включает параметр PARTITION BY или REMOVE PARTITIONING, который должен быть определен последним после любых других технических требований. ADD PARTITION, DROP PARTITION, DISCARD PARTITION, IMPORT PARTITION, COALESCE PARTITION, REORGANIZE PARTITION, EXCHANGE PARTITION, ANALYZE PARTITION, CHECK PARTITION и REPAIR PARTITION не могут быть объединены с другими изменениями технических требований в ALTER TABLE, так как опции только перечислены на отдельном разделе. Для получения дополнительной информации об опциях разделения см. разделы 14.1.15 и 14.1.7.1.

До MySQL 5.7.6 разделенные таблицы InnoDB использовали непатентованное средство ha_partition в качестве обработчика, используемого MyISAM и другими механизмами хранения, не поставляющих их собственные обработчики разделения, в MySQL 5.7.6 и позже такие таблицы составлены, используя собственный обработчик механизма хранения InnoDB. После MySQL 5.7.9 Вы можете обновить таблицу InnoDB, которая была составлена в MySQL 5.7.6 или ранее (то есть, с ha_partition) на InnoDB, используя ALTER TABLE ... UPGRADE PARTITIONING (Bug #76734, Bug #20727344). Эта версия ALTER TABLE не принимает никакие другие опции и может использоваться только на единственной таблице за один раз.

Вы можете также использовать mysql_upgrade, чтобы обновить более старые разделенные таблицы InnoDB.

Некоторые операции могут привести к предупреждениям, если предприняты на таблице, для которой механизм хранения не поддерживает такую работу. Эти предупреждения могут быть выведены на экран SHOW WARNINGS. См. раздел 14.7.5.40.

Для информации о поиске неисправностей ALTER TABLE см. раздел B.5.6.1.

Хранение, работа и соображения параллелизма

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

Исключение, упомянутое ранее, это блокировка чтения ALTER TABLE (не только записи) в пункте, где это готово очистить устаревшие структуры таблиц от таблицы и табличных кэшей определения. В этом пункте это должно приобрести исключительную блокировку. Чтобы сделать так, это ждет завершения текущих чтений и блокирует новые чтения и записи.

Для таблиц MyISAM Вы можете убыстрить воссоздание индекса (самая медленная часть процесса изменения), устанавливая к высокому значению myisam_sort_buffer_size.

Для некоторых операций, оперативное выполнение ALTER TABLE возможно, которое не требует временной таблицы:

Вы можете предписать ALTER TABLE работу, которая иначе не потребовалась бы, чтобы табличная копия использовала временный табличный метод (как поддержано в MySQL 5.0), устанавливая old_alter_table в ON, или указав параметр ALGORITHM=COPY в alter_specification. Если есть конфликт между old_alter_table и параметром ALGORITHM со значением кроме DEFAULT, ALGORITHM имеет приоритет. ALGORITHM=DEFAULT аналогичен отсутствию ALGORITHM вовсе.

Определение ALGORITHM=INPLACE заставляет использовать оперативный метод для пунктов и механизмов хранения, которые поддерживают это, и приводит к ошибке иначе, таким образом избегая длинной табличной копии, если Вы пытаетесь изменить таблицу, которая использует иной механизм хранения, чем Вы ожидаете. См. раздел 16.12.

Для таблиц InnoDB копирование ALTER TABLE на таблице, которая находится в совместно используемом табличном пространстве, таком как общее табличное пространство или системное табличное пространство может увеличить количество пространства, использованного табличным пространством. Такие операции требуют такого большого количества дополнительного пространства, как данные в таблице плюс индекс. Для таблицы, которая находится в совместно используемом табличном пространстве, дополнительное пространство, используемое во время копирования таблицы ALTER TABLE не выпущено назад к операционной системе, как для таблицы, которая находится в табличном пространстве file-per-table.

С MySQL 5.7.4 ALTER TABLE обновляет временные столбцы MySQL 5.5 до формата 5.6 для ADD COLUMN, CHANGE COLUMN, MODIFY COLUMN, ADD INDEX и FORCE. Это преобразование не может быть сделано, используя алгоритм INPLACE, потому что таблица должна быть восстановлена, таким образом, определение ALGORITHM=INPLACE в этих случаях приводит к ошибке. Определите ALGORITHM=COPY в случае необходимости.

С MySQL 5.7.6 ALTER TABLE на многостолбцовом индексе используемом, чтобы разделить таблицу по KEY не может быть выполнен онлайн, когда работа изменила бы порядок столбцов. В таких случаях Вы должны использовать копирование ALTER TABLE (Bug #17896265).

Вы можете управлять уровнем параллельного чтения и записи таблицы, в то время как это изменяется, используя параметр LOCK. Определение значения не по умолчанию для этого пункта позволяет Вам требовать определенного количества параллельного доступа или исключительности во время изменений и останавливает работу, если требуемая степень блокировки недоступна. Параметры для LOCK:

WITHOUT VALIDATION и WITH VALIDATION затрагивают ALTER TABLE, если он выполняет оперативную работу для модификаций произведенных виртуальных столбцов. См. раздел 14.1.7.2.

Вы можете также использовать ALTER TABLE tbl_name FORCE, чтобы выполнить null-работу, которая восстанавливает таблицу. Для получения дополнительной информации см. раздел 16.12.1.

Примечания использования

С функцией mysql_info() C API Вы можете узнать, сколько было скопировано строк ALTER TABLE. См. раздел 25.8.7.36.

14.1.7.1. Операции разделения ALTER TABLE

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

ALTER TABLE может содержать PARTITION BY или REMOVE PARTITIONING в дополнении к другим изменениям технических требований, но PARTITION BY или REMOVE PARTITIONING должен быть определен последний после любых других технических требований.

ADD PARTITION, DROP PARTITION, COALESCE PARTITION, REORGANIZE PARTITION, ANALYZE PARTITION, CHECK PARTITION и REPAIR PARTITION не могут быть объединены с другими изменениями технических требований в ALTER TABLE. Для получения дополнительной информации см. раздел 14.1.7.1.

Только единственный случай любой из следующих опций может использоваться в данном ALTER TABLE: PARTITION BY, ADD PARTITION, DROP PARTITION, TRUNCATE PARTITION, EXCHANGE PARTITION, REORGANIZE PARTITION или COALESCE PARTITION, ANALYZE PARTITION, CHECK PARTITION, OPTIMIZE PARTITION, REBUILD PARTITION, REMOVE PARTITIONING.

Например, следующие два запроса недопустимы:

ALTER TABLE t1 ANALYZE PARTITION p1, ANALYZE PARTITION p2;
ALTER TABLE t1 ANALYZE PARTITION p1, CHECK PARTITION p2;
В первом случае Вы можете проанализировать разделы p1 и p2 табьлицы t1 одновременно, используя единственный запрос ANALYZE PARTITION, который перечисляет оба раздела, что будет проанализировано так:
ALTER TABLE t1 ANALYZE PARTITION p1, p2;
Во втором случае невозможно сделать ANALYZE и CHECK на разных разделах той же самой таблицы одновременно. Вместо этого Вы должны сделать два отдельных запроса:
ALTER TABLE t1 ANALYZE PARTITION p1;
ALTER TABLE t1 CHECK PARTITION p2;
REBUILD в настоящее время не поддерживаются для подразделения. REBUILD явно отвергнуто с подразделением, и ALTER TABLE выдаст ошибку.

CHECK PARTITION и REPAIR PARTITION терпят неудачу, когда разделение, которое будет проверено или восстановлено, содержит любые ошибки дубликата ключа.

См. раздел 20.3.4.

14.1.7.2. ALTER TABLE и произведенные столбцы

Действия ALTER TABLE, разрешенные для произведенных столбцов: ADD, MODIFY и CHANGE.

14.1.7.3. Примеры ALTER TABLE

Начните с таблицы t1. Она создается как показано здесь:

CREATE TABLE t1 (a INTEGER,b CHAR(10));
Переименуем ее из t1 в t2:
ALTER TABLE t1 RENAME t2;
Изменить столбец a с INTEGER на TINYINT NOT NULL (имя то же самое) и изменить столбец b с CHAR(10) на CHAR(20) с переименованием этого с b на c:
ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
Добавить новый столбец TIMESTAMP d:
ALTER TABLE t2 ADD d TIMESTAMP;
Добавить индексирование на столбце d и индекс UNIQUE на a:
ALTER TABLE t2 ADD INDEX (d), ADD UNIQUE (a);
Удалить столбец c:
ALTER TABLE t2 DROP COLUMN c;
Добавить новый столбец AUTO_INCREMENT целого числа c:
ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
      ADD PRIMARY KEY (c);
Мы индексировали c (как PRIMARY KEY), потому что столбцы AUTO_INCREMENT должны быть индексированы, и мы объявляем c как NOT NULL, потому что столбцы первичного ключа не могут быть NULL.

Когда Вы добавляете AUTO_INCREMENT, значения столбцов заполнены порядковыми номерами автоматически. Для таблиц MyISAM Вы можете установить первый порядковый номер, выполняя SET INSERT_ID=value до ALTER TABLE или используя опцию таблицы AUTO_INCREMENT=value. См. раздел 6.1.5.

С MyISAM если Вы не изменяете столбец AUTO_INCREMENT, порядковый номер не затронут. Если Вы удаляете AUTO_INCREMENT и затем добавляете другой столбец AUTO_INCREMENT, числа повторно упорядочены, начиная с 1.

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

CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY)
SELECT * FROM t1 ORDER BY col1, col2;
Это предполагает, что таблица t1 имеет столбцы col1 и col2.

Этот набор запросов также произведет новую таблицу t2, идентичную t1, с добавлением столбца AUTO_INCREMENT:

CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY;
INSERT INTO t2 SELECT * FROM t1 ORDER BY col1, col2;

Гарантировать то же самое упорядочивание на ведущем устройстве и на ведомом устройстве всех столбцов t1 можно, указанием в ORDER BY.

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

DROP TABLE t1;
ALTER TABLE t2 RENAME t1;

14.1.8. ALTER VIEW

ALTER
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
Этот запрос изменяет определение представления, которое должно существовать. Синтаксис подобен CREATE VIEW, эффект тот же самый, как для CREATE OR REPLACE VIEW. См. раздел 14.1.18. Это запрос требует привилегий CREATE VIEW и DROP для представления и некоторой привилегии для каждого столбца, упомянутого в SELECT. ALTER VIEW разрешен только определителю или пользователям с привилегией SUPER.

14.1.9. CREATE DATABASE

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...

create_specification:
[DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name
CREATE DATABASE создает базу данных с именем. Чтобы использовать этот запрос, Вы нуждаетесь в привилегии CREATE для базы данных. CREATE SCHEMA это синоним для CREATE DATABASE .

Ошибка происходит, если база данных существует, и Вы не определяли IF NOT EXISTS.

В MySQL 8.0 CREATE DATABASE не разрешен в пределах сеанса, у которого есть активный LOCK TABLES.

create_specification определяют характеристики базы данных. Характеристики базы данных сохранены в словаре данных. CHARACTER SET определяет набор символов базы данных по умолчанию. COLLATE определяет сопоставление базы данных по умолчанию. Раздел 11.1 обсуждает имена сопоставления и набора символов.

База данных в MySQL осуществлена как каталог, содержащий файлы, которые соответствуют таблицам в базе данных. Поскольку нет никаких таблиц в базе данных, когда это первоначально создается, CREATE DATABASE создает только каталог в соответствии с каталогом данных MySQL. Правила для допустимых имен базы данных даны в разделе 10.2. Если имя базы данных содержит специальные символы, название каталога базы данных содержит закодированные версии тех символов как описано в разделе 10.2.3.

Создание каталога базы данных, вручную создавая каталог в соответствии с каталогом данных (например, с помощью mkdir) временно не поддержано в MySQL 8.0.0.

Вы можете также использовать mysqladmin, чтобы создать базы данных. См. раздел 5.5.2.

14.1.10. CREATE EVENT

CREATE
[DEFINER = { user | CURRENT_USER }]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO event_body;

schedule:
AT timestamp [+ INTERVAL interval] ...
  | EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]

interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
  WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
  DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
Этот запрос создает и намечает новое событие. Оно не будет работать, если Планировщик Событий не будет включен. Для информации о проверке состояния Планировщика Событий и включении в случае необходимости см. раздел 21.4.2.

CREATE EVENT требует привилегию EVENT для схемы, в которой должно быть создано событие. Это могло бы также потребовать привилегию SUPER , в зависимости от значения DEFINER, как описано позже в этом разделе.

Минимальные требования для допустимого CREATE EVENT:

Это пример минимального CREATE EVENT :

CREATE EVENT myevent ON SCHEDULE
       AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
       DO UPDATE myschema.mytable SET mycol = mycol + 1;
Предыдущий запрос создает событие myevent. Это выполняется однажды в один час после его создания, выполняя запрос SQL, который постепенно увеличивает значение столбца mycol в таблице myschema.mytable на 1.

event_name должен быть допустимым идентификатором MySQL с максимальной длиной 64 символа. Имена событий не являются чувствительными к регистру, таким образом, у Вас не может быть двух событий, названных myevent и MyEvent в той же самой схеме. Вообще, правила, управляющие именами событий, являются теми же самыми, как для названий сохраненных подпрограмм. См. раздел 10.2.

Событие связано со схемой. Если никакая схема не обозначена как часть event_name, значение по умолчанию (текущая схема) принято. Чтобы создать событие в определенной схеме, квалифицируйте имя события с использованием имени схемы schema_name.event_name .

DEFINER определяет учетную запись MySQL, которая будет использоваться, проверяя привилегии доступа во время выполнения событий. Если user дано, это должна быть учетная запись MySQL, определенная как 'user_name'@'host_name ', CURRENT_USER или CURRENT_USER(). Значение по умолчанию DEFINER: пользователь, который выполняет CREATE EVENT. Это то же самое, как определение DEFINER = CURRENT_USER.

Если Вы определяете DEFINER, эти правила определяют допустимые пользовательские значения DEFINER:

См. раздел 21.6.

В пределах события CURRENT_USER() возвращает учетную запись для проверки привилегии во время выполнения события, то есть DEFINER. См. раздел 7.3.12.

IF NOT EXISTS для CREATE EVENT имеет тот же смысл, как для CREATE TABLE: если событие уже существует в той же самой схеме, никакие меры не предприняты и никакой ошибки нет. (днако, предупреждение будет произведено в таких случаях.

ON SCHEDULE определяет когда, как часто, и как долго event_body определен для повторений событий. Этот пункт принимает одну из двух форм:

ON SCHEDULE может использовать выражения, вовлекающие встроенные функции MySQL и пользовательские переменные, чтобы получить любое из значений timestamp или interval , которые это содержит. Вы не можете использовать сохраненные функции или определяемые пользователем функции в таких выражениях, и при этом Вы не можете использовать табличные ссылки, однако, Вы можете использовать SELECT FROM DUAL. Это верно для CREATE EVENT и ALTER EVENT. Ссылки на сохраненные функции, определяемые пользователем функции и таблицы в таких случаях определенно не разрешены и терпят неудачу с ошибкой (Bug #22830).

Времена в ON SCHEDULE интерпретируются, используя значение time_zone текущего сеанса. Это становится часовым поясом событий, то есть, часовой пояс, который используется для планирования события, является текущим в пределах события при выполнении. Эти времена преобразованы в UTC и сохранены наряду с часовым поясом событий в таблице mysql.event. Это позволяет выполнению событий продолжиться как определено, независимо от любых последующих изменений часового пояса сервера или эффектов летнего времени. Для дополнительной информации о представлении времен событий см. раздел 21.4.4. См. также разделы 14.7.5.18 и 22.7.

Обычно как только событие истекло, оно немедленно удалено. Вы можете переопределить это поведение, определяя ON COMPLETION PRESERVE. Использование ON COMPLETION NOT PRESERVE просто делает поведение по умолчанию явным.

Вы можете создать событие, но препятствовать тому, чтобы это было активно, использованием ключевого слова DISABLE. Альтернативно, Вы можете использовать ENABLE, чтобы сделать явным состояние значения по умолчанию, которое является активным. Это является самым полезным в соединении с ALTER EVENT (см. раздел 14.1.2).

Третье значение может также появиться вместо ENABLE или DISABLE: DISABLE ON SLAVE установлен для состояния события на ведомом устройстве, чтобы указать, что событие создавалось на ведущем устройстве и копировалось к ведомому устройству, но не запущено на ведомом устройстве. См. раздел 19.4.1.12.

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

DO определяет действие, которое выполняет событие, и состоит из запросов SQL. Почти любой допустимый запрос MySQL, который может использоваться в сохраненной подпрограмме, может также использоваться в качестве действия для запланированного события, см. раздел C.1. Например, следующее событие e_hourly удаляет все строки из таблицы sessions однажды в час, где эта таблица является частью схемы site_activity:

CREATE EVENT e_hourly ON SCHEDULE
       EVERY 1 HOUR COMMENT 'Clears out sessions table each hour.'
       DO DELETE FROM site_activity.sessions;
MySQL хранит sql_mode, когда событие создано или изменено, и всегда запускает событие с этой установкой в силе, независимо от текущего режима SQL сервера, когда событие начинает выполняться.

CREATE EVENT, который содержит ALTER EVENT в DO, кажется, преуспевает, однако, когда сервер пытается запустить получающееся запланированное событие, выполнение терпит неудачу с ошибкой.

Такие запросы, как SELECT или SHOW, которые просто возвращают набор результатов, не имеют никакого эффекта, когда используются в событии: вывод от них не посылают MySQL Monitor, и при этом он не сохранен нигде. Однако, Вы можете использовать такие запросы, как SELECT ... INTO и INSERT INTO ... SELECT, которые сохраняют результат. См. следующий пример в этом разделе для последнего случая.

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

Как с сохраненными подпрограммами, Вы можете использовать синтаксис составного запроса DO с ключевыми словами BEGIN и END:

delimiter |

CREATE EVENT e_daily
ON SCHEDULE
   EVERY 1 DAY
COMMENT 'Saves total number of sessions then clears the table each day'
DO BEGIN
  INSERT INTO site_activity.totals (time, total)
  SELECT CURRENT_TIMESTAMP, COUNT(*) FROM site_activity.sessions;
  DELETE FROM site_activity.sessions;
END |

delimiter ;
Этот пример использует команду delimiter, чтобы изменить разделитель запроса. См. раздел 21.1.

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

delimiter |

CREATE EVENT e
ON SCHEDULE
   EVERY 5 SECOND
DO BEGIN
   DECLARE v INTEGER;
   DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
   SET v = 0;
   WHILE v < 5 DO
     INSERT INTO t1 VALUES (0);
     UPDATE t2 SET s1 = s1 + 1;
     SET v = v + 1;
  END WHILE;
END |

delimiter ;
Нет никакого способа передать параметры непосредственно к или от событий, однако, возможно вызвать сохраненную подпрограмму с параметрами в пределах события:
CREATE EVENT e_call_myproc
ON SCHEDULE
   AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
DO CALL myproc(5, 27);
Если определитель имеет привилегию SUPER, событие может читать и писать глобальные переменные. Поскольку предоставление этой привилегии влечет за собой потенциал для злоупотребления, экстремальная забота должна быть проявлена при этом.

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

14.1.11. CREATE FUNCTION

CREATE FUNCTION используется, чтобы создать сохраненные функции и определяемые пользователем функции (UDF):

14.1.12. CREATE INDEX

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[index_type]
ON tbl_name (index_col_name,...)
[index_option]
[algorithm_option | lock_option] ...

index_col_name:
col_name [(length)] [ASC | DESC]

index_type:
USING {BTREE | HASH}

index_option:
KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}

algorithm_option:
ALGORITHM [=] {DEFAULT|INPLACE|COPY}

lock_option:
LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
CREATE INDEX отображен на ALTER TABLE, чтобы создать индекс. См. раздел 14.1.7. CREATE INDEX не может использоваться, чтобы создать PRIMARY KEY, используйте ALTER TABLE. См. раздел 9.3.1.

Обычно Вы создаете все индексы на таблице в то время, когда таблица составлена с CREATE TABLE. См. раздел 14.1.15. Это особенно важно для InnoDB, где первичный ключ определяет физическое расположение строк в файле с данными. CREATE INDEX позволяет добавить индекс к существующим таблицам.

Список столбцов формы (col1,col2,...) создает многостолбцовый индекс, значения ключа, сформированы, связывая значения данных столбцов.

Для строковых столбцов может быть создан индекс, который использует только ведущую часть значений столбцов, используя col_name(length), чтобы определить длину префикса:

Запрос, показанный здесь, создает индекс с использованием первых 10 символов столбца name (принимая, что name имеет недвоичной строковый тип):

CREATE INDEX part_of_name ON customer (name(10));
Если имена в столбце обычно отличаются по первым 10 символам, это не должно быть намного медленнее, чем индекс, создаваемый из всего name. Кроме того, использование приставок столбца для индекса может сделать индексный файл намного меньшим, что может сохранить много дискового пространства и может также убыстрить INSERT.

Поддержка префиксов и длины (где поддержано) зависят от механизма хранения. Например, приставка может составить до 767 байтов для InnoDB, которые используют формат строки REDUNDANT или COMPACT. Предел длины поднят до 3072 байтов для таблиц InnoDB, которые используют формат строки DYNAMIC или COMPRESSED . Для MyISAM предел префикса составляет 1000 байтов.

Индекс UNIQUE создает ограничение, таким образом, что все значения в индексе должны быть отличными. Ошибка происходит, если Вы пытаетесь добавить новую строку со значением ключа, которое соответствует существующей строке. Для всех механизмов UNIQUE допускает многократные NULL для столбцов, которые могут содержать NULL. Если Вы определяете префикс столбца в UNIQUE, значения столбцов должны быть уникальными в пределах префикса.

FULLTEXT поддержаны только для InnoDB и MyISAM и могут включать только столбцы CHAR, VARCHAR и TEXT. Индексация всегда происходит по всему столбцу. Префиксы столбца не поддержаны, любая длина префикса проигнорирована, если определена. См. раздел 13.9.

MyISAM, InnoDB, NDB и ARCHIVE поддерживают пространственные столбцы, например, POINT и GEOMETRY. См. раздел 12.5. Однако, поддержка пространственной индексации столбца изменяется среди механизмов. Пространственный и непространственный индексы доступны, согласно следующим правилам.

Пространственный индекс (создаваемый использованием SPATIAL INDEX) имееет эти характеристики:

Характеристики непространственных индексов (создаваемых с INDEX, UNIQUE или PRIMARY KEY):

InnoDB допускает вторичные индексы на виртуальных столбцах. Для получения дополнительной информации см. раздел 14.1.15.6.

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

После списка столбцов индекса могут быть даны опции. Значение index_option может быть любым следующим:

ALGORITHM и LOCK могут быть даны, чтобы влиять на табличный метод копирования и уровень параллелизма для чтения и записи таблицы в то время, как индексы изменяются. У них есть то же самое значение, что в ALTER TABLE. См. раздел 14.1.7

14.1.13. CREATE PROCEDURE и CREATE FUNCTION

CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body

CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body

proc_parameter:
[ IN | OUT | INOUT ] param_name type

func_parameter:
param_name type

type:
Any valid MySQL data type

characteristic:
COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }

routine_body:
Valid SQL routine statement
Эти запросы создают сохраненные подпрограммы. По умолчанию подпрограмма связана с базой данных значения по умолчанию. Чтобы связать подпрограмму явно с данной базой данных, определите имя как db_name.sp_name, когда Вы создаете это.

CREATE FUNCTION также используется в MySQL, чтобы поддержать UDF (определяемые пользователем функции). См. раздел 26.4. UDF может быть расценен как внешняя сохраненная функция. Сохраненные функции совместно используют свое пространство имен с UDF. См. раздел 10.2.4.

Чтобы вызвать хранимую процедуру, используйте CALL (см. раздел 14.2.1). Чтобы вызвать сохраненную функцию, обратитесь к ней в выражении. Функция возвращает значение во время оценки выражения.

CREATE PROCEDURE и CREATE FUNCTION требуют привилегию CREATE ROUTINE . Они могли бы также потребовать привилегию SUPER, в зависимости от значения DEFINER, как описано позже в этом разделе. Если двоичное журналирование включено, CREATE FUNCTION может потребовать привилегию SUPER, см. раздел 21.7.

По умолчанию MySQL автоматически предоставляет привилегии ALTER ROUTINE и EXECUTE создателю подпрограммы. Это поведение может быть изменено, отключая automatic_sp_privileges. См. раздел 21.2.2.

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

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

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

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

Каждый параметр IN это параметр по умолчанию. Чтобы определить иное для параметра, используйте ключевое слово OUT или INOUT перед названием параметра.

Определение параметра как IN, OUT или INOUT допустимо только для PROCEDURE. Для FUNCTION параметры всегда расцениваются как IN.

IN передает значение в процедуру. Процедура могла бы изменить значение, но модификация не видна вызывающему, когда процедура возвращается. OUT передает значение из процедуры назад. Его начальное значение NULL в пределах процедуры, и значение видимо вызывающему, когда процедура возвращается. INOUT инициализирован вызывающим, может быть изменен процедурой, и любое изменение, произведенное процедурой, видимо вызывающему, когда процедура возвращается.

Для каждого OUT или INOUT передайте определяемую пользователем переменную в CALL, которое вызывает процедуру так, чтобы Вы могли получить ее значение, когда процедура возвращается. Если Вы вызываете процедуру изнутри другой хранимой процедуры или функции, Вы можете также передать параметр или местную переменную как IN или INOUT.

На параметры нельзя сослаться в запросах, подготовленных в пределах подпрограммы, см. раздел C.1 .

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

mysql> delimiter //

mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
    -> BEGIN
    ->   SELECT COUNT(*) INTO param1 FROM t;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @a;
+----+
| @a |
+----+
| 3  |
+----+
1 row in set (0.00 sec)
Пример использует команду delimiter, чтобы изменить разделитель запросов с ; на // в то время, как процедура определяется. Это позволяет разделитель ;, используемый в теле процедуры, который пройдет к серверу вместо того, чтобы интерпретироваться mysql. См. раздел 21.1.

RETURNS может быть определен только для FUNCTION, для которой это принудительно. Это указывает на тип возврата функции, и функциональное тело должно содержать команду RETURN value. Если RETURN возвращает значение иного типа, значение приведено к надлежащему типу. Например, если функция определяет ENUM или SET в RETURNS, но RETURN возвращает целое число, значение, возвращенное из функции, является строкой для передачи члена ENUM или SET.

Следующая функция в качестве примера берет параметр, выполняет работу, используя функцию SQL, и возвращает результат. В этом случае не нужно использовать delimiter, потому что функциональное определение не содержит внутренний ;:

mysql> CREATE FUNCTION hello (s CHAR(20))
mysql> RETURNS CHAR(50) DETERMINISTIC
    -> RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world!  |
+----------------+
1 row in set (0.00 sec)
Типы параметра и функциональные типы возвращения используют любой допустимый тип данных. COLLATE может использоваться, если предшествующий признак CHARACTER SET.

routine_body состоит из допустимых запросов SQL. Это может быть простым запросом, например, SELECT или INSERT, или составным запросом с BEGIN и END. Составные запросы могут содержать декларации, циклы и другие проверки утверждения структуры. Синтаксис для этих запросов описан в разделе 14.6.

MySQL разрешает подпрограммам содержать запросы DDL, такие как CREATE и DROP. MySQL также разрешает хранимым процедурам (но не сохраненным функциям) содержать операционные запросы SQL, такие как COMMIT. Сохраненные функции, возможно, не содержат запросы, которые явно или неявно закрывают транзакцию. Поддержка этих запросов не требуется стандартом SQL, который заявляет, что каждый поставщик системы управления базами данных может решить, разрешить ли их.

Запросы, которые возвращают набор результатов, могут использоваться в пределах хранимой процедуры, но не в пределах сохраненной функции. Этот запрет включает SELECT, которые не имеют INTO var_list, и другие запросы, например, SHOW, EXPLAIN и CHECK TABLE. Для запросов, которые могут возвратить набор результатов, происходит ошибка Not allowed to return a result set from a function (ER_SP_NO_RETSET). Для запросов, которые могут во времени выполнения возвратить набор результатов, происходит ошибка PROCEDURE %s can't return a result set in the given context ( ER_SP_BADSELECT).

USE в пределах сохраненных подпрограмм не разрешены. Когда подпрограмма вызвана, неявный USE db_name выполнен (и отменен, когда подпрограмма заканчивается). Это сделано, чтобы иметь базу данных по умолчанию, в то время как подпрограмма выполняется. Ссылки на объекты в базах данных кроме базы данных значения по умолчанию должны быть квалифицированы с соответствующим именем базы данных.

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

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

COMMENT расширение MySQL, и может использоваться, чтобы описать сохраненную подпрограмму. Эта информация выведена на экран SHOW CREATE PROCEDURE и SHOW CREATE FUNCTION .

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

Подпрограмму считают deterministic, если это всегда приводит к тому же самому результату для тех же самых входных параметров, и not deterministic иначе. Если ни один из параметров DETERMINISTIC или NOT DETERMINISTIC не задн в определении, значение по умолчанию NOT DETERMINISTIC. Чтобы объявить, что функция детерминирована, Вы должны определить DETERMINISTIC явно.

Оценка природы подпрограммы основана на honesty создателя: MySQL не проверяет, что подпрограмма, объявленная DETERMINISTIC, свободна от запросов, которые приводят к недетерминированным результатам. Однако, DETERMINISTIC подпрограмма могла бы затронуть результаты. Объявление недетерминированной подпрограммы как NONDETERMINISTIC может привести к неожиданным результатам, заставляя оптимизатор сделать неправильный выбор плана выполнения. Объявление детерминированной подпрограммы как NONDETERMINISTIC могло бы уменьшить работу, заставляя доступную оптимизацию не использоваться.

Если двоичное журналирование включено, DETERMINISTIC влияет на обработку определений подпрограмм MySQL. См. раздел 21.7.

Подпрограмма, которая содержит NOW() (возможно, синонимы) или RAND() недетерминирована, но это может быть безопасно для репликации. Для NOW() двоичной журнал включает timestamp и копирует правильно. RAND() также копирует правильно, пока вызывается только единственный раз во время выполнения подпрограммы. Вы можете рассмотреть timestamp и случайное число как неявные вводы, которые идентичны на ведущем и ведомом устройствах.

Несколько характеристик предоставляют информацию о природе использования данных подпрограммой. В MySQL эти характеристики только консультация. Сервер не использует их, чтобы ограничить, какие виды запросов подпрограмме разрешат выполнить.

SQL SECURITY может быть DEFINER или INVOKER, чтобы определить контекст безопасности, то есть, выполняет ли подпрограмма использование привилегий учетной записи, названной в подпрограмме DEFINER или пользователя, который вызывает. У этой учетной записи должно быть разрешение получить доступ к базе данных, с которой связана подпрограмма. Значение по умолчанию DEFINER. Пользователь, который вызывает подпрограмму, должен иметь привилегию EXECUTE для этого.

DEFINER определяет учетную запись MySQL, которая будет использоваться, проверяя привилегии доступа во время выполнения для подпрограмм, которые имеют SQL SECURITY DEFINER.

Если значение user дано для DEFINER, это должна быть учетная запись MySQL, определенная как 'user_name'@'host_name' , CURRENT_USER или CURRENT_USER() . По умолчанию DEFINER это пользователь, который выполняет CREATE PROCEDURE или CREATE FUNCTION. Это то же самое, как определение DEFINER = CURRENT_USER явно.

Если Вы определяете DEFINER, эти правила определяют допустимые пользовательские значения DEFINER:

См. раздел 21.6.

В пределах сохраненной подпрограммы, которая определена с SQL SECURITY DEFINER, CURRENT_USER возвращает значение DEFINER. Для информации об аудите пользователей в пределах сохраненных подпрограмм см. раздел 7.3.12.

Рассмотрите следующую процедуру, которая выводит на экран количество учетных записей MySQL, перечисленных в mysql.user:

CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
BEGIN
  SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
Процедуре назначают DEFINER = 'admin'@'localhost', независимо от того, какой пользователь определяет это. Это выполняется с привилегиями той учетной записи, независимо от того, какой пользователь вызывает это (потому что характеристика безопасности по умолчанию DEFINER). Процедура преуспевает или терпит неудачу в зависимости от того, имеет ли вызывающий привилегию EXECUTE для нее, и имеет ли 'admin'@'localhost' привилегию SELECT на таблице mysql.user.

Теперь предположите, что процедура определена с SQL SECURITY INVOKER:

CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
SQL SECURITY INVOKER
BEGIN
  SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
У процедуры все еще есть DEFINER = 'admin'@'localhost', но в этом случае, это выполняется с привилегиями пользователя вызова. Таким образом, процедура преуспевает или терпит неудачу в зависимости от того, имеет ли вызывающий привилегию EXECUTE для нее и привилегию SELECT для таблицы mysql.user.

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

14.1.14. CREATE SERVER

CREATE SERVER server_name
FOREIGN DATA WRAPPER wrapper_name
OPTIONS (option [, option] ...)

option:
  { HOST character-literal
  | DATABASE character-literal
  | USER character-literal
  | PASSWORD character-literal
  | SOCKET character-literal
  | OWNER character-literal
  | PORT numeric-literal }
Это запрос создает определение сервера для использования с механизмом хранения FEDERATED. CREATE SERVER создает новую строку в таблице servers базы данных mysql. Этот запрос требует привилегии SUPER.

server_name должен быть уникальной ссылкой на сервер. Определения сервера глобальны в рамках сервера, невозможно квалифицировать определение сервера для определенной базы данных. server_name имеет максимальную длину 64 символов (имена длиннее 64 символов являются тихо усеченными), и нечувствительно к регистру. Вы можете определить имя как заключенную в кавычки строку.

wrapper_name должен быть mysql, может быть заключен в кавычки с единственными кавычками. Другие значения для wrapper_name в настоящее время не поддерживаются.

Для каждой option Вы должны определить символьный или числовой литерал. Символьные литералы UTF-8 поддерживают максимальную длину 64 символа и значение по умолчанию пустая строка. Строковые литералы являются тихо усеченными к 64 символам. Числовые должны быть числом между 0 и 9999, по умолчанию 0.

OWNER в настоящее время не применяется и не имеет никакого эффекта на собственность или работу соединения сервера, которое создается.

CREATE SERVER создает запись в таблице mysql.servers, которая может позже использоваться с CREATE TABLE, создавая таблицу FEDERATED. Опции, которые Вы определяете, будут использоваться, чтобы заполнить столбцы в mysql.servers. Столбцы таблицы: Server_name, Host, Db, Username, Password, Port и Socket.

Например:

CREATE SERVER s FOREIGN DATA WRAPPER mysql
       OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test');
Убедитесь, что определили все опции, необходимые, чтобы установить соединение с сервером. Имя пользователя, имя хоста и имя базы данных принудительны. Другие опции, такие как пароль, могли бы требоваться также.

Данные в таблице могут использоваться, создавая соединение с таблицей FEDERATED:

CREATE TABLE t (s1 INT) ENGINE=FEDERATED CONNECTION='s';
См. раздел 17.8.

CREATE SERVER автоматически закрывает транзакцию.

В MySQL 8.0 CREATE SERVER не записан в двоичный журнал, независимо от формата журналирования, который используется.

14.1.15. CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
(create_definition,...)
[table_options]
[partition_options]

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options]
[partition_options]
[IGNORE | REPLACE]
[AS] query_expression

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
{ LIKE old_tbl_name | (LIKE old_tbl_name) }

create_definition:
col_name column_definition
  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
  [index_option] ...
  | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
  [index_option] ...
  | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
  [index_name] [index_type] (index_col_name,...)
  [index_option] ...
  | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)
  [index_option] ...
  | [CONSTRAINT [symbol]] FOREIGN KEY
  [index_name] (index_col_name,...) reference_definition
  | CHECK (expr)

column_definition:
data_type [NOT NULL | NULL] [DEFAULT default_value]
  [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
  [COMMENT 'string']
  [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]
  [reference_definition]
  | data_type [GENERATED ALWAYS] AS (expression)
  [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
  [NOT NULL | NULL] [[PRIMARY] KEY]

data_type:
BIT[(length)]
  | TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  | INT[(length)] [UNSIGNED] [ZEROFILL]
  | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]
  | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]
  | DATE
  | TIME[(fsp)]
  | TIMESTAMP[(fsp)]
  | DATETIME[(fsp)]
  | YEAR
  | CHAR[(length)] [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | VARCHAR(length) [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | BINARY[(length)]
  | VARBINARY(length)
  | TINYBLOB
  | BLOB
  | MEDIUMBLOB
  | LONGBLOB
  | TINYTEXT [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | TEXT [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | MEDIUMTEXT [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | LONGTEXT [BINARY]
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | ENUM(value1,value2,value3,...)
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | SET(value1,value2,value3,...)
  [CHARACTER SET charset_name] [COLLATE collation_name]
  | JSON
  | spatial_type

index_col_name:
col_name [(length)] [ASC | DESC]

index_type:
USING {BTREE | HASH}

index_option:
KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}

reference_definition:
REFERENCES tbl_name (index_col_name,...)
  [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
  [ON DELETE reference_option]
  [ON UPDATE reference_option]

reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION

table_options:
table_option [[,] table_option] ...

table_option:
ENGINE [=] engine_name
  | AUTO_INCREMENT [=] value
  | AVG_ROW_LENGTH [=] value
  | [DEFAULT] CHARACTER SET [=] charset_name
  | CHECKSUM [=] {0 | 1}
  | [DEFAULT] COLLATE [=] collation_name
  | COMMENT [=] 'string'
  | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'}
  | CONNECTION [=] 'connect_string'
  | DATA DIRECTORY [=] 'absolute path to directory'
  | DELAY_KEY_WRITE [=] {0 | 1}
  | ENCRYPTION [=] {'Y' | 'N'}
  | INDEX DIRECTORY [=] 'absolute path to directory'
  | INSERT_METHOD [=] { NO | FIRST | LAST }
  | KEY_BLOCK_SIZE [=] value
  | MAX_ROWS [=] value
  | MIN_ROWS [=] value
  | PACK_KEYS [=] {0 | 1 | DEFAULT}
  | PASSWORD [=] 'string'
  | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
  | STATS_AUTO_RECALC [=] {DEFAULT|0|1}
  | STATS_PERSISTENT [=] {DEFAULT|0|1}
  | STATS_SAMPLE_PAGES [=] value
  | TABLESPACE tablespace_name
  | UNION [=] (tbl_name[,tbl_name]...)

partition_options:
PARTITION BY
{ [LINEAR] HASH(expr)
| [LINEAR] KEY [ALGORITHM={1|2}] (column_list)
| RANGE{(expr) | COLUMNS(column_list)}
| LIST{(expr) | COLUMNS(column_list)} }
[PARTITIONS num]
[SUBPARTITION BY
{ [LINEAR] HASH(expr)
| [LINEAR] KEY [ALGORITHM={1|2}] (column_list) }
  [SUBPARTITIONS num]
]
[(partition_definition [, partition_definition] ...)]

partition_definition:
PARTITION partition_name [VALUES
{LESS THAN {(expr | value_list) | MAXVALUE}
| IN (value_list)}]
[[STORAGE] ENGINE [=] engine_name]
[COMMENT [=] 'comment_text' ]
[DATA DIRECTORY [=] 'data_dir']
[INDEX DIRECTORY [=] 'index_dir']
[MAX_ROWS [=] max_number_of_rows]
[MIN_ROWS [=] min_number_of_rows]
[TABLESPACE [=] tablespace_name]
[(subpartition_definition [, subpartition_definition] ...)]

subpartition_definition:
SUBPARTITION logical_name
[[STORAGE] ENGINE [=] engine_name]
[COMMENT [=] 'comment_text' ]
[DATA DIRECTORY [=] 'data_dir']
[INDEX DIRECTORY [=] 'index_dir']
[MAX_ROWS [=] max_number_of_rows]
[MIN_ROWS [=] min_number_of_rows]
[TABLESPACE [=] tablespace_name]

query_expression:
SELECT ...   (Some valid select or union statement)
CREATE TABLE составляет таблицу с именем. Вы должны иметь привилегию CREATE для таблицы.

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

Имя таблицы может быть определено как db_name.tbl_name, чтобы составлять таблицу в определенной базе данных. Это работает независимо от того, есть ли база данных по умолчанию, предполагая, что база данных существует. Если Вы используете заключенные в кавычки идентификаторы, то заключите в кавычки имена базы данных и имена таблиц отдельно. Например, `mydb`.`mytbl` не `mydb.mytbl`.

Клонирование или копирование таблицы

CREATE TABLE ... LIKE составляет пустую таблицу, основанную на определении другой таблицы, включая любые параметры столбца и индексы, определенные в оригинальной таблице:

CREATE TABLE new_tbl LIKE orig_tbl;
См. раздел 14.1.15.1.

Чтобы составить одну таблицу от другой, добавьте SELECT в конце CREATE TABLE:

CREATE TABLE new_tbl SELECT * FROM orig_tbl;
См. раздел 14.1.15.2.

Временные таблицы

Вы можете использовать ключевое слово TEMPORARY, составляя таблицу. Таблица TEMPORARY видима только текущему сеансу и удалена автоматически, когда сеанс закрыт. Это означает, что два различных сеанса могут использовать то же самое временное имя таблицы, не находясь в противоречии друг с другом или с существующими не-TEMPORARY таблицами. Существующая таблица скрыта, пока временная таблица не удалена. Чтобы составить временные таблицы, Вы должны иметь привилегию CREATE TEMPORARY TABLES.

InnoDB не поддерживает сжатые временные таблицы. Когда innodb_strict_mode включен (значение по умолчанию), CREATE TEMPORARY TABLE возвращает ошибку, если ROW_FORMAT=COMPRESSED или указан KEY_BLOCK_SIZE. Если innodb_strict_mode отключен, предупреждения выпущены, и временная таблица составлена, используя несжатый формат строки. Временные таблицы InnoDB составлены в совместно используемом временном табличном пространстве ibtmp1. innodb_file_per-table не затрагивает создание временных таблиц InnoDB.

CREATE TABLE автоматически не закрывает текущую активную транзакцию, если Вы используете ключевое слово TEMPORARY.

Таблицы TEMPORARY имеют очень свободные отношения с базами данных (схемами). Удаление базы данных автоматически не удаляет таблицы TEMPORARY в пределах той базы данных. Кроме того, Вы можете создать таблицу TEMPORARY в несуществующей базе данных, если Вы квалифицируете имя таблицы с именем базы данных в CREATE TABLE. В этом случае все последующие ссылки на таблицу должны быть квалифицированы с именем базы данных.

Существующая таблица с тем же самым именем

Ключевые слова IF NOT EXISTS не дают ошибке произойти, если таблица существует. Однако, нет никакой проверки, что у существующей таблицы есть структура, идентичная обозначенной в CREATE TABLE.

Физическое представление

Для таблицы InnoDB в табличном пространстве file-per-table или общем табличном пространстве табличных данные и связанные индексы сохранены в файле ibd в каталоге базы данных. Когда таблица InnoDB составлена в системном табличном пространстве, табличные данные и индексы сохранены в файлах ibdata*, которые представляют системное табличное пространство. innodb_file_per_table управляет, составлены ли таблицы в табличных пространствах file-per-table или системном табличном пространстве по умолчанию. Опция TABLESPACE может использоваться, чтобы поместить таблицу в табличное пространство file-per-table, общее табличное пространство или системное табличное пространство, независимо от innodb_file_per_table .

Для MyISAM механизм хранения создает файлы с данными и индексные файлы. Таким образом, для каждой таблицы MyISAM tbl_name есть два дисковых файла.

ФайлНазначение
tbl_name.MYD Данные
tbl_name.MYI Индексы

Глава 17 описывает то, что регистрирует каждый механизм хранения, чтобы представить таблицы. Если имя таблицы содержит специальные символы, названия табличных файлов содержат закодированные версии тех символов как описано в разделе 10.2.3.

Типы данных и признаки для столбцов

data_type представляет тип данных в определении столбца. spatial_type представляет пространственный тип данных. Показанный синтаксис типа данных является только образцом. Для полного описания синтаксиса, доступного для определения типов данных столбца, так же как и для информации о свойствах каждого типа см. главу 12 и раздел 12.5. Тип данных JSON также поддержан для столбцов таблицы, см. раздел 12.6.

Некоторые признаки не относятся ко всем типам данных. AUTO_INCREMENT применяется только к целому числу и типам с плавающей запятой. DEFAULT не относится к типам BLOB, TEXT, GEOMETRY и JSON.

Механизмы хранения

Опция ENGINE определяет механизм хранения для таблицы, используя одно из имен, показанных в следующей таблице. Имя механизма может быть взято в кавычки. Заключенное в кавычки имя 'DEFAULT' признано, но проигнорировано.

Механизм хранения Описание
InnoDB Транзакционно-безопасные таблицы с блокировкой строки и внешними ключами. Механизм хранения значения по умолчанию для новых таблиц. См. главу 16.
MyISAM Двоичной механизм хранения, который прежде всего используется для рабочих нагрузок, главным образом, чтения или только для чтения. См. раздел 17.2.
MEMORYДанные для этого механизма хранятся только в памяти. См. раздел 17.3.
CSVТаблицы, которые хранят строки в отделенном запятыми формате значений. См. раздел 17.4.
ARCHIVE Механизм хранения архивирования. См. раздел 17.5.
EXAMPLE Механизм в качестве примера. См. раздел 17.9.
FEDERATED Механизм хранения, который получает доступ к удаленным таблицам. См. раздел 17.8.
HEAPСиноним для MEMORY.
MERGEНабор таблиц MyISAM, используемых в качестве одной таблицы. Также известен как MRG_MyISAM. См. раздел 17.7.

По умолчанию, если определен механизм хранения, который не доступен, запрос терпит неудачу с ошибкой. Вы можете переопределить это поведение, удаляя режим SQL NO_ENGINE_SUBSTITUTION (см. раздел 6.1.8), чтобы MySQL позволил замену указанного механизма механизмом хранения по умолчанию вместо этого. Обычно в таких случаях это InnoDB, который является значением по умолчанию для default_storage_engine. Когда NO_ENGINE_SUBSTITUTION выключен, предупреждение происходит, если спецификация механизма хранения не соблюдается.

Оптимизация работы

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

Составление разделенных таблиц

partition_options может использоваться, чтобы управлять разделением таблицы, составленной с CREATE TABLE.

Не все варианты в синтаксисе для partition_options в начале этого раздела доступны для всех типов разделения. Пожалуйста, см. списки для следующих отдельных типов для информации, определенной для каждого типа, и см. главу 20 для подробностей.

Если используется, partition_options начинается с PARTITION BY. Этот пункт содержит функцию, которая используется, чтобы определить разделение, функция возвращает целочисленное значение в пределах от 1 до num, где num число разделов. Максимальное количество определяемых пользователем разделов, которые может содержать таблица, 1024, число подразделов рассматривается позже и включено в этот максимум. Выбор, который доступен для этой функции в MySQL 8.0, показывают в следующем списке:

Выражение (expr) в PARTITION BY не может отнестись ни к каким столбцам не в составленной таблице, такие ссылки определенно не разрешены и заставляют запрос терпеть неудачу с ошибкой (Bug #29444).

Каждое разделение может быть индивидуально определено, используя partition_definition. Отдельные части, составляющие этот пункт, следующие:

Разделение произведенными столбцами разрешено. Например:

CREATE TABLE t1 (s1 INT, s2 INT AS (EXP(s1)) STORED)
       PARTITION BY LIST (s2) (PARTITION p1 VALUES IN (1));
Разделение рассматривает произведенный столбец как регулярный столбец, который является обходным решениям для ограничений на функции, которые не разрешены для того, чтобы разделить (см. раздел 20.6.3). Предыдущий пример демонстрирует этот метод: EXP() не может использоваться непосредственно в PARTITION BY, но произведенный столбец определил использование EXP().

яРазделение может быть изменено, слито, добавлено к таблицам и исключено из таблиц. Для основной информации о запросах MySQL, чтобы выполнить эти задачи, см. раздел 14.1.7. Подробности в разделе 20.3.

Оригинал CREATE TABLE, включая все технические требования и табличные опции сохранено MySQL, когда таблица составлена. Это сделано, чтобы, если Вы изменяете сопоставления или другие настройки, используя ALTER TABLE, оригинальные табличные определенные опции были сохранены. Это позволяет Вам изменять табличные типы даже при том, что форматы строки, поддержанные этими двумя механизмами, могут отличаться.

Поскольку текст оригинального запроса сохранен, но из-за способа, которым могут быть тихо реконфигурированы определенные значения и опции (хотя бы ROW_FORMAT), активное табличное определение (доступно через DESCRIBE или SHOW TABLE STATUS) и табличная строка создания (доступна через SHOW CREATE TABLE) сообщат различные значения.

14.1.15.1. CREATE TABLE ... LIKE

CREATE TABLE ... LIKE применяется, чтобы составить пустую таблицу, основанную на определении другой таблицы, включая любой столбец, префикс и индекс, определенные в оригинальной таблице:

CREATE TABLE new_tbl LIKE orig_tbl;
Копия создается, используя ту же самую версию табличного формата хранения, как оригинальная таблица. Привилегия SELECT требуется на оригинальной таблице.

LIKE работает только для базовых таблиц, не для представлений.

Вы не можете выполнить CREATE TABLE или CREATE TABLE ... LIKE в то время, как есть запрос LOCK TABLES.

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

Для CREATE TABLE ... LIKE целевая таблица сохраняет произведенную информацию о столбце от оригинальной таблицы.

CREATE TABLE ... LIKE не сохраняет табличные опции DATA DIRECTORY или INDEX DIRECTORY, которые были определены для оригинальной таблицы, или любые определения внешнего ключа.

Если оригинальная таблица TEMPORARY, CREATE TABLE ... LIKE не сохраняет TEMPORARY. Чтобы создать целевую таблицу TEMPORARY, надо использовать CREATE TEMPORARY TABLE ... LIKE.

14.1.15.2. CREATE TABLE ... SELECT

Вы можете составить одну таблицу от другой, добавляя SELECT в конец the CREATE TABLE:

CREATE TABLE new_tbl [AS] SELECT * FROM orig_tbl;
MySQL создает новые столбцы для всех элементов в SELECT:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
    ->        PRIMARY KEY (a), KEY(b))
    ->        ENGINE=MyISAM SELECT b,c FROM test2;
Это создает MyISAM с тремя столбцами, a, b и c. ENGINE часть CREATE TABLE и не должно использоваться после SELECT, это привело бы к синтаксической ошибке. То же самое истина для других опций CREATE TABLE, например, для CHARSET.

Заметьте, что столбцы из SELECT добавлены к правой стороне таблицы. Возьмите следующий пример:

mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+

mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)
Для каждой строки в таблице foo строка вставлена в bar со значениями из foo и значениями по умолчанию для новых столбцов.

В таблице, следующей из CREATE TABLE ... SELECT, столбцы, названные только в части CREATE TABLE на первом месте. Столбцы, названные в обеих частях или только в SELECT, прибывают после этого. Тип данных столбцов SELECT могут быть переопределены, также определяя столбец в части CREATE TABLE.

Если какие-либо ошибки происходят, копируя данные к таблице, таблица автоматически удалена и не создана.

Вы можете предшествовать SELECT IGNORE или REPLACE, чтобы указать, как обработать строки, которые дублируют уникальные значения ключа. С IGNORE отказываются от строк, которые дублируют существующую строку на уникальном значении ключа. С REPLACE новые строки заменяют строки, у которых есть то же самое уникальное значение ключа. Если IGNORE или REPLACE не определен, будет ошибка дубликата уникального значения ключа.

Поскольку упорядочивание строк в основном SELECT не может всегда определяться, CREATE TABLE ... IGNORE SELECT и CREATE TABLE ... REPLACE SELECT отмечены как опасные для основанной на запросе репликации. С этим изменением такие запросы производят предупреждение в журнале, используя основанный на запросе режим и зарегистрированы, используя основанный на строке формат, используя режим MIXED. См. раздел 19.2.1.1.

CREATE TABLE ... SELECT автоматически не создает индекс. Это сделано преднамеренно, чтобы сделать запрос настолько гибким насколько возможно. Если Вы хотите иметь индексы в составленной таблице, Вы должны определить их перед SELECT:

mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
Для CREATE TABLE ... SELECT целевая таблица не сохраняет информацию о том, являются ли столбцы, выбранные из исходной таблицы, произведенными столбцами. Часть SELECT не может назначить значения на произведенные столбцы в целевой таблице.

Некоторое преобразование типов данных могло бы произойти. Например, AUTO_INCREMENT не сохранен, и VARCHAR могут стать CHAR. Сохраняются признаки NULL (или NOT NULL) для тех столбцов, у которых они есть, CHARACTER SET, COLLATION, COMMENT и DEFAULT.

Составляя таблицу с CREATE TABLE ... SELECT, удостоверьтесь в псевдонимах любых вызовов функции или выражения в запросе. Если Вы не делаете этого, CREATE мог бы потерпеть неудачу или привести к нежелательным именам столбцов.

CREATE TABLE artists_and_works
  SELECT artist.name, COUNT(work.artist_id) AS number_of_works
  FROM artist LEFT JOIN work ON artist.id = work.artist_id
  GROUP BY artist.id;
Вы можете также явно определить тип данных для столбца в составленной таблице:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
Для CREATE TABLE ... SELECT, если задано IF NOT EXISTS и целевая таблица существует, ничто не вставлено в целевую таблицу, и запрос не зарегистрирован.

Чтобы гарантировать, что двоичный журнал может использоваться, чтобы обновить оригинальные таблицы, MySQL не разрешает параллельные вставки во время CREATE TABLE ... SELECT .

Вы не можете использовать FOR UPDATE как часть SELECT в таком запросе, как CREATE TABLE new_table SELECT ... FROM old_table .... Если Вы пытаетесь сделать так, запрос терпит неудачу.

14.1.15.3. Используя ограничения FOREIGN KEY

MySQL поддерживает внешние ключи, которые позволяют Вам перекрестно ссылаться на связанные данные через таблицы, и ограничения внешнего ключа, которые сохраняют эти данные распространения последовательными. Существенный синтаксис для определения ограничения внешнего ключа в CREATE TABLE или ALTER TABLE похож на это:

[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]

reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION
index_name представляет ID внешнего ключа. index_name проигнорировано, если уже есть явно определенный индекс на дочерней таблице, которая может поддержать внешний ключ. Иначе MySQL неявно создает индекс внешнего ключа, который называют согласно следующим правилам:

Определения внешних ключей подвергаются следующим условиям:

Справочные действия

Этот раздел описывает, как ссылка внешних ключей гарантирует целостность.

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

Когда UPDATE или DELETE затрагивает значение ключа в родительской таблице, у которой есть соответствие строк в дочерней таблице, результат зависит от действия, определенного, используя ON UPDATE и ON DELETE в FOREIGN KEY. MySQL поддерживает пять опций относительно действия, перечисленных здесь:

Для ON DELETE или ON UPDATE действие значения по умолчанию всегда RESTRICT.

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

Ограничение внешнего ключа на произведенный сохраненный столбец не может использовать ON UPDATE CASCADE, ON DELETE SET NULL, ON UPDATE SET NULL, ON DELETE SET DEFAULT или ON UPDATE SET DEFAULT.

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

Для InnoDB ограничения, связанные с внешними ключами и произведенными столбцами, см. в разделе 16.8.6.

Примеры пунктов внешнего ключа

Вот простой пример, который имеет отношение таблиц parent и child через внешний ключ единственного столбца:

CREATE TABLE parent (id INT NOT NULL,
                     PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id),
                    FOREIGN KEY (parent_id) REFERENCES parent(id)
                    ON DELETE CASCADE) ENGINE=INNODB;
Более сложный пример, в котором у таблицы product_order есть внешние ключи для двух других таблиц. Один внешний ключ ссылается на индекс из двух столбцов в таблице product. Второй ссылается на индекс из единственного столбца в customer:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
                      price DECIMAL, PRIMARY KEY(category, id))
                      ENGINE=INNODB;

CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,
                            product_category INT NOT NULL,
                            product_id INT NOT NULL,
                            customer_id INT NOT NULL, PRIMARY KEY(no),
                            INDEX (product_category, product_id),
                            INDEX (customer_id),
                            FOREIGN KEY (product_category, product_id)
                            REFERENCES product(category, id)
                            ON UPDATE CASCADE ON DELETE RESTRICT,
                            FOREIGN KEY (customer_id)
                            REFERENCES customer(id)) ENGINE=INNODB;
Добавление внешних ключей

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

ALTER TABLE tbl_name
ADD [CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
Внешний ключ может быть сам ссылочным (обращающийся к той же самой таблице). Когда Вы добавляете ограничение внешнего ключа к таблице через ALTER TABLE, не забудьте создать необходимый индекс сначала.

Удаление внешних ключей

Вы можете также использовать ALTER TABLE, чтобы удалить внешние ключи, используя синтаксис, показанный здесь:

ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;
Если FOREIGN KEY включал имя CONSTRAINT, когда Вы создали внешний ключ, Вы можете обратиться к тому имени, чтобы удалить внешний ключ. Иначе значение fk_symbol произведено внутренне, когда внешний ключ создается. Чтобы узнать символьное значение, когда Вы хотите удалить внешний ключ, используйте SHOW CREATE TABLE:
mysql> SHOW CREATE TABLE ibtest11c\G
*************************** 1. row ***************************
   Table: ibtest11c
Create Table: CREATE TABLE `ibtest11c` (
  `A` int(11) NOT NULL auto_increment,
  `D` int(11) NOT NULL default '0',
  `B` varchar(200) NOT NULL default '',
  `C` varchar(175) default NULL,
  PRIMARY KEY  (`A`,`D`,`B`),
  KEY `B` (`B`,`C`),
  KEY `C` (`C`),
  CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`)
REFERENCES `ibtest11a` (`A`, `D`)
ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`)
REFERENCES `ibtest11a` (`B`, `C`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB CHARSET=latin1
1 row in set (0.01 sec)

mysql> ALTER TABLE ibtest11c DROP FOREIGN KEY `0_38775`;
Добавление и удаление внешнего ключа в том же самом ALTER TABLE поддержано для ALTER TABLE ... ALGORITHM=INPLACE , но не поддержано для ALTER TABLE ... ALGORITHM=COPY .

В MySQL 8.0 сервер запрещает изменения столбцов внешнего ключа с потенциалом потери справочной целостности. Обходное решение должно использовать ALTER TABLE ... DROP FOREIGN KEY прежде, чем изменить определение столбца и ALTER TABLE ... ADD FOREIGN KEY позже.

Внешние ключи и другие запросы MySQL

Таблица и идентификаторы столбца в FOREIGN KEY ... REFERENCES ... могут быть заключены в кавычки в пределах обратных кавычек (`). Альтернативно, двойные кавычки (") может использоваться, если включен режим SQL ANSI_QUOTES. Установка lower_case_table_names также принята во внимание.

Вы можете рассмотреть определения внешнего ключа дочерней таблицы как часть вывода SHOW CREATE TABLE :

SHOW CREATE TABLE tbl_name;
Вы можете также получить информацию о внешних ключах, запрашивая таблицу INFORMATION_SCHEMA.KEY_COLUMN_USAGE.

Вы можете считать информацию о внешних ключах, используемую таблицами InnoDB в INNODB_SYS_FOREIGN и INNODB_SYS_FOREIGN_COLS в базе данных INFORMATION_SCHEMA.

mysqldump производит правильные определения таблиц в файле дампа, включая внешние ключи для дочерних таблиц.

Чтобы облегчить перезагрузку файла дампа для таблиц, у которых есть отношения внешнего ключа, mysqldump автоматически, включает запрос в вывод дампа, чтобы установить foreign_key_checks в 0. Это избегает проблем с таблицами, имеющими необходимость быть перезагруженными в особом порядке, когда дамп перезагружен. Также возможно установить эту переменную вручную:

mysql> SET foreign_key_checks = 0;
mysql> SOURCE dump_file_name;
mysql> SET foreign_key_checks = 1;
Это позволяет Вам импортировать таблицы в любом порядке, если файл дампа содержит таблицы, которые правильно не упорядочены для внешних ключей. Это также ускоряет работу импорта. Установка foreign_key_checks в 0 может также быть полезна для игнорирования ограничений внешнего ключа во время LOAD DATA и ALTER TABLE. Однако, даже если foreign_key_checks = 0, MySQL не разрешает создание ограничения внешнего ключа, где столбец ссылается на несоответствующий тип столбца. Кроме того, если у таблицы есть ограничения внешнего ключа, ALTER TABLE не может использоваться, чтобы изменить таблицу, чтобы использовать другой механизм хранения. Чтобы изменить механизм хранения, Вы должны сначала удалить любые ограничения внешнего ключа.

Вы не можете использовать DROP TABLE для таблицы, на которую ссылается ограничение FOREIGN KEY , если Вы не делаете SET foreign_key_checks = 0. Когда Вы удаляете таблицу, любые ограничения, которые были определены в запросе, используемом, чтобы составить эту таблицу, также удалены.

Если Вы обновляете таблицу, которая была удалена, у нее должно быть определение, которое соответствует ограничениям внешнего ключа, ссылающимся на нее. У этого должны быть правильные имена столбцов и типы, и таблица должна иметь индекс на ключах, на которые ссылаются, как заявлено ранее. Если эти условия не удовлетворены, MySQL возвращает Error 1005 и Error 150 в сообщении об ошибке, что означает, что ограничение внешнего ключа не было правильно сформировано. Точно так же, если ALTER TABLE терпит неудачу из-за Error 150, это означает, что определение внешнего ключа было неправильно сформировано для измененной таблицы.

Для таблиц InnoDB Вы можете получить подробное объяснение ошибки внешнего ключа в MySQL Server, просмотрев вывод SHOW ENGINE INNODB STATUS.

Для пользователей, знакомых с ANSI/ISO SQL Standard, отметьте, что никакой механизм хранения, включая InnoDB, не признает или проводит в жизнь MATCH в определениях ограничения справочной целостности. Использование явного MATCH не будет иметь указанного эффекта, и также вызывает ON DELETE и ON UPDATE, которые будут проигнорированы. По этим причинам определть MATCH не надо.

MATCH в стандарте SQL управляет, как NULL обработаны в сложном (из нескольких столбцов) внешнем ключе, сравниваясь с первичным ключом. MySQL по существу осуществляет семантику, определенную MATCH SIMPLE, которые разрешают внешнему ключу быть всему или частично NULL. В этом случае (дочерняя таблица) строке, содержащей такой внешний ключ, разрешают быть вставленной и не соответствовать строке в (родительской) таблице, на которую ссылаются. Возможно осуществить другую семантику, используя триггеры.

Дополнительно, MySQL требует, чтобы столбцы, на которые ссылаются, были индексированы по исполнительным причинам. Однако, система не проводит в жизнь требование, что столбцы, на которые ссылаются, UNIQUE или объявлены NOT NULL. Обработка ссылок внешнего ключа на групповые ключи или ключи, которые содержат NULL не четко определены для таких операций, как UPDATE или DELETE CASCADE . Вам советуют использовать внешние ключи, которые ссылаются только на UNIQUE (включая PRIMARY) и ключи NOT NULL.

Кроме того, MySQL разбирает, но игнорирует inline REFERENCES (как определено в SQL), где ссылки определены как часть спецификации столбца. MySQL принимает REFERENCES только когда определено как часть отдельного FOREIGN KEY. Для механизмов хранения, которые не поддерживают внешние ключи (MyISAM , например), MySQL Server разбирает и игнорирует технические требования внешнего ключа.

14.1.15.4. В некоторых случаях, MySQL тихо изменяет технические требования столбца от данных в CREATE TABLE или ALTER TABLE. Они могли бы быть изменениями типа данных, признаков, связанных с типом данных или спецификации индекса.

Все изменения подвергаются внутреннему пределу размера строки 65535 байтов, которые могут заставить некоторые попытки изменений типа данных терпеть неудачу. См. раздел C.10.4 .

Чтобы видеть, использовал ли MySQL тип данных кроме того, который Вы определили, используйте DESCRIBE или SHOW CREATE TABLE после создания или изменения таблицы.

Определенные другие изменения типа данных могут произойти, если Вы сжимаете таблицу, используя myisampack. См. раздел 17.2.3.3.

14.1.15.5. CREATE TABLE и произведенные столбцы

CREATE TABLE поддерживает спецификацию произведенных столбцов. Значения произведенного столбца вычислены от выражения, включенного в определение столбца.

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

CREATE TABLE triangle (sidea DOUBLE, sideb DOUBLE,
       sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb)));
INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8);
Выбор из таблицы приводит к этому результату:
mysql> SELECT * FROM triangle;
+-------+-------+--------------------+
| sidea | sideb | sidec              |
+-------+-------+--------------------+
| 1     | 1     | 1.4142135623730951 |
| 3     | 4     | 5                  |
| 6     | 8     | 10                 |
+-------+-------+--------------------+
Любое приложение, которое использует таблицу triangle имеет доступ к значениям гипотенузы, не имея необходимость определять выражение, которое вычисляет их.

У произведенных определений столбца есть этот синтаксис:

col_name data_type
   [GENERATED ALWAYS] AS (expression)
   [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
   [[NOT] NULL] [[PRIMARY] KEY]
AS (expression) указывает, что столбец произведен и определяет выражение, используемое, чтобы вычислить значения столбцов. AS можно предшествовать GENERATED ALWAYS, чтобы сделать произведенную природу столбца более явной. Конструкции, которые разрешены или запрещены в выражении, обсуждены позже.

VIRTUAL или STORED указывает, как сохранены значения столбцов, у которого есть значения для использования столбца:

Значение по умолчанию VIRTUAL, если никакое ключевое слово не определено.

Разрешено смешивать столбцы VIRTUAL и STORED в пределах таблицы.

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

Произведенные выражения столбца должны придерживаться следующих правил. Ошибка происходит, если выражение содержит отвергнутые конструкции.

Если выражение оценивается к типу данных, который отличается от заявленного типа столбца, принуждение к заявленному типу происходит согласно обычным правилам преобразования типа MySQL. См. раздел 13.2.

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

Для CREATE TABLE ... LIKE целевая таблица сохраняет произведенную информацию о столбце от оригинальной таблицы.

Для CREATE TABLE ... SELECT целевая таблица не сохраняет информацию о том, являются ли столбцы в выборке произведенными столбцами. Часть SELECT может назначить значения на произведенные столбцы в целевой таблице.

Разделение произведенными столбцами разрешено.

Ограничение внешнего ключа на произведенный сохраненный столбец не может использовать ON UPDATE CASCADE, ON DELETE SET NULL, ON UPDATE SET NULL, ON DELETE SET DEFAULT или ON UPDATE SET DEFAULT.

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

Для InnoDB ограничения, связанные с внешними ключами и произведенными столбцами, см. в разделе 16.8.6.

Триггеры не могут использовать NEW.col_name или OLD.col_name, чтобы обратиться к произведенным столбцам.

Для INSERT, REPLACE и UPDATE, если произведенный столбец вставлен, заменил или обновил явно, единственное разрешенное значение DEFAULT.

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

У произведенных столбцов есть несколько случаев использования:

Предположите, что таблица t1 содержит столбцы first_name и last_name, и приложения часто создает полное имя, используя выражение:

SELECT CONCAT(first_name,' ',last_name) AS full_name FROM t1;
Один способ избежать выписывать выражение состоит в том, чтобы создать представление v1 на t1, которое упрощает приложения, позволяя им выбрать full_name непосредственно, не используя выражение:
CREATE VIEW v1 AS
       SELECT *, CONCAT(first_name,' ',last_name) AS full_name FROM t1;
       SELECT full_name FROM v1;
Произведенный столбец также позволяет приложениям выбрать full_name непосредственно, без потребности определить представление:
CREATE TABLE t1 (first_name VARCHAR(10), last_name VARCHAR(10),
                 full_name VARCHAR(255) AS
                 (CONCAT(first_name, ' ', last_name)));
SELECT full_name FROM t1;

14.1.15.6. Вторичный индекс и произведенные виртуальные столбцы

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

Вторичный индекс может быть создан на одном или более виртуальных столбцах или на комбинации виртуальных столбцов и непроизведенных виртуальных столбцов. Вторичный индекс на виртуальных столбцах может быть определен как UNIQUE.

Когда вторичный индекс создается на произведенном виртуальном столбце, произведенные значения столбцов осуществлены в записях индекса. Если индексирование является покрывающим (который включает все столбцы, полученные запросом), произведенные значения столбцов получены от осуществленных значений в индексе вместо вычисленного на лету.

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

Значения индексированного виртуального столбца MVCC-зарегистрированы, чтобы избежать ненужного перевычисления произведенных значений столбцов во время отката или во время работы чистки. Длина данных зарегистрированных значений ограничена ключевым пределом 767 байтов для COMPACT и REDUNDANT или 3072 байтами для DYNAMIC и COMPRESSED.

Добавление или удаление вторичного индекса на виртуальном столбце это оперативная работа.

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

Использование произведенного виртуального столбца индекса, чтобы косвенно индексировать столбцы JSON

Как отмечено выше, JSON не могут быть индексированы непосредственно. Чтобы создать индексирование, которое ссылается на такой столбец косвенно, Вы можете определить произведенный столбец, который извлекает информацию, которая должна быть индексирована, затем создать индексирование на произведенном столбце, как показано в этом примере:

mysql> CREATE TABLE jemp (c JSON,
    ->        g INT GENERATED ALWAYS AS (JSON_EXTRACT(c, '$.id')),
    ->        INDEX i (g));
Query OK, 0 rows affected (0.28 sec)

mysql> INSERT INTO jemp (c) VALUES
     >   ('{"id":"1","name": "Fred"}'), ('{"id": "2","name": "Wilma"}'),
     >   ('{"id":"3","name": "Barney"}'), ('{"id": "4","name": "Betty"}');
Query OK, 4 rows affected (0.04 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT JSON_UNQUOTE(JSON_EXTRACT(c, '$.name')) AS name
     >        FROM jemp WHERE g > 2;
+--------+
| name   |
+--------+
| Barney |
| Betty  |
+--------+
2 rows in set (0.00 sec)

mysql> EXPLAIN SELECT JSON_UNQUOTE(JSON_EXTRACT(c, '$.name')) AS name
     >         FROM jemp WHERE g > 2\G
*************************** 1. row ***************************
   id: 1
  select_type: SIMPLE
table: jemp
   partitions: NULL
 type: range
possible_keys: i
  key: i
  key_len: 5
  ref: NULL
 rows: 2
 filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select json_unquote(json_extract(`test`.`jemp`.`c`,'$.name'))
AS `name` from `test`.`jemp` where (`test`.`jemp`.`g` > 2)
1 row in set (0.00 sec)

MySQL 8.0 поддерживает две формы для того, чтобы получить доступ к значению путем JSON:

Таким образом, запрос SELECT JSON_UNQUOTE(JSON_EXTRACT(c, '$.name')) FROM jemp может быть переписан в более короткой форме как SELECT JSON_UNQUOTE(c->'$.name') FROM jemp или еще более сжато как SELECT c->>'$.name' FROM jemp.

Когда Вы используете EXPLAIN для SELECT или другого запроса SQL, содержащего одно или более выражений, которые используют -> или ->>, эти выражения преобразованы в их эквивалент с JSON_EXTRACT() и (если нужно) JSON_UNQUOTE(), как показано в выводе SHOW WARNINGS немедленно после EXPLAIN:

mysql> EXPLAIN SELECT c->"$.name"
     >         FROM jemp WHERE g > 2\G ORDER BY c->"$.name"
*************************** 1. row ***************************
   id: 1
  select_type: SIMPLE
table: jemp
   partitions: NULL
 type: range
possible_keys: i
  key: i
  key_len: 5
  ref: NULL
 rows: 2
 filtered: 100.00
Extra: Using where; Using filesort
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select json_extract(`test`.`jemp`.`c`,'$.name') AS
  `c->"$.name"` from `test`.`jemp` where (`test`.`jemp`.`g` > 2)
  order by json_extract(`test`.`jemp`.`c`,'$.name')
1 row in set (0.00 sec)

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

14.1.16. CREATE TABLESPACE

CREATE TABLESPACE tablespace_name
ADD DATAFILE 'file_name'
[FILE_BLOCK_SIZE = value]
[ENGINE [=] engine_name]
Этот запрос используется, чтобы создать табличное пространство InnoDB. Оно упоминается как общее табличное пространство.

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

После создания общего табличного пространства, Вы можете использовать CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name или ALTER TABLE tbl_name TABLESPACE [=] tablespace_name, чтобы добавить таблицы к табличному пространству.

См. раздел 16.7.9.

CREATE TABLESPACE поддержан с InnoDB с MySQL 5.7.6. В более ранних выпусках CREATE TABLESPACE поддержан только NDB, который является механизмом хранения MySQL Cluster.

Опции

Примечания

Примеры

Этот пример демонстрирует создание общего табличного пространства и добавление трех несжатых таблиц различных форматов строки.

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1
                 ROW_FORMAT=REDUNDANT;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts1
                 ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts1
                 ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.00 sec)
Этот пример демонстрирует создание общего табличного пространства и добавление сжатой таблицы. Пример принимает значение по умолчанию innodb_page_size 16K. FILE_BLOCK_SIZE = 8192 требует, чтобы у сжатой таблицы был KEY_BLOCK_SIZE = 8.
mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd'
                 FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2
                 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
Query OK, 0 rows affected (0.00 sec)

14.1.17. CREATE TRIGGER

CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
[trigger_order]
trigger_body
trigger_time: { BEFORE | AFTER }
trigger_event: { INSERT | UPDATE | DELETE }
trigger_order: { FOLLOWS | PRECEDES } other_trigger_name
Этот запрос создает новый триггер. Это объект базы данных, который связан с таблицей и активируется, когда особое событие имеет место для таблицы. Триггер становится связанным с таблицей, названной tbl_name, которая должна быть постоянной. Вы не можете связать триггер с таблицей TEMPORARY или представлением.

Более аккуратные имена существуют в пространстве имен схемы, означая, что у всех триггеров должны быть уникальные имена в пределах схемы. У триггеров в различных схемах может быть то же самое имя.

Этот раздел описывает CREATE TRIGGER. Подробности в разделе 21.3.1.

CREATE TRIGGER требует привилегию TRIGGER для таблицы связаланной с триггером. Запрос может также потребовать привилегию SUPER в зависимости от значения DEFINER. Если двоичное журналирование включено, CREATE TRIGGER мог бы потребовать привилегию SUPER, см. раздел 21.7.

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

trigger_time время срабатывания. Это может быть BEFORE или AFTER, чтобы указать, что триггер активируется прежде или после каждой строки, которая будет изменена.

trigger_event указывает на вид работы, которая активирует триггер. Допустимые значения trigger_event:

trigger_event не представляет буквальный тип запроса SQL, который активирует триггер, поскольку это представляет тип табличной работы. Например, триггер INSERT активируется не только для INSERT, но и для LOAD DATA, потому что оба запроса вставляют строки в таблицу.

Потенциально запутывающий пример этого INSERT INTO ... ON DUPLICATE KEY UPDATE ...: триггер BEFORE INSERT активируется для каждой строки, сопровождаемой любым триггером AFTER INSERT или триггерами BEFORE UPDATE и AFTER UPDATE в зависимости от того, было ли дублирование ключа для строки.

Каскадные действия внешнего ключа не активируют триггеры.

Возможно определить многократные триггеры для данной таблицы, у которых есть тот же самый случай и время действия. Например, Вы можете иметь два триггера BEFORE UPDATE. По умолчанию, триггеры, у которых есть тот же самый случай и время действия, активируются в порядке, в котором они создавались. Чтобы затронуть порядок, определите trigger_order, который указывает FOLLOWS или PRECEDES и название существующего триггера, у которого также есть тот же самый случай и время действия. С FOLLOWS новый триггер активируется после существующего, с PRECEDES перед существующим триггером.

trigger_body запрос, чтобы выполнить, когда триггер активируется. Чтобы выполнить много запросов, используйте BEGIN ... END. Это также позволяет Вам использовать те же самые запросы, которые разрешены в пределах сохраненных подпрограмм. См. раздел 14.6.1. Некоторые запросы не разрешены в триггерах, см. раздел C.1.

В пределах тела триггера Вы можете обратиться к столбцам в подчиненной таблице (таблица, связанная с триггером) при использовании псевдонимов OLD и NEW. OLD.col_name обращается к столбцу существующей строки прежде, чем это будет обновлено или удалено. NEW.col_name обращается к столбцу новой строки, которая будет вставлена или существующей строки после того, как столбец обновлен.

Триггеры не могут использовать NEW.col_name или OLD.col_name, чтобы обратиться к произведенным столбцам. Для информации о произведенных столбцах см. раздел 14.1.15.5.

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

DEFINER определяет учетную запись MySQL, которая будет использоваться, проверяя привилегии доступа во время активации. Если user задано, это должна быть учетная запись MySQL, определенная как 'user_name'@' host_name', CURRENT_USER или CURRENT_USER(). Значение по умолчанию DEFINER: пользователь, который выполняет CREATE TRIGGER. Это то же самое, как определение DEFINER = CURRENT_USER.

Если Вы определяете DEFINER, эти правила определяют допустимое значение DEFINER:

MySQL берет во внимание DEFINER, проверяя привилегии следующим образом:

См. раздел 21.6.

В пределах тела триггера CURRENT_USER() возвращает учетную запись для проверки привилегии во время активации. Это DEFINER, но не пользователь, действия которого заставили триггер быть активированным. Для информации о пользователе в пределах триггеров см. раздел 7.3.12.

Если Вы используете LOCK TABLES , чтобы заблокировать таблицу, у которой есть триггеры, таблицы, используемые в пределах триггера, также заблокированы, как описано в разделе 14.3.5.2.

См. раздел 21.3.1.

14.1.18. CREATE VIEW

CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
CREATE VIEW создает новое представление или заменяет существующее представление, если указано OR REPLACE. Если представление не существует, CREATE OR REPLACE VIEW то же самое, как CREATE VIEW. Если представление действительно существует, CREATE OR REPLACE VIEW то же самое, как ALTER VIEW.

См. раздел C.5.

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

Определение представления заморожено во время создания и не затронуто последующими изменениями определений основных таблиц. Например, если представление определено как SELECT * на таблице новые столбцы, добавленные к таблице позже, не становятся частью представления, а столбцы, исключенные из таблицы, приведут к ошибке, выбирая из представления.

ALGORITHM затрагивает, как MySQL обрабатывает представление. DEFINER и SQL SECURITY определяют контекст безопасности, который будет использоваться, проверяя привилегии доступа во время запроса представления. WITH CHECK OPTION может быть дан, чтобы ограничить вставки или обновления строк в таблицах, на которые ссылается представление. Эти пункты описаны позже в этом разделе.

CREATE VIEW требует привилегии CREATE VIEW для представления, и некоторую привилегию для каждого столбца, выбранного SELECT. Для столбцов, используемых в другом месте в SELECT, Вы должны иметь привилегию SELECT. Если указано OR REPLACE, Вы должны также иметь привилегию DROP для представления. CREATE VIEW мог бы также потребовать привилегию SUPER в зависимости от значения DEFINER, как описано позже в этом разделе.

Когда на представление ссылаются, проверка привилегии происходит как описано позже в этом разделе.

Представление принадлежит базе данных. По умолчанию, новое представление создается в базе данных по умолчанию. Чтобы создать представление явно в данной базе данных, надо использовать db_name.view_name , чтобы квалифицировать имя представления с именем базы данных:

CREATE VIEW test.v AS SELECT * FROM t;
Неквалифицированное имя таблицы или представления в SELECT также интерпретируется относительно базы данных значения по умолчанию. Представление может обратиться к таблицам или представлениям в других базах данных, квалифицируя таблицу или рассмотреть имя с соответствующим именем базы данных.

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

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

У представления должны быть уникальные имена столбцов без дубликатов, точно так же, как у базовой таблицы. По умолчанию названия столбцов, полученных SELECT, используются для имен столбцов представления. Чтобы определить явные названия столбцов представления, определите дополнительно column_list как список отделенных запятыми идентификаторов. Число имен в column_list должно быть то же самое, как число столбцов, полученных SELECT.

Представление может быть создано из многих видов SELECT. Это может сослаться на базовые таблицы или другие представления. Это может использовать соединения, UNION и подзапросы. SELECT даже не обязан обращаться к таблицам вообще:

CREATE VIEW v_today (today) AS SELECT CURRENT_DATE;
Следующий пример определяет представление, которое выбирает два столбца из другой таблицы, так же как выражение, вычисленное от тех столбцов:
mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+-----+-------+-------+
| qty | price | value |
+-----+-------+-------+
| 3   | 50    |   150 |
+-----+-------+-------+
Определение представления подвергается следующим ограничениям:

ORDER BY разрешен в определении представления, но это проигнорировано, если Вы выбираете из представления, используя запрос, у которого есть его собственный ORDER BY.

Для других опций или пунктов в определении эффект не определен. Например, если определение представления включает LIMIT, и Вы выбираете из представления, используя запрос, у которого есть его собственный LIMIT, не определено, какой предел применяется. Этот же самый принцип относится к таким опциям, как ALL, DISTINCT или SQL_SMALL_RESULT, INTO, FOR UPDATE, LOCK IN SHARE MODE и PROCEDURE.

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

mysql> CREATE VIEW v (mycol) AS SELECT 'abc';
Query OK, 0 rows affected (0.01 sec)

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| mycol |
+-------+
1 row in set (0.01 sec)

mysql> SET sql_mode = 'ANSI_QUOTES';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| abc   |
+-------+
1 row in set (0.00 sec)
DEFINER и SQL SECURITY определяют, который пользователь MySQL использовать, проверяя привилегии доступа на представлении, когда запрос выполнен. Допустимые SQL SECURITY: DEFINER(значение по умолчанию) и INVOKER. Они указывают, что необходимые привилегии должны быть проведены пользователем, который определил или вызвал представление, соответственно.

Если user задано для DEFINER, это должна быть учетная запись MySQL, определенная как 'user_name'@'host_name' , CURRENT_USER или CURRENT_USER(). Значение по умолчанию DEFINER это пользователь, который выполняет CREATE VIEW. Это то же самое, как определение DEFINER = CURRENT_USER.

Если DEFINER задан, эти правила определяют допустимое значение DEFINER:

См. раздел 21.6.

В пределах определения представления CURRENT_USER возвращает значение по умолчанию DEFINER. Для представлений, определенных с SQL SECURITY INVOKER, CURRENT_USER возвращает учетку вызывающего представление. См. раздел 7.3.12.

В пределах сохраненной подпрограммы, которая определена с SQL SECURITY DEFINER, CURRENT_USER возвращает DEFINER подпрограммы. Это также затрагивает представление, определенное в пределах такой подпрограммы, если определение представления содержит DEFINER CURRENT_USER.

MySQL проверяет привилегии представления:

Пример: представление могло бы зависеть от сохраненной функции, а функция могла бы вызвать другие сохраненные подпрограммы. Например, следующее представление вызывает сохраненную функцию f():

CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);
Предположите, что f() содержит запрос:
IF name IS NULL then
   CALL p1();
ELSE
   CALL p2();
END IF;
Привилегии, требуемые для того, чтобы выполнить запрос в пределах f(), будут проверены, когда выполняется f(). Это могло бы означать, что привилегии необходимы для p1() или p2(), в зависимости от пути выполнения в пределах f(). Те привилегии должны быть проверены во время выполнения, и пользователь, который должен обладать привилегиями, определен SQL SECURITY представления v и функции f().

DEFINER и SQL SECURITY для представлений это расширения к стандартному SQL. В стандартном SQL представления обработаны, используя правила для SQL SECURITY DEFINER. Стандарт говорит, что definer представления, который является тем же самым, как владельцем схемы представления, получает применимые права на представлении (например, SELECT ) и может предоставить их. У MySQL нет никакого понятия владельца схемы, таким образом, MySQL добавляет пункт, чтобы идентифицировать definer. DEFINER расширение, где намерение состоит в том, чтобы иметь то, что имеет стандарт, то есть, постоянный отчет о том, кто определил представление. Это то, почему значение по умолчанию DEFINER учетная запись создателя представления.

ALGORITHM тоже расширение MySQL. Это затрагивает, как MySQL обрабатывает представление. ALGORITHM берет три значения: MERGE, TEMPTABLE или UNDEFINED. См. разделы 21.5.2 и 9.2.1.18.3.

Некоторые представления обновляемые. Таким образом, Вы можете использовать их в запросах UPDATE, DELETE или INSERT, чтобы обновить содержание основной таблицы. Для представления, чтобы быть обновляемым, должны быть непосредственные отношения между строками в представлении и строками в основной таблице. Есть также определенные другие конструкции, которые делают представление необновляемым.

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

WITH CHECK OPTION может быть дан для обновляемого представления, чтобы предотвратить вставки или обновления к строкам кроме тех, для которых WHERE в select_statement истина.

В WITH CHECK OPTION для обновляемого представления ключевые слова LOCAL и CASCADED определяют контекст проверки, когда представление определено с точки зрения другого представления. LOCAL ограничивает CHECK OPTION только к определяемому представлению. CASCADED вызывает проверку на то, чтобы лежать в основе представлений, которые будут оценены также. Когда никакое ключевое слово не дано, значение по умолчанию CASCADED.

См. разделы 21.5.3 и 21.5.4.

14.1.19. DROP DATABASE

DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
DROP DATABASE удаляет все таблицы в базе данных и базу данных. Будьте очень осторожны с этим запросом! Чтобы использовать DROP DATABASE, нужна привилегия DROP на базе данных. DROP SCHEMA синоним для DROP DATABASE.

Когда база данных удалена, пользовательские привилегии на базе данных не удалены автоматически. см. раздел 14.7.1.6.

IF EXISTS используется, чтобы препятствовать ошибке, если база данных не существует.

Если база данных по умолчанию удалена, она сброшена (DATABASE() вернет NULL).

Если Вы используете DROP DATABASE на символически соединенной базе данных, удалены ссылка и оригинальная база данных.

DROP DATABASE возвращает число таблиц, которые были удалены.

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

.BAK.DAT .HSH.MRG
.MYD.MYI .cfg.db
.ibd.ndb

Если другие файлы или каталоги остаются в каталоге базы данных после того, как MySQL удаляет только перечисленных, каталог базы данных не может быть удален. В этом случае, Вы должны удалить любые остающиеся файлы или каталоги вручную и снова использовать DROP DATABASE.

Удаление базы данных не удаляет таблицы TEMPORARY, которые были составлены в той базе данных. Таблицы TEMPORARY автоматически удалены, когда сеанс, который создал их, заканчивается.

Вы можете также удалить базы данных с помощью mysqladmin . см. раздел 5.5.2.

14.1.20. DROP EVENT

DROP EVENT [IF EXISTS] event_name
Этот запрос удаляет событие event_name. Оно немедленно прекращает быть активным и удалено полностью из сервера.

Если событие не существует, будет ошибка ERROR 1517 (HY000): Unknown event 'event_name'. Вы можете переопределить это и заставить запрос вместо этого производить предупреждение для несуществующих событий, используя IF EXISTS.

Это запрос требует привилегии EVENT для схемы, к которой принадлежит удаляемое событие.

14.1.21. DROP FUNCTION

DROP FUNCTION используется, чтобы удалить сохраненные функции и определяемые пользователем функции (UDF):

14.1.22. DROP INDEX

DROP INDEX index_name ON tbl_name
[algorithm_option | lock_option] ...

algorithm_option:
ALGORITHM [=] {DEFAULT|INPLACE|COPY}

lock_option:
LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
DROP INDEX удаляет индекс index_name из таблицы tbl_name. Отображен на ALTER TABLE, чтобы удалить индекс. См. раздел 14.1.7.

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

DROP INDEX `PRIMARY` ON t;
ALGORITHM и LOCK могут быть указаны. Они влияют на табличный метод копирования и уровень параллелизма для чтения и записи таблицы в то время, как индекс изменяется. У них есть то же самое значение, что ALTER TABLE. См. раздел 14.1.7.

14.1.23. DROP PROCEDURE и DROP FUNCTION

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
Этот запрос используется, чтобы удалить хранимую процедуру или функцию. Таким образом, указанная подпрограмма удалена из сервера. Вы должны иметь привилегию ALTER ROUTINE для подпрограммы. Если включена automatic_sp_privileges , эта привилегия и EXECUTE предоставлены автоматически создателю, когда подпрограмма создана и удалены у создателя, когда подпрограмма удалена. См. раздел 21.2.2.

IF EXISTS расширение MySQL. Это препятствует ошибке, если процедура или функция не существуют. Предупреждение произведено, которое может быть рассмотрено с SHOW WARNINGS .

DROP FUNCTION также используется, чтобы удалить определяемые пользователем функции (см. раздел 14.7.3.2).

14.1.24. DROP SERVER

DROP SERVER [ IF EXISTS ] server_name
Удаляет определение сервера для названного сервера server_name. The Соответствующая строка в mysql.servers удалена. Это запрос требует привилегию SUPER.

Удаление сервера для таблицы не затрагивает таблицы FEDERATED, которые использовали эту информацию о соединении, когда они создавались. См. раздел 14.1.14 .

DROP SERVER не закрывает транзакцию.

DROP SERVER не записан в двоичный журнал, независимо от формата журналирования, который используется.

14.1.25. DROP TABLE

DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
DROP TABLE удаляет одну или более таблиц. Вы должны иметь привилегию DROP для каждой таблицы. Все табличные данные и табличное определение удалены, так что будьте осторожны ! Если какая-либо из таблиц, названных в списке параметров, не существует, MySQL возвращает ошибку, указывая по имени, какие несуществующие таблицы не удалось удалить, но удаляет все таблицы в списке, которые действительно существуют.

Когда таблица удалена, пользовательские привилегии на таблице не удалены автоматически. См. раздел 14.7.1.6.

Для разделенной таблицы DROP TABLE удаляет табличное определение, все его разделение и все данные, которые хранились в разделении. Это также удаляет определения разделения, связанные с удаленной таблицей.

IF EXISTS препятствует ошибке для таблиц, которые не существуют. NOTE произведен для каждой несуществующей таблицы, используя IF EXISTS. См. раздел 14.7.5.40 .

RESTRICT и CASCADE разрешены, чтобы сделать проще портирование. В MySQL 8.0 ничего они не делают.

DROP TABLE автоматически закрывает текущую активную транзакцию, если Вы не используете TEMPORARY.

TEMPORARY имеет следующие эффекты:

Применение TEMPORARY хороший способ гарантировать, что Вы случайно не удаляете не-TEMPORARY таблицу.

14.1.26. DROP TABLESPACE

DROP TABLESPACE tablespace_name
   [ENGINE [=] engine_name]
Этот запрос используется, чтобы удалить общее табличное пространство InnoDB, которое создавалось, используя CREATE TABLESPACE (см. раздел 14.1.16).

Все таблицы должны быть исключены из табличного пространства до DROP TABLESPACE. Если табличное пространство не пусто, DROP TABLESPACE возвращает ошибку.

tablespace_name чувствительный к регистру идентификатор в MySQL.

ENGINE: Определяет механизм хранения, который использует табличное пространство, где engine_name название механизма хранения. В настоящее время только InnoDB поддержан. Вы не должны определить ENGINE = InnoDB, если InnoDB определен как механизм хранения по умолчанию ( default_storage_engine=InnoDB).

DROP TABLESPACE поддержан с InnoDB с MySQL 5.7.6. В более ранних выпусках DROP TABLESPACE поддерживает NDB, MySQL Cluster. DROP TABLESPACE поддерживает NDB в MySQL 5.7 когда MySQL Cluster переходит кодовой базы MySQL 5.7. Последняя версия MySQL Cluster основана на MySQL 5.6.

Примечания

Пример

Этот пример демонстрирует, как удалить общее табличное пространство InnoDB. Общее табличное пространство ts1 создается с единственной таблицей. Прежде чем удалить табличное пространство, таблица должна быть удалена.

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> DROP TABLE t1;
Query OK, 0 rows affected (0.01 sec)

mysql> DROP TABLESPACE ts1;
Query OK, 0 rows affected (0.01 sec)

14.1.27. DROP TRIGGER

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
Этот запрос удаляет триггер. Имя хемы (базы данных) является дополнительным. Если схема опущена, триггер исключен из схемы по умолчанию. DROP TRIGGER требует привилегию TRIGGER для таблицы с триггером.

IF EXISTS препятствовует ошибке для триггера, который не существует. См. раздел 14.7.5.40.

Триггеры для таблицы также удалены, если Вы удаляете таблицу.

14.1.28. DROP VIEW

DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
DROP VIEW удаляет одно или более представлений. Вы должны иметь привилегию DROP для каждого представления. Если какое-либо из представлений, названных в списке параметров, не существует, MySQL возвращает ошибку, указывая по имени, какие несуществующие представления это было неспособно удалить, но удаляет все представления в списке, которые действительно существуют.

IF EXISTS препятствует ошибке для представлений, которые не существуют. См. раздел 14.7.5.40.

RESTRICT и CASCADE, если дано, разобраны и проигнорированы.

14.1.29. RENAME TABLE

RENAME TABLE tbl_name TO new_tbl_name
[, tbl_name2 TO new_tbl_name2] ...
Это запрос переименовывает одну или более таблиц. Работа сделана атомарно, что означает, что никакой другой сеанс не может получить доступ ни к одной из таблиц в то время, как переименование работает.

Например, таблица old_table может быть переименована new_table:

RENAME TABLE old_table TO new_table;
Этот запрос эквивалентен ALTER TABLE:
ALTER TABLE old_table RENAME new_table;
Если запрос переименовывает больше, чем одну таблицу, операции сделаны слева направо. Если Вы хотите поменять два имени таблиц, Вы можете сделать так (tmp_table пока нет):
RENAME TABLE old_table TO tmp_table, new_table TO old_table,
       tmp_table TO new_table;
MySQL проверяет целевое имя таблицы прежде, чем проверить, существует ли исходная таблица. Например, если new_table уже есть, а old_table пока нет, следующий запрос терпит неудачу, как показано здесь:
mysql> SHOW TABLES;
+----------------+
| Tables_in_mydb |
+----------------+
| table_a        |
+----------------+
1 row in set (0.00 sec)

mysql> RENAME TABLE table_b TO table_a;
ERROR 1050 (42S01): Table 'table_a' already exists
Если две базы данных находятся на той же самой файловой системе, Вы можете использовать RENAME TABLE, чтобы перемещать таблицу от одной базы данных в другую:
RENAME TABLE current_db.tbl_name
       TO other_db.tbl_name;
Вы можете использовать этот метод, чтобы переместить все таблицы от одной базы данных в другую, в действительности переименовывая базу данных. У MySQL нет никакого спецзапроса, чтобы выполнить эту задачу.

Если есть какие-либо триггеры, связанные с таблицей, которая перемещена в иную базу данных, запрос терпит неудачу с ошибкой Trigger in wrong schema.

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

RENAME TABLE также работает для представлений, пока Вы не пытаетесь переименовать представление в иную базу данных.

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

Когда Вы выполняете RENAME TABLE, у Вас не может быть никаких заблокированных таблиц или активных транзакций. Вы должны также иметь привилегии ALTER и DROP на оригинальной таблице, CREATE и INSERT на новой таблице.

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

Вы не можете использовать RENAME TABLE, чтобы переименовать таблицу TEMPORARY. Однако, Вы можете использовать ALTER TABLE.

Подобно RENAME TABLE, ALTER TABLE ... RENAME может также использоваться, чтобы переместить таблицу в иную базу данных. Независимо от запроса, используемого, чтобы выполнить переименовывание, если работа переместила бы таблицу в базу данных, расположенную в иной файловой системе, успех результата определен платформой и зависит от основных требований операционной системы, используемых, чтобы переместить табличные файлы.

14.1.30. TRUNCATE TABLE

TRUNCATE [TABLE] tbl_name
TRUNCATE TABLE освобождает таблицу полностью. Это требует привилегии DROP. Логически TRUNCATE TABLE это DELETE, который удаляет все строки, или последовательность DROP TABLE и CREATE TABLE.

В MySQL 8.0 TRUNCATE TABLE отображен на DROP TABLE и CREATE TABLE. В результате этого изменения TRUNCATE TABLE является временно не атомным. Сьой сервера во время TRUNCATE TABLE может привести к удаленной таблице и ограничениям внешнего ключа в системных таблицах InnoDB SYS_FOREIGN и SYS_FOREIGN_COLS.

Чтобы достигнуть высокой производительности, TRUNCATE TABLE обходит метод DML удаления данных. Таким образом, это не может быть откачено, это не вызывает триггеры ON DELETE и это не может быть выполнено для таблиц InnoDB с родительско-дочерними отношениями внешнего ключа.

Хотя TRUNCATE TABLE подобно DELETE, это классифицировано как запрос DDL, а не запрос DML. Это отличается от DELETE:

TRUNCATE TABLE закрывает все обработчики для таблицы, которые были открыты с HANDLER OPEN.

TRUNCATE TABLE пишется в репликацию как DROP TABLE и CREATE TABLE, то есть DDL вместо DML. Это вследствие того, что, используя InnoDB и другие транзакционные механизмы хранения, где операционный уровень изоляции не разрешает основанное на запросе журналирование ( READ COMMITTED или READ UNCOMMITTED), запрос не был зарегистрирован и копировался, используя режим STATEMENT или MIXED (Bug #36763).

В MySQL 5.7 и ранее на системе с большим буферным пулом и включенным innodb_adaptive_hash_index TRUNCATE TABLE может вызвать временное падение системной работы из-за просмотра LRU, который произошел, когда удаление индекса адаптивного хеша таблицы записано (Bug #68184). Переотображение TRUNCATE TABLE на DROP TABLE и CREATE TABLE в MySQL 8.0 избегает проблематичного просмотра LRU.

TRUNCATE TABLE может использоваться с Performance Schema, но эффект состоит в том, чтобы сбросить сводные столбцы к 0 или NULL, а не удалению строк. См. раздел 23.9.15.

14.2. Манипуляции данными

14.2.1. CALL

CALL sp_name([parameter[,...]])
CALL sp_name[()]
CALL вызывает хранимую процедуру, которая была определена ранее с CREATE PROCEDURE.

Хранимые процедуры, которые не берут параметров, могут быть вызваны без круглых скобок. Таким образом, CALL p() и CALL p аналогичны.

CALL может передать назад значения, используя параметры, которые объявлены как OUT или INOUT. Когда процедура возвращается, программа клиента может также получить число строк, затронутых для заключительного запроса, выполненного в пределах подпрограммы: на уровне SQL вызовите ROW_COUNT(), из C API вызовите mysql_affected_rows().

Чтобы возвращать значение из процедуры, используя параметр OUT или INOUT, передайте параметр посредством пользовательской переменной, а затем проверьте значение переменной после возвращений процедуры. Если Вы вызываете процедуру изнутри другой хранимой процедуры или функции, Вы можете также передать обычный параметр или местную переменную как параметр IN или INOUT. Для INOUT инициализируйте его значение прежде, чем передать к процедуре. Следующая процедура имеет параметры OUT, которые процедура устанавливает к текущей версии сервера, и значение INOUT, которое процедура постепенно увеличивает:

CREATE PROCEDURE p (OUT ver_param VARCHAR(25), INOUT incr_param INT)
BEGIN
  # Set value of OUT parameter
  SELECT VERSION() INTO ver_param;
  # Increment value of INOUT parameter
  SET incr_param = incr_param + 1;
END;
Прежде, чем вызвать процедуру, инициализируйте переменную, которую передадут как INOUT. После запроса процедуры значения этих двух переменных будут установлены или изменены:
mysql> SET @increment = 10;
mysql> CALL p(@version, @increment);
mysql> SELECT @version, @increment;
+--------------+------------+
| @version     | @increment |
+--------------+------------+
| 5.5.3-m3-log | 11         |
+--------------+------------+
В готовом запросе CALL, используемом с PREPARE и EXECUTE, заполнители могут использоваться для параметров IN, OUT и INOUT. Эти типы параметров могут использоваться следующим образом:
mysql> SET @increment = 10;
mysql> PREPARE s FROM 'CALL p(?, ?)';
mysql> EXECUTE s USING @version, @increment;
mysql> SELECT @version, @increment;
+--------------+------------+
| @version     | @increment |
+--------------+------------+
| 5.5.3-m3-log | 11         |
+--------------+------------+
Чтобы написать программу на C, которая использует CALL, чтобы выполнить хранимые процедуры, которые производят наборы результатов, флаг CLIENT_MULTI_RESULTS должен быть включен. Это потому, что каждый вызов CALL возвращает результат, чтобы указать на состояние запроса, в дополнение к любым наборам результатов, которые могли бы быть возвращены запросами, выполненными в пределах процедуры. CLIENT_MULTI_RESULTS должен также быть включен, если CALL используется, чтобы выполнить любую хранимую процедуру, которая содержит готовые запросы. Не может быть определено, когда такая процедура загружена, произведут ли те запросы наборы результатов, таким образом, будет необходимо предположить, что они будут.

CLIENT_MULTI_RESULTS может быть включен, когда Вы вызываете mysql_real_connect() , явно, передавая CLIENT_MULTI_RESULTS непосредственно, или неявно, передавая CLIENT_MULTI_STATEMENTS (который также включает CLIENT_MULTI_RESULTS). В MySQL 8.0 CLIENT_MULTI_RESULTS включен по умолчанию.

Чтобы обработать результат CALL, используя mysql_query() или mysql_real_query() , используйте цикл, который вызывает mysql_next_result(), чтобы определить, есть ли больше результатов. Для примера см. раздел 25.8.17.

В MySQL 8.0 программы на C могут использовать интерфейс готового запроса, чтобы выполнить CALL и обратиться к параметрам OUT и INOUT. Это сделано, обрабатывая результат CALL , используя цикл, который вызывает mysql_stmt_next_result() , чтобы определить, есть ли больше результатов. Для примера см. раздел 25.8.20. Языки, которые обеспечивают интерфейс MySQL, могут использовать подготовленный CALL, чтобы непосредственно получить параметры процедуры OUT и INOUT.

В MySQL 8.0 метаданные, измененные объектами, упомянутыми сохраненными программами, обнаружены и вызывают автоматический перепарсинг затронутых запросов, когда программа затем выполнена. Для получения дополнительной информации см. раздел 9.10.4.

14.2.2. DELETE

DELETE это запрос DML, который удаляет строки из таблицы.

Однотабличный синтаксис

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[PARTITION (partition_name,...)]
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
DELETE удаляет строки из tbl_name и возвращает число удаленных строк. Чтобы проверить число удаленных строк, вызовите ROW_COUNT(), см. раздел 13.14.

Главные предложения

Условия в дополнительном WHERE идентифицирует, которые строки удалить. Без WHERE все строки удалены.

where_condition выражение, которое оценивается к истине для каждой строки, которая будет удалена. Это определено как описано в разделе 14.2.9.

Если указан ORDER BY, строки удалены в порядке, который определен. LIMIT устанавливает границу числа строк, которые могут быть удалены. Эти пункты относятся к единственной таблице, но не к удалению из нескольких таблиц.

Многотабличный синтаксис

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[.*] [, tbl_name[.*]] ...
FROM table_references
[WHERE where_condition]
Или:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[.*] [, tbl_name[.*]] ...
USING table_references
[WHERE where_condition]

Привилегии

Вы нуждаетесь в привилегии DELETE на таблице, чтобы удалить строки из нее. Вы нуждаетесь только в привилегии SELECT для любых столбцов, которые только считаны, такие как названные в WHERE.

Работа

Когда Вы не должны знать число удаленных строк, TRUNCATE TABLE более быстрый способ освободить таблицу, чем DELETE без WHERE. В отличие от этого, TRUNCATE TABLE не может использоваться в пределах транзакции, или если у Вас есть блокировка на таблице. См. разделы 14.1.30 и 14.3.5.

Скорость операции удаления может также быть затронута факторами, обсужденными в разделе 9.2.2.3.

Чтобы гарантировать, что данный запрос DELETE не занимает слишком много времени, параметр LIMIT row_count для DELETE определяет максимальное количество строк, которые будут удалены. Если число строк, чтобы удалить, больше предела, повторите DELETE до числа затронутых строк меньше LIMIT.

Подзапросы

Вы не можете удалить из таблицы и выбрать из той же самой таблицы в одном подзапросе.

Разделенные таблицы

DELETE поддерживает явный выбор разделения, используя опцию PARTITION, которая берет список разделенных запятой значений названий из одного или более разделов или подразделов (или обоих), из которых можно выбрать строки, которые будут исключены. Проигнорировано разделение, не включенное в список. Учитывая разделенную таблицу t с разделом p0, выполнение DELETE FROM t PARTITION (p0) имеет тот же самый эффект на таблицу как выполнение ALTER TABLE t TRUNCATE PARTITION (p0), в обоих случаях все строки в разделе p0 удалены.

PARTITION может использоваться наряду с WHERE, тогда условие проверено только на строках в перечисленном разделе. Например, DELETE FROM t PARTITION (p0) WHERE c < 5 удаляет строки только из раздела p0 для которых верно условие c < 5, строки в любом другом разделе не проверены и таким образом не затронуты DELETE.

Опция PARTITION может также использоваться в многотабличном DELETE. Вы можете использовать до одной такой опции на таблицу, названную в опции FROM.

См. раздел 20.5.

Столбцы Auto-Increment

Если Вы удаляете строку, содержащую максимальное значение для AUTO_INCREMENT, значение не использовано снова для MyISAM или InnoDB. Если Вы удаляете все строки в таблице с DELETE FROM tbl_name (без WHERE) в режиме autocommit, последовательность запускается для всех механизмов хранения, кроме InnoDB и MyISAM. Есть некоторые исключения к этому поведению для InnoDB, см. раздел 16.8.5.

Для MyISAM Вы можете определить второй столбец AUTO_INCREMENT в многостолбцовом ключе. В этом случае повторное использование значений, удаленных из вершины последовательности, происходит даже для MyISAM. См. раздел 4.6.9.

Модификаторы

DELETE поддерживает следующие модификаторы:

Порядок удаления

Если DELETE включает ORDER BY, строки удалены в порядке, определенном пунктом. Это полезно прежде всего в соединении с LIMIT. Например, следующий запрос находит строки, соответствующие WHERE, сортирует их по timestamp_column и удаляет первую (самый старую):

DELETE FROM somelog WHERE user = 'jcole'
       ORDER BY timestamp_column LIMIT 1;
ORDER BY также помогает удалить строки в порядке, требуемом, чтобюы избегать нарушений ссылочной целостности.

Таблицы InnoDB

Если Вы удаляете много строк из большой таблицы, Вы можете превысить табличный размер блокировки для InnoDB. Чтобы избежать этой проблемы или просто минимизировать время, когда таблица остается заблокированной, следующая стратегия (которая не использует DELETE вообще), могла бы быть полезным:

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

    INSERT INTO t_copy SELECT * FROM t WHERE ... ;
    
  2. Используйте RENAME TABLE, чтобы атомарно переместить оригинальную таблицу из пути и переименовать копию к настоящему имени:
    RENAME TABLE t TO t_old, t_copy TO t;
    
  3. Удалите оригинальную таблицу:
    DROP TABLE t_old;
    

Никакие другие сеансы не могут получить доступ к вовлеченным таблицам в то время, как работает RENAME TABLE , таким образом, переименование не подвергается проблемам параллелизма. См. раздел 14.1.29.

Таблицы MyISAM

В MyISAM удаленные строки поддержаны в связанном списке и последующие INSERT повторно используют старые позиции строки. Чтобы восстановить неиспользуемое место и уменьшить размеры файла, используйте OPTIMIZE TABLE или myisamchk, чтобы реорганизовать таблицы. OPTIMIZE TABLE легче использовать, но myisamchk быстрее. См. разделы 14.7.2.4 и 5.6.4.

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

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

  1. Составьте таблицу, которая содержит индексированный столбец AUTO_INCREMENT.

  2. Вставьте много строк в таблицу. Каждая вставка в индекс добавляет значение к верхнему концу индекса.
  3. Удалите блок строк на нижнем конце диапазона столбца, используя DELETE QUICK.

В этом сценарии блоки индекса, связанные с удаленными значениями, становятся сильно пустыми, но не слиты с другим блоками индекса из-за использования QUICK. Они остаются такими, когда новые вставки происходят, потому что новые строки не имеют индексных значений в удаленном диапазоне. Кроме того, они остаются пустыми даже если Вы позже используете DELETE без QUICK, если некоторые из удаленных индексных значений лежат в блоках в пределах или смежных с незаполненными блоками. Чтобы исправить неиспользованное индексное пространство при этих обстоятельствах, используют OPTIMIZE TABLE.

Если Вы собираетесь удалить много строк из таблицы, могло бы быть быстрее, использовать DELETE QUICK сопровождаемый OPTIMIZE TABLE. Это восстанавливает индексирование вместо того, чтобы делать много операций слияния индексных блоков.

Мультитабличное удаление

Вы можете определить много таблиц в DELETE, чтобы удалить строки из одной или более таблиц в зависимости от условия в WHERE. Вы не можете использовать ORDER BY или LIMIT в многотабличном DELETE. table_references перечисляет таблицы, вовлеченные в соединение, как описано в разделе 14.2.9.2.

Для первого многотабличного синтаксиса соответствуют только строки от таблиц, перечисленных перед FROM. Для второго соответствуют только строки от таблиц, перечисленных в FROM (до USING). Эффект состоит в том, что Вы можете удалить строки из многих таблиц в то же самое время и иметь дополнительные таблицы, которые используются только для того, чтобы искать:

DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3
       WHERE t1.id=t2.id AND t2.id=t3.id;
Или:
DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3
       WHERE t1.id=t2.id AND t2.id=t3.id;
Эти запросы используют все три таблицы, ища строки, чтобы удалить, но удаляют соответствующие строки только из таблиц t1 и t2.

Предыдущее использование в качестве примера INNER JOIN, но мультитабличный DELETE может использовать другие типы соединения, разрешенные в SELECT, например, LEFT JOIN. Например, чтобы удалить строки, которые существуют в t1, у которых нет никакого соответствия в t2, используйте LEFT JOIN:

DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Синтаксис допускает .* после каждого tbl_name для совместимости с Access.

Если Вы используете многотабличный DELETE с таблицами InnoDB, для которых есть ограничения внешнего ключа, оптимизатор MySQL мог бы обработать таблицы в порядке, который отличается от их родительских/дочерних отношений. В этом случае запрос терпит неудачу и откатывается. Вместо этого Вы должны удалить из единственной таблицы и использовать ON DELETE, который обеспечивает InnoDB, чтобы заставить другие таблицы быть измененными соответственно.

Если Вы объявляете псевдоним для таблицы, Вы должны использовать псевдоним, обращаясь к таблице:

DELETE t1 FROM test AS t1, test2 WHERE ...

Табличные псевдонимы в многотабличном DELETE должны быть объявлены только в части table_references. В другом месте ссылки псевдонима разрешены, но не декларации псевдонима.

Правильно:

DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2
       WHERE a1.id=a2.id;

DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2
       WHERE a1.id=a2.id;
Неправильно:
DELETE t1 AS a1, t2 AS a2 FROM t1 INNER JOIN t2 WHERE a1.id=a2.id;
DELETE FROM t1 AS a1, t2 AS a2 USING t1 INNER JOIN t2 WHERE a1.id=a2.id;

14.2.3. DO

DO expr [, expr] ...
DO выполняет выражения, но не возвращает результатов. В большинстве отношений DO сокращение для SELECT expr, ..., но имеет преимущество, что это немного быстрее, когда Вы не заботитесь о результате.

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

Пример: Этот SELECT тормозит запросы, но также и производит набор результатов:

mysql> SELECT SLEEP(5);
+----------+
| SLEEP(5) |
+----------+
| 0        |
+----------+
1 row in set (5.02 sec)
DO, с другой стороны, делает такую же паузу, не производя набор результатов:
mysql> DO SLEEP(5);
Query OK, 0 rows affected (4.99 sec)
Это могло быть полезно, например в сохраненной функции или триггере которые запрещают запросы, которые производят наборы результатов.

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

14.2.4. HANDLER

HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name
        { = | <= | >= | < | > } (value1,
        value2,...)
        [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name
        { FIRST | NEXT | PREV | LAST }
        [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
        [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
HANDLER обеспечивает прямой доступ к табличным интерфейсам механизма хранения. Это доступно для InnoDB и MyISAM.

HANDLER ... OPEN открывает таблицу, делая это доступным последующму использованию HANDLER ... READ. Этот табличный объект не использован совместно другими сеансами и не закрыт до HANDLER ... CLOSE или конца сеанса.

Если Вы открываете таблицу, используя псевдоним, дальнейшие ссылки на открытую таблицу с другим HANDLER должны использовать псевдоним, а не имя таблицы. Если Вы не используете псевдоним, но открываете таблицу, используя имя таблицы, квалифицированное именем базы данных, дальнейшие ссылки должны использовать неквалифицированное имя таблицы. Например, для таблицы, открытой, используя mydb.mytable, дальнейшие ссылки должны использовать mytable.

Первый синтаксис HANDLER ... READ приносит строку, где указанный индекс удовлетворяет данные значения и соблюдает WHERE. Если у Вас есть многостолбцовый индекс, укажите список значений столбцов как список разделенных запятой значений. Или определите значения для всех столбцов в индексировании, или определите значения для крайнего левого префикса индекса столбцов. Предположите, что индекс my_idx включает три столбца col_a, col_b и col_c, в этом порядке. HANDLER может определить значения для всех трех столбцов в индексе или для столбцов в крайнем левом префиксе. Например:

HANDLER ... READ my_idx = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... READ my_idx = (col_a_val,col_b_val) ...
HANDLER ... READ my_idx = (col_a_val) ...
Чтобы использовать HANDLER интерфейс, чтобы обратиться к таблице PRIMARY KEY, используйте заключенный в кавычки идентификатор `PRIMARY`:
HANDLER tbl_name READ `PRIMARY` ...
Второй синтаксис HANDLER ... READ приносит строку от таблицы в порядке индекса, который соответствует WHERE.

Третий синтаксис HANDLER ... READ приносит строку от таблицы в естественном порядке строк, который соответствует WHERE. Это быстрее HANDLER tbl_name READ index_name, когда полное сканирование таблицы желаемо. Естественный порядок строк это порядок, в котором строки сохранены в файле данных. Это запрос работает на InnoDB также, но нет такого понятия, потому что нет никакого отдельного файла с данными.

Без LIMIT все формы HANDLER ... READ принесут единственную строку. Чтобы возвратить определенное число строк, включайте LIMIT. У него есть тот же самый синтаксис, как у SELECT, см. раздел 14.2.9.

HANDLER ... CLOSE закрывает таблицу, которая была открыта HANDLER ... OPEN.

Есть несколько причин использовать интерфейс HANDLER вместо нормального SELECT:

HANDLER несколько низкоуровневый запрос. Например, это не обеспечивает последовательность. Таким образом, HANDLER ... OPEN не берет снимок таблицы, и не блокирует таблицу. Это означает, что после HANDLER ... OPEN табличные данные могут быть изменены (текущим сеансом или другими сеансами), и эти модификации могли бы быть только частично видимыми в HANDLER ... NEXT или HANDLER ... PREV.

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

TRUNCATE TABLE закрывает все обработчики для таблицы, которые были открыты с HANDLER OPEN.

Если таблица сбрасывается с FLUSH TABLES tbl_name WITH READ LOCK, обработчик неявно сбрасывается и теряет свою позицию.

14.2.5. INSERT

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
  col_name=expr
[, col_name=expr] ... ]
Или:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE
  col_name=expr
[, col_name=expr] ... ]
Или:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE
  col_name=expr
[, col_name=expr] ... ]
INSERT вставляет новые строки в существующую таблицу. INSERT ... VALUES и INSERT ... SET формы вставляют строки, основанные на явно указанных значениях. INSERT ... SELECT вставляет строки, выбранные из другой таблицы или таблиц. INSERT ... SELECT рассмотрена в разделе 14.2.5.1.

Вставляя в разделенную таблицу, Вы можете управлять, какие раздел и подраздел принимают новые строки. PARTITION берет список разделенных запятой значений названий одного или более раздела или подразда (или оба) таблицы. Если любая из строк, которые будут вставлены данным INSERT не соответствует одному из перечисленных разделов, INSERT терпит неудачу с ошибкой Found a row not matching the given partition set. См. раздел 20.5.

В MySQL 8.0 DELAYED принято, но проигнорировано сервером. См. раздел 14.2.5.2.

Вы можете использовать REPLACE вместо INSERT, чтобы перезаписывать старые строки. REPLACE копия INSERT IGNORE в обработке новых строк, которые содержат уникальные значения ключа, которые дублируют старые строки: новые строки используются, чтобы заменить старые строки вместо того, чтобы отказать, см. раздел 14.2.8.

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

Значения столбцов могут быть даны несколькими способами:

INSERT с использованием VALUES может вставить многократные строки. Чтобы сделать это, включайте многократные списки значений столбцов, каждый в пределах круглых скобок и отделенный запятыми. Пример:

INSERT INTO tbl_name (a,b,c)
       VALUES(1,2,3), (4,5,6), (7,8,9);
Список значений для каждой строки должен быть приложен в пределах круглых скобок. Следующий запрос незаконный, потому что число значений в списке не соответствует числу имен столбцов:
INSERT INTO tbl_name (a,b,c)
       VALUES(1,2,3,4,5,6,7,8,9);
VALUE синоним VALUES этом контексте. Ни один ничего не подразумевает о числе списков значений, и может использоваться, есть ли единственный список значений или многократные списки.

Число затронутых строк для INSERT может быть получено, используя ROW_COUNT() (см. раздел 13.14) или mysql_affected_rows() C API (см. раздел 25.8.7.1).

Если Вы используете INSERT ... VALUES с многократными списками значения или INSERT ... SELECT, запрос возвращает информационную строку в этом формате:

Records: 100 Duplicates: 0 Warnings: 0
Records указывает на число строк, обработанных запросом. Это не обязательно число строк, фактически вставленных, потому что Duplicates может быть отличным от нуля. Duplicates указывает на число строк, которые не могли быть вставлены, потому что они дублируют некоторые существующие уникальные индексные значения. Warnings указывает на число попыток вставить значения столбцов, которые были проблематичны в некотором роде. Предупреждения могут произойти при любом из следующих условий:

Если произведенный столбец вставлен явно, единственное разрешенное значение DEFAULT. См. раздел 14.1.15.5.

Если Вы используете C API, информационная строка может быть получена, вызывая mysql_info(), см. раздел 25.8.7.36.

Если INSERT вставляет строку в таблицу, которая имеет AUTO_INCREMENT, Вы можете считать значение для этого столбца при использовании SQL LAST_INSERT_ID(). Из C API используйте mysql_insert_id(). Однако, Вы должны отметить, что две функции не всегда ведут себя тождественно. Поведение INSERT относительно AUTO_INCREMENT рассмотрено в разделах 13.14 и 25.8.7.38.

INSERT поддерживает следующие модификаторы:

Вставка в таблицу требует привилегии INSERT для таблицы. Если ON DUPLICATE KEY UPDATE используется, и дубликат ключа вызываетUPDATE вместо этого, запрос требует привилегию UPDATE для столбцов, которые будут обновлены. Для столбцов, которые считаны, но не изменены, нужна только SELECT (для столбцов в правой части col_name=expr в ON DUPLICATE KEY UPDATE).

В MySQL 8.0 INSERT, затрагивающий разделенную таблицу, используя такой механизм хранения, как MyISAM, который использует блокировки на уровне таблицы, блокирует только тот раздел, в который фактически вставлены строки. Для механизмов хранения вроде InnoDB, которые используют блокировку на уровне строки, никакая блокировка раздела не имеет места. См. Partitioning and Locking.

14.2.5.1. INSERT ... SELECT

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
С INSERT ... SELECT Вы можете быстро вставить много строк в таблицу от одной или многих таблиц. Например:
INSERT INTO tbl_temp2 (fld_id)
       SELECT tbl_temp1.fld_order_id
       FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Следующие условия держатся для INSERT ... SELECT:

Вы можете явно выбрать, какой раздел или подраздел (или оба) источника или таблицы назначения (или обеих) должны использоваться с опцией PARTITION после названия таблицы. Когда PARTITION используется с названием исходной таблицы в части SELECT, строки выбраны только из раздела или подраздела, названного в его списке разделов. Когда PARTITION используется с названием целевой таблицы для части INSERT, тогда должно быть возможно вставить все строки в раздел или подраздел, названный в списке разделов после опции, иначе INSERT ... SELECT терпит неудачу. Для получения дополнительной информации и примеров см. раздел 20.5.

В части значений ON DUPLICATE KEY UPDATE Вы можете обратиться к столбцам в других таблицах, пока Вы не используете GROUP BY в части SELECT . Один побочный эффект состоит в том, что Вы должны квалифицировать групповые имена столбцов в части значений.

Порядок, в котором строки возвращены SELECT без ORDER BY не определен. Это означает, что, используя репликацию нет никакой гарантии, что такой SELECT возвращает в том же самом порядке на ведущем и ведомом устройствах, это может привести к несогласованностям между ними. Чтобы препятствовать этому, Вы должны всегда писать INSERT ... SELECT, которые должны копироваться как INSERT ... SELECT ... ORDER BY column . Выбор column не имеет значения, пока тот же самый порядок строк проведен в жизнь на ведущем и на ведомом устройствах. См. также раздел 19.4.1.17.

Из-за этой проблемы INSERT ... SELECT ON DUPLICATE KEY UPDATE и INSERT IGNORE ... SELECT отмечены как опасные для основанной на запросе репликации. С этим изменением такие запросы производят предупреждение в журнале, используя основанный на запросе режим и зарегистрированы, используя основанный на строке формат, используя режим MIXED (Bug #11758262, Bug #50439).

См. также раздел 19.2.1.1.

В MySQL 8.0 INSERT ... SELECT, который действовал на разделенные таблицы, используя такой механизм хранения, как MyISAM, который использует блокировки на уровне таблицы, блокирует все разделы целевой таблицы. Однако, только тот раздел, который фактически считан из исходной таблицы, заблокирован. Это не происходит с таблицами, используя такие механизмы хранения, как InnoDB, которые работают с блокировкой на уровне строки. См. Partitioning and Locking.

14.2.5.2. INSERT DELAYED

INSERT DELAYED ...
Опция DELAYED для INSERT в MySQL это расширение MySQL к стандартному SQL. В предыдущих версиях MySQL это может использоваться для определенных видов таблиц (таких, как MyISAM), таким образом это, когда клиент использует INSERT DELAYED, регистрируется сервером сразу, и строка стоит в очереди, чтобы быть вставленной, когда таблица не находится в использовании никаким другим потоком.

DELAYED устарела в MySQL 5.6.6. В MySQL 8.0 DELAYED не поддерживается. Сервер признает, но игнорирует DELAYED, обрабатывает вставку как неотсроченную вставку и производит предупреждение ER_WARN_LEGACY_SYNTAX_CONVERTED (INSERT DELAYED is no longer supported. The statement was converted to INSERT). DELAYED намечено для удаления в будущем выпуске.

14.2.5.3. INSERT ... ON DUPLICATE KEY UPDATE

Если Вы определяете ON DUPLICATE KEY UPDATE, и строка вставлена, которая вызвала бы дубликат значения в индексе UNIQUE или PRIMARY KEY, MySQL применит UPDATE из старой строки. Например, если столбец a объявлен как UNIQUE и содержит значение 1, следующие два запроса имеют подобный эффект:

INSERT INTO table (a,b,c) VALUES (1,2,3)
       ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
Эффекты не идентичны для таблицы InnoDB, где a столбец auto-increment. Со столбцом auto-increment INSERT увеличивает значение auto-increment, но UPDATE не делает.

ON DUPLICATE KEY UPDATE может содержать многократные назначения столбца, отделенные запятыми.

С ON DUPLICATE KEY UPDATE значение затронутых строк за строку 1, если строка вставлена как новая строка, 2, если существующая строка обновлена, и 0, если существующая строка установлена в ее текущее значение. Если Вы определяете CLIENT_FOUND_ROWS для mysql_real_connect() соединяясь с mysqld , значение затронутых строк 1 (не 0), если существующая строка установлена в ее текущее значение.

Если b также уникален, INSERT эквивалентен UPDATE:

UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
Если a=1 OR b=2 соответствует несколько строк, только одна обновлена. Вообще, Вы должны попытаться избегать использования ON DUPLICATE KEY UPDATE на таблицах с уникальным многократным индексом.

Вы можете использовать VALUES(col_name) в UPDATE, чтобы обратиться к значениям столбцов из части INSERT запроса INSERT ... ON DUPLICATE KEY UPDATE. Другими словами, VALUES(col_name ) в ON DUPLICATE KEY UPDATE относится к значению col_name было бы вставлено, если бы не было никакой ошибки дублирования ключа. Эта функция особенно полезна при вставке многих строк. VALUES() является значащей только в INSERT ... UPDATE, иначе вернет NULL:

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
       ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
Этот запрос идентичен следующим двум запросам:
INSERT INTO table (a,b,c) VALUES (1,2,3)
       ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
       ON DUPLICATE KEY UPDATE c=9;
Если таблица содержит AUTO_INCREMENT и INSERT ... ON DUPLICATE KEY UPDATE вставляет или обновляет строку, LAST_INSERT_ID() возвращает значение AUTO_INCREMENT.

DELAYED проигнорирована, когда Вы используете ON DUPLICATE KEY UPDATE.

Поскольку результаты INSERT ... SELECT зависят от упорядочивания строк из SELECT и этот порядок не может всегда гарантироваться, возможно, регистрируя INSERT ... SELECT ON DUPLICATE KEY UPDATE для ведущего и ведомого устройств получить разные результаты. Таким образом, INSERT ... SELECT ON DUPLICATE KEY UPDATE отмечены как опасные для основанной на запросе репликации. С этим изменением такие запросы производят предупреждение в журнале, используя основанный на запросе режим и зарегистрированы, используя основанный на строке формат, используя режим MIXED. Кроме того, INSERT ... ON DUPLICATE KEY UPDATE для таблицы, имеющей больше чем один уникальный или первичный ключ, также отмечен как опасный (Bug #11765650, Bug #58637), см. раздел 19.2.1.1.

В MySQL 8.0 INSERT ... ON DUPLICATE KEY UPDATE на разделенной таблице, используя механизм хранения MyISAM, который использует блокировки на уровне таблицы, блокирует любой раздел таблицы, в котором обновлен ключевой столбец раздела. Для механизмов хранения, которые используют блокировку на уровне строки, это не так. См. Partitioning and Locking.

14.2.6. LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[PARTITION (partition_name,...)]
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number {LINES | ROWS}]
[(col_name_or_user_var,...)]
[SET col_name = expr,...]
LOAD DATA INFILE читает строки из текстового файла в таблицу на сверхвысокой скорости. LOAD DATA INFILE дополнение SELECT ... INTO OUTFILE , см. раздел 14.2.9.1). Чтобы писать данные из таблицы в файл, надо использовать SELECT ... INTO OUTFILE. Чтобы считать файл назад в таблицу, надо использовать LOAD DATA INFILE. Синтаксис FIELDS и LINES тот же самый для обоих запросов. Оба пункта являются дополнительными, но FIELDS должен предшествовать LINES, если оба определены.

Вы можете также загрузить файлы с данными при использовании mysqlimport , это работает, посылая серверу запрос LOAD DATA INFILE. Опция --local заставляет mysqlimport читать файлы с данными из хоста клиента. Вы можете определить --compress, чтобы получить лучшую работу по медленным сетям, если клиент и сервер поддерживают сжатый протокол. См. раздел 5.5.5.

Имя файла должно быть дано как буквальная строка. На Windows определите наклонные черты влево в путях как наклонные черты вправо или удвоенные наклонные черты влево. character_set_filesystem управляет интерпретацией имени файла.

LOAD DATA поддерживает явный выбор раздел, используя PARTITION со списком разделенных запятой значений одного или более названий разделов, подразделов или обоих. Когда эта опция используется, если какие-либо строки из файла не могут быть вставлены ни в один раздел, названный в списке, запрос терпит неудачу с ошибкой Found a row not matching the given partition set. См. раздел 20.5.

Для разделенных таблиц, используя механизмы хранения, которые используют табличные блокировки, например, MyISAM, LOAD DATA не может сократить блокировки раздела. Это не относится к таблицам, использующим механизмы хранения, которые используют блокировку на уровне строки, например, InnoDB. См. Partitioning and Locking.

Сервер использует набор символов, обозначенный character_set_database, чтобы интерпретировать информацию в файле. SET NAMES и установка character_set_client не затрагивают интерпретацию ввода. Если содержание входного файла использует набор символов, который отличается от значения по умолчанию, обычно предпочтительно определить набор символов файла при использовании CHARACTER SET. Набор символов binary определяет отсутствие конвертации.

LOAD DATA INFILE интерпретирует все области в файле как наличие того же самого набора символов, независимо от типов данных столбцов, в которые загружены значения полей. Для правильной интерпретации содержания файла Вы должны гарантировать, что он был написан с правильным набором символов. Например, если Вы пишете файл с данными с mysqldump -T или через SELECT ... INTO OUTFILE в mysql , надо убедиться, что использовали опцию --default-character-set, чтобы вывод был написан в наборе символов, который будет использоваться, когда файл загружен LOAD DATA INFILE.

Невозможно загрузить файлы с данными, которые используют ucs2, utf16, utf16le или utf32.

Если Вы используете LOW_PRIORITY, выполнение LOAD DATA отсрочено, пока никакие другие клиенты не читают из таблицы. Это затрагивает только механизмы хранения, которые используют только блокировку на уровне таблицы (MyISAM, MEMORY и MERGE).

Если Вы определяете CONCURRENT с MyISAM, которая удовлетворяет условию для параллельных вставок (то есть, не содержит свободных блоков в середине), другие потоки могут получить данные от таблицы в то время, как работает LOAD DATA. Эта опция затрагивает исполнение LOAD DATA, даже если никакой другой поток не использует таблицу в то же самое время.

С основанной на строке репликацией CONCURRENT копируется независимо от версии MySQL. С основанной на запросе репликацией CONCURRENT не копируется до MySQL 5.5.1 (см. Bug #34628). См. раздел 19.4.1.18.

LOCAL затрагивает ожидаемое местоположение файла и обработку ошибок, как описано позже. LOCAL применим только если Ваш сервер и Ваш клиент оба были сконфигурированы, чтобы разрешить это. Например, если mysqld был запущен с --local-infile=0, LOCAL не работает. См. раздел 7.1.6.

LOCAL затрагивает, где файл, как ожидают, будет найден:

В не-LOCAL случае эти правила означают, что файл ./myfile.txt считан из каталога данных сервера, тогда как файл myfile.txt считан из каталога базы данных по умолчанию. Например, если база данных значения по умолчанию db1, следующий запрос LOAD DATA читает файл data.txt из каталога базы данных db1, даже при том, что запрос явно загружает файл в таблицу в db2:

LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
Из соображений безопасности, читая текстовые файлы, расположенные на сервере, файлы должны находиться в каталоге базы данных или быть читаемыми учетной записью пользователя, используемой, чтобы выполнить сервер. Кроме того, чтобы использовать LOAD DATA INFILE на файлах сервера Вы должны иметь привилегию FILE. См. раздел 7.2.1. Для не-LOCAL, если secure_file_priv установлена в непустое имя каталога, файл, который будет загружен, должен быть расположен в том каталоге.

Использование LOCAL немного медленнее, чем разрешение серверу получить доступ к файлам непосредственно, потому что содержание файла должен послать по соединению клиент к серверу. С другой стороны, Вы не нуждаетесь в привилегии FILE, чтобы загрузить местные файлы.

LOCAL также меняет обработку ошибок:

REPLACE и IGNORE управляют обработкой входных строк, которые дублируют существующие строки на уникальных значениях ключа:

Чтобы проигнорировать ограничения внешнего ключа во время работы загрузки, установите SET foreign_key_checks = 0 перед LOAD DATA.

Если Вы используете LOAD DATA INFILE на пустой таблице MyISAM, все групповые индексы создаются в отдельном пакете (что касается REPAIR TABLE). Обычно это делает LOAD DATA INFILE намного быстрее, когда Вы имеете много индексов. В некоторых крайних случаях Вы можете создать индексирование еще быстрее, выключая их с ALTER TABLE ... DISABLE KEYS прежде, чем загрузить файл в таблицу и используя ALTER TABLE ... ENABLE KEYS, чтобы пересоздать индексирование после загрузки файла. См. раздел 9.2.2.1.

Для LOAD DATA INFILE и SELECT ... INTO OUTFILE синтаксис FIELDS и LINES одинаков. Оба пункта являются дополнительными, но FIELDS должен предшествовать LINES, если оба определены.

Если Вы определяете FIELDS, каждый из его подпунктов (TERMINATED BY, [OPTIONALLY] ENCLOSED BY и ESCAPED BY) является также дополнительным, за исключением того, что Вы должны определить по крайней мере один из них.

Если Вы не определяете FIELDS или LINES, значения по умолчанию те же самые, как будто Вы написали:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
LINES TERMINATED BY '\n' STARTING BY ''
Наклонная черта влево это символ ESC MySQL в пределах строк в запросах SQL, чтобы определить буквальную наклонную черту влево, Вы должны определить две наклонных черты влево для значения, которое будет интерпретироваться как единственная наклонная черта влево. Escape-последовательности '\t' и '\n' определяют символы tab и newline, соответственно.

Другими словами, по умолчанию в LOAD DATA INFILE спецсимволы обработаны следующим образом, когда ввод читается:

Наоборот значения по умолчанию SELECT ... INTO OUTFILE в выводе:

Если Вы произвели текстовый файл на системе Windows, Вам, возможно, придется использовать LINES TERMINATED BY '\r\n', чтобы считать файл должным образом, потому что программы Windows, как правило, используют два символа в качестве разделителя строки. Некоторые программы, такие как WordPad, могли бы использовать \r как разделитель строки при записи файлов. Чтобы считать такие файлы, надо использовать LINES TERMINATED BY '\r'.

Если у всех строк, которые Вы хотите читать, есть общий префикс, который Вы хотите проигнорировать, Вы можете использовать LINES STARTING BY 'prefix_string', чтобы перескакивать через префикс и что-либо перед ним. Если строка не включает префикс, вся строка пропущена. Предположите, что Вы делаете следующий запрос:

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test
     FIELDS TERMINATED BY ','  LINES STARTING BY 'xxx';
Если файл с данными похож на это:
xxx"abc",1
something xxx"def",2
"ghi",3
Получающиеся строки будут ("abc",1) и ("def",2). Третья строка в файле пропущена, потому что это не содержит префикс.

IGNORE number LINES может использоваться, чтобы проигнорировать строки в начале файла. Например, Вы можете использовать IGNORE 1 LINES, чтобы перескакивать через начальную строку заголовка, содержащую имена столбцов:

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test IGNORE 1 LINES;
Когда Вы используете SELECT ... INTO OUTFILE c LOAD DATA INFILE, чтобы написать данные от базы данных в файл и затем считать файл назад в базу данных позже, опции для обоих запросов должны соответствовать. Иначе LOAD DATA INFILE не будет интерпретировать содержание файла должным образом. Предположите, что Вы используете SELECT ... INTO OUTFILE, чтобы написать файл с областями, разграниченными запятыми:
SELECT * INTO OUTFILE 'data.txt' FIELDS TERMINATED BY ',' FROM table2;
Чтобы считать файл разделенных запятыми значений назад, правильный запрос:
LOAD DATA INFILE 'data.txt' INTO TABLE table2
     FIELDS TERMINATED BY ',';
Если бы вместо этого Вы попытались читать файл запросом, показанным ниже, то это не работало бы, потому что это инструктирует LOAD DATA INFILE искать tab между областями:
LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY '\t';
Вероятный результат состоит в том, что каждая входная строка интерпретировалась бы как единственная область.

LOAD DATA INFILE может использоваться, чтобы считать файлы, полученные из внешних источников. Например, много программ могут экспортировать данные в формате отделенных запятыми значений (CSV). Если строки в таком файле закончены возвратом каретки и новой строкой, запрос, показанный здесь, иллюстрирует опции, которые Вы использовали бы, чтобы загрузить файл:

LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
     FIELDS TERMINATED BY ',' ENCLOSED BY '"'
     LINES TERMINATED BY '\r\n' IGNORE 1 LINES;
Если входные значения не обязательно приложены в пределах кавычек, надо использовать OPTIONALLY перед ENCLOSED BY.

Любая опция может определить пустую строку (''). Если не пуста, значения FIELDS [OPTIONALLY] ENCLOSED BY и FIELDS ESCAPED BY должны быть единственным символом. FIELDS TERMINATED BY, LINES STARTING BY и LINES TERMINATED BY могут быть больше, чем одним символом. Например, чтобы написать строки, которые закончены возвратом каретки/ переводом строки или считать файл, содержащий такие строки, определяют LINES TERMINATED BY '\r\n' clause.

Считать файл, содержащий записи, которые отделены строками, состоящими из %%, можно таким запросом:

CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
       joke TEXT NOT NULL);
LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
     FIELDS TERMINATED BY '' LINES TERMINATED BY '\n%%\n' (joke);
FIELDS [OPTIONALLY] ENCLOSED BY управляет цитированием полей. Для вывода (SELECT ... INTO OUTFILE ), если Вы опускаете слово OPTIONALLY, все области заключены в символ ENCLOSED BY. Пример такого вывода (использующий запятую в качестве полевого разделителя):
"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"
Если указано OPTIONALLY, символ ENCLOSED BY используется только, чтобы приложить значения от столбцов, у которых есть строковый тип данных (CHAR, BINARY, TEXT или ENUM):
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20
Возникновения символа ENCLOSED BY в пределах значения поля оставляют, предварительно помечая их символом ESCAPED BY. Также отметьте, что если Вы определяете пустой ESCAPED BY, возможно неосторожно произвести вывод, который не может быть считан должным образом LOAD DATA INFILE. Например, предыдущий вывод выглядел бы следующим образом, если символ ESC пуст. Заметьте, что вторая область в четвертой строке содержит запятую после кавычки, которая ошибочно заканчивает область:
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20
Для ввода символ ENCLOSED BY, если есть, отрезан от концов значений полей. Это истина, независимо от того, определен ли OPTIONALLY, OPTIONALLY не имеет никакого эффекта на входную интерпретацию. Возникновения символа ENCLOSED BY, которому предшествует символ ESCAPED BY интерпретируются как часть текущего значения поля.

Если область начинается с ENCLOSED BY, экземпляры того символа признаны завершением значения поля, только если сопровождаемы областью или строкой TERMINATED BY. Чтобы избегать двусмысленности возникновений, ENCLOSED BY в пределах значения поля может быть удвоен и интерпретируется как единственный случай символа. Например, если ENCLOSED BY '"' определен, кавычки обработаны как показано здесь:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss  -> The "BIG" boss
The ""BIG"" boss-> The ""BIG"" boss
FIELDS ESCAPED BY определяет, как читать или писать специальные символы:

В определенных случаях взаимодействуют опции:

Обработка NULL изменяется согласно FIELDS и LINES:

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

Некоторые случаи не поддержаны LOAD DATA INFILE:

Следующий пример загружает все столбцы таблицы persondata:

LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
По умолчанию, когда никакой список столбцов не обеспечен в конце LOAD DATA INFILE, входные строки, как ожидают, будут содержать область для каждого столбца таблицы. Если Вы хотите загрузить только некоторые из столбцов таблицы, определите список столбцов:
LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
Вы должны также определить список столбцов, если порядок областей во входном файле отличается от порядка столбцов в таблице. Иначе, MySQL не может сказать, как соотнести поля ввода со столбцами таблицы.

Список столбцов может содержать имена столбцов или пользовательские переменные. С пользовательскими переменными SET позволяет Вам выполнить преобразования на их значениях прежде, чем назначить результат столбцам.

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

LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, @var1)
     SET column2 = @var1/100;
SET может использоваться, чтобы поставлять значения, не сделанные во входном файле. Следующий запрос установит column3 к текущей дате и времени:
LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, column2)
     SET column3 = CURRENT_TIMESTAMP;
Вы можете также отказаться от входного значения, назначая его на пользовательскую переменную, но не назначая переменную столбцу таблицы:
LOAD DATA INFILE 'file.txt' INTO TABLE t1
     (column1, @dummy, column2, @dummy, column3);
Использование списка столбца/переменной и SET подвергается следующим ограничениям:

Обрабатывая входную строку, LOAD DATA разделяет ее на области и использует значения согласно списку столбца/переменной и SET, если они присутствуют. Тогда получающаяся строка вставлена в таблицу. Если есть BEFORE INSERT или AFTER INSERT триггеры для таблицы, они активированы прежде или после вставки строки, соответственно.

Если у входной строки есть слишком много областей, дополнительные области проигнорированы, и число предупреждений увеличено.

Если у входной строки есть слишком мало областей, столбцы таблицы, для которых отсутствуют поля ввода, установлены в их значения по умолчанию. Назначение значения по умолчанию описано в разделе 12.7.

Пустое значение поля интерпретируется как отличающееся от недостающей области:

Это те же самые значения, которые будут результатом, если Вы назначаете пустую строку явно на строку, число или тип даты или времени явно в INSERT или UPDATE.

Обработка пустых или неправильных значений полей отличается от только что описанного, если режим SQL установлен в строгое значение. Например, если sql_mode TRADITIONAL, преобразование пустого значения или значения такого, как 'x' для числового столбца приводит к ошибке, а не преобразованию в 0. С LOCAL или IGNORE предупреждения происходят, а не ошибки, даже со строгим sql_mode, и строка вставлены, используя то же самое поведение самого близкого значения, используемое для не ограничивающих режимов SQL. Это происходит, потому что у сервера нет никакого способа остановить передачу файла в середине работы.

TIMESTAMP установлены в текущую дату и время, только если есть значение NULL для столбца (то есть, \N) и столбец не разрешает значения NULL или если значение по умолчанию столбца TIMESTAMP текущий timestamp и это опущено в полевом списке, когда полевой список определен.

LOAD DATA INFILE воспринимает весь ввод как строки, таким образом, Вы не можете использовать числовые значения для ENUM или SET, как с INSERT. Все значения ENUM и SET должны быть определены как строки.

Значения BIT не могут быть загружены, используя двоичную запись (например, b'011010'). Чтобы работать вокруг этого, определите значения как регулярные целые числа и используйте SET, чтобы преобразовать их так, чтобы MySQL выполнил числовое преобразование типа и загрузил их в столбец BIT должным образом:

shell> cat /tmp/bit_test.txt
2
127

shell> mysql test
mysql> LOAD DATA INFILE '/tmp/bit_test.txt'
    ->      INTO TABLE bit_test (@var1) SET b = CAST(@var1 AS UNSIGNED);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT BIN(b+0) FROM bit_test;
+----------+
| bin(b+0) |
+----------+
| 10       |
| 1111111  |
+----------+
2 rows in set (0.00 sec)
В Unix, если LOAD DATA надо читать из канала, Вы можете использовать следующий метод (пример загружает каталог / в таблицу db1.t1):
mkfifo /mysql/data/db1/ls.dat
chmod 666 /mysql/data/db1/ls.dat
find / -ls > /mysql/data/db1/ls.dat &
mysql -e "LOAD DATA INFILE 'ls.dat' INTO TABLE t1" db1
Здесь Вы должны выполнить команду, которая производит данные, которые будут загружены и mysql на отдельных терминалах или выполнить процесс генерации данных в фоне (как показано в предыдущем примере). Если Вы не сделаете этого, то канал заблокируется, пока данные не считаны процессом mysql.

Когда LOAD DATA INFILE завершится, это возвращает информационную строку в следующем формате:

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0
Предупреждения происходят при тех же самых обстоятельствах как когда значения вставлены, используя INSERT (см. раздел 14.2.5), за исключением того, что LOAD DATA INFILE также производит предупреждения, когда есть слишком мало или слишком много областей во входной строке.

Вы можете использовать SHOW WARNINGS , чтобы получить список первых max_error_count предупреждений как информацию о том, что пошло не так, как надо. См. раздел 14.7.5.40.

Если Вы используете C API, Вы можете получить информацию о запросе, вызывая mysql_info(). См. раздел 25.8.7.36.

14.2.7. LOAD XML

LOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE [db_name.]tbl_name
[CHARACTER SET charset_name]
[ROWS IDENTIFIED BY '<tagname>']
[IGNORE number {LINES | ROWS}]
[(field_name_or_user_var,...)]
[SET col_name = expr,...]
LOAD XML читает данные из XML-файла в таблицу. file_name должен быть дан как буквальная строка. tagname в дополнительном ROWS IDENTIFIED BY должен также быть дан как буквальная строка, и должен быть окружен угловыми скобками (< и >).

LOAD XML работает как дополнение выполнения mysql в режим вывода XML (то есть, запуская клиента с --xml). Чтобы написать данные от таблицы в XML-файл, Вы можете вызвать mysql с опциями --xml и -e:

shell> mysql --xml -e 'SELECT * FROM mydb.mytable' > file.xml
Чтобы считать файл назад в таблицу, надо использовать LOAD XML INFILE. По умолчанию элемент <row> является эквивалентом строки таблицы базы данных, это может быть изменено, используя ROWS IDENTIFIED BY.

Этот запрос поддерживает три различных формата XML:

Все три формата могут использоваться в том же самом XML-файле, подпрограмма импорта автоматически обнаруживает формат для каждой строки и интерпретирует это правильно. Теги являются соответствующими, основываясь на теге или названии атрибута и имени столбца.

Следующие пункты работают для LOAD XML по существу аналогично LOAD DATA:

См. раздел 14.2.6.

(field_name_or_user_var, ...) список разделенных запятой значений одной или более областей XML или пользовательских переменных. Название пользовательской переменной, используемой с этой целью, должно соответствовать название области из XML-файла с префиксом @. Вы можете использовать имена полей, чтобы выбрать только желаемые области. Пользовательские переменные могут использоваться, чтобы сохранить соответствующие значения полей для последующего повторного использования.

IGNORE number LINES или IGNORE number ROWS пропускает первые number строк в XML-файле. Это походит на LOAD DATA IGNORE ... LINES.

Предположите, что нам назвали таблицу person, создаваемую как показано здесь:

USE test;
CREATE TABLE person (person_id INT NOT NULL PRIMARY KEY,
       fname VARCHAR(40) NULL, lname VARCHAR(40) NULL,
       created TIMESTAMP);
Предположите далее, что эта таблица первоначально пуста.

Теперь предположите, что у нас есть простой XML-файл person.xml, чье содержание показано здесь:

<list>
  <person person_id="1" fname="Kapek" lname="Sainnouine"/>
  <person person_id="2" fname="Sajon" lname="Rondela"/>
  <person person_id="3"><fname>Likame</fname><lname>ц√rrtmons</lname></person>
  <person person_id="4"><fname>Slar</fname><lname>Manlanth</lname></person>
  <person><field name="person_id">5</field><field name="fname">Stoma</field>
<field name="lname">Milu</field></person>
  <person><field name="person_id">6</field><field name="fname">Nirtam</field>
<field name="lname">Sklц╤d</field></person>
  <person person_id="7"><fname>Sungam</fname><lname>Dulbц╔d</lname></person>
  <person person_id="8" fname="Sraref" lname="Encmelt"/>
</list>
Каждый из допустимых форматов XML, обсужденных ранее, представлен в этом файле в качестве примера.

Импортировать данные из person.xml в таблицу person можно так:

mysql> LOAD XML LOCAL INFILE 'person.xml'
    ->      INTO TABLE person
    ->      ROWS IDENTIFIED BY '<person>';

Query OK, 8 rows affected (0.00 sec)
Records: 8  Deleted: 0  Skipped: 0  Warnings: 0
Здесь мы принимаем, что person.xml расположен в каталоге данных MySQL. Если файл не может быть найден, то будет ошибка:
ERROR 2 (HY000): File '/person.xml' not found (Errcode: 2)
ROWS IDENTIFIED BY '<person>' означает, что каждый элемент <person> в XML-файле считают эквивалентным строке в таблице, в которую должны быть импортированы данные. В этом случае это таблица person в базе данных test.

Как видно из ответа по серверу, 8 строк были импортированы в таблицу test.person. Это может быть проверено простым SELECT:

mysql> SELECT * FROM person;
+-----------+--------+------------+---------------------+
| person_id | fname  | lname      | created             |
+-----------+--------+------------+---------------------+
| 1         | Kapek  | Sainnouine | 2007-07-13 16:18:47 |
| 2         | Sajon  | Rondela    | 2007-07-13 16:18:47 |
| 3         | Likame | ц√rrtmons  | 2007-07-13 16:18:47 |
| 4         | Slar   | Manlanth   | 2007-07-13 16:18:47 |
| 5         | Stoma  | Nilu       | 2007-07-13 16:18:47 |
| 6         | Nirtam | Sklц╤d     | 2007-07-13 16:18:47 |
| 7         | Sungam | Dulbц╔d    | 2007-07-13 16:18:47 |
| 8         | Sreraf | Encmelt    | 2007-07-13 16:18:47 |
+-----------+--------+------------+---------------------+
8 rows in set (0.00 sec)
Это показывает, как заявлено ранее в этом разделе, что любые из 3 форматов XML могут появиться в единственном файле и быть считаны при использовании LOAD XML.

Инверсия работы импорта то есть, вывод табличных данных MySQL в XML, может быть достигнута, используя mysql:

shell> mysql --xml -e "SELECT * FROM test.person" > person-dump.xml
shell> cat person-dump.xml
<?xml version="1.0"?>

<resultset statement="SELECT * FROM test.person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
<field name="person_id">1</field>
<field name="fname">Kapek</field>
<field name="lname">Sainnouine</field>
  </row>

  <row>
<field name="person_id">2</field>
<field name="fname">Sajon</field>
<field name="lname">Rondela</field>
  </row>

  <row>
<field name="person_id">3</field>
<field name="fname">Likema</field>
<field name="lname">ц√rrtmons</field>
  </row>

  <row>
<field name="person_id">4</field>
<field name="fname">Slar</field>
<field name="lname">Manlanth</field>
  </row>

  <row>
<field name="person_id">5</field>
<field name="fname">Stoma</field>
<field name="lname">Nilu</field>
  </row>

  <row>
<field name="person_id">6</field>
<field name="fname">Nirtam</field>
<field name="lname">Sklц╤d</field>
  </row>

  <row>
<field name="person_id">7</field>
<field name="fname">Sungam</field>
<field name="lname">Dulbц╔d</field>
  </row>

  <row>
<field name="person_id">8</field>
<field name="fname">Sreraf</field>
<field name="lname">Encmelt</field>
  </row>
</resultset>

Опция --xml предписывает клиенту mysql использовать XML-формат для его вывода, опция -e заставляет клиента немедленно выполнить запрос SQL после опции. См. раздел 5.5.1.

Вы можете проверить, что дамп допустим, создавая копию person и импортируя файл дампа в новую таблицу:

mysql> USE test;
mysql> CREATE TABLE person2 LIKE person;
Query OK, 0 rows affected (0.00 sec)

mysql> LOAD XML LOCAL INFILE 'person-dump.xml' INTO TABLE person2;
Query OK, 8 rows affected (0.01 sec)
Records: 8  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM person2;
+-----------+--------+------------+---------------------+
| person_id | fname  | lname      | created             |
+-----------+--------+------------+---------------------+
| 1         | Kapek  | Sainnouine | 2007-07-13 16:18:47 |
| 2         | Sajon  | Rondela    | 2007-07-13 16:18:47 |
| 3         | Likema | ц√rrtmons  | 2007-07-13 16:18:47 |
| 4         | Slar   | Manlanth   | 2007-07-13 16:18:47 |
| 5         | Stoma  | Nilu       | 2007-07-13 16:18:47 |
| 6         | Nirtam | Sklц╤d     | 2007-07-13 16:18:47 |
| 7         | Sungam | Dulbц╔d    | 2007-07-13 16:18:47 |
| 8         | Sreraf | Encmelt    | 2007-07-13 16:18:47 |
+-----------+--------+------------+---------------------+
8 rows in set (0.00 sec)
Нет никакого требования что каждая область в XML-файле быть соответствующей столбцу в соответствующей таблице. Пропущены области, у которых нет никаких соответствующих столбцов. Вы можете видеть это, опустошив таблицу person2 и удалив столбец created, затем используйте тот же самый LOAD XML:
mysql> TRUNCATE person2;
Query OK, 8 rows affected (0.26 sec)

mysql> ALTER TABLE person2 DROP COLUMN created;
Query OK, 0 rows affected (0.52 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE person2\G
*************************** 1. row ***************************
   Table: person2
Create Table: CREATE TABLE `person2` (
  `person_id` int(11) NOT NULL,
  `fname` varchar(40) DEFAULT NULL,
  `lname` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`person_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> LOAD XML LOCAL INFILE 'person-dump.xml' INTO TABLE person2;
Query OK, 8 rows affected (0.01 sec)
Records: 8  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM person2;
+-----------+--------+------------+
| person_id | fname  | lname      |
+-----------+--------+------------+
| 1         | Kapek  | Sainnouine |
| 2         | Sajon  | Rondela    |
| 3         | Likema | ц√rrtmons  |
| 4         | Slar   | Manlanth   |
| 5         | Stoma  | Nilu       |
| 6         | Nirtam | Sklц╤d     |
| 7         | Sungam | Dulbц╔d    |
| 8         | Sreraf | Encmelt    |
+-----------+--------+------------+
8 rows in set (0.00 sec)
Порядок, в котором области даны в каждой строке XML-файла, не затрагивает работу LOAD XML, полевой порядок может измениться от строки до строки, и не обязан быть в том же самом порядке, как соответствующие столбцы в таблице.

Как упомянуто ранее, Вы можете использовать список из одной или более областей XML (field_name_or_user_var, ...) (чтобы выбрать желаемые области только) или пользовательские переменные (чтобы сохранить соответствующие значения полей для более позднего использования). Пользовательские переменные могут быть особенно полезными, когда Вы хотите вставить данные из XML-файла в столбцы таблицы, имена которых не соответствуют таковым из областей XML. Чтобы видеть, как это работает, мы сначала составляем таблицу individual, которая соответствует структуре person, но столбцы называются по-другому:

mysql> CREATE TABLE individual (individual_id INT NOT NULL PRIMARY KEY,
    ->        name1 VARCHAR(40) NULL,
    ->        name2 VARCHAR(40) NULL, made TIMESTAMP);
Query OK, 0 rows affected (0.42 sec)
В этом случае Вы не можете просто загрузить XML-файл непосредственно в таблицу, потому что имена полей и имена столбцов не соответствуют:
mysql> LOAD XML INFILE '../bin/person-dump.xml' INTO TABLE test.individual;
ERROR 1263 (22004): Column set to default value; NULL supplied to
NOT NULL column 'individual_id' at row 1
Это происходит, потому что сервер MySQL ищет имена полей, соответствующие имена столбцов целевой таблицы. Вы можете работать вокруг этой проблемы, выбирая значения полей в пользовательские переменные, затем устанавливая столбцы целевой таблицы, равные значениям тех переменных, через использование SET. Вы можете выполнить обе эти операции в единственном запросе, как показано здесь:
mysql> LOAD XML INFILE '../bin/person-dump.xml'
    ->      INTO TABLE test.individual (@person_id, @fname, @lname, @created)
    ->      SET individual_id=@person_id, name1=@fname, name2=@lname, made=@created;
Query OK, 8 rows affected (0.05 sec)
Records: 8  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM individual;
+---------------+--------+------------+---------------------+
| individual_id | name1  | name2      | made                |
+---------------+--------+------------+---------------------+
| 1             | Kapek  | Sainnouine | 2007-07-13 16:18:47 |
| 2             | Sajon  | Rondela    | 2007-07-13 16:18:47 |
| 3             | Likema | ц√rrtmons  | 2007-07-13 16:18:47 |
| 4             | Slar   | Manlanth   | 2007-07-13 16:18:47 |
| 5             | Stoma  | Nilu       | 2007-07-13 16:18:47 |
| 6             | Nirtam | Sklц╤d     | 2007-07-13 16:18:47 |
| 7             | Sungam | Dulbц╔d    | 2007-07-13 16:18:47 |
| 8             | Srraf  | Encmelt    | 2007-07-13 16:18:47 |
+---------------+--------+------------+---------------------+
8 rows in set (0.00 sec)
Названия пользовательских переменных должны соответствовать таковым из соответствующих областей XML-файла с добавлением необходимого префикса @, чтобы указать, что это переменные. Пользовательские переменные не должны быть перечислены или назначены в том же самом порядке в качестве соответствующих областей.

Используя ROWS IDENTIFIED BY '<tagname >' возможно импортировать данные из того же самого XML-файла в таблицы базы данных с различными определениями. Для этого примера, предположите, что Вам назвали файл address.xml, который содержит следующий XML:

<?xml version="1.0"?>

<list>
  <person person_id="1">
<fname>Robert</fname>
<lname>Jones</lname>
<address address_id="1" street="Mill Creek Road" zip="45365" city="Sidney"/>
<address address_id="2" street="Main Street" zip="28681" city="Taylorsville"/>
  </person>

  <person person_id="2">
<fname>Mary</fname>
<lname>Smith</lname>
<address address_id="3" street="River Road" zip="80239" city="Denver"/>
<!-- <address address_id="4" street="North Street" zip="37920" city="Knoxville"/> -->
  </person>

</list>
Вы можете снова использовать таблицу test.person как определено ранее в этом разделе, после очистки всех существующих записей из таблицы и затем показа ее структуры как показано здесь:
mysql< TRUNCATE person;
Query OK, 0 rows affected (0.04 sec)

mysql< SHOW CREATE TABLE person\G
*************************** 1. row ***************************
   Table: person
Create Table: CREATE TABLE `person` (
  `person_id` int(11) NOT NULL,
  `fname` varchar(40) DEFAULT NULL,
  `lname` varchar(40) DEFAULT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`person_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
Теперь создайте таблицу address в базе данных test, используя следующий запрос CREATE TABLE :
CREATE TABLE address (address_id INT NOT NULL PRIMARY KEY,
       person_id INT NULL, street VARCHAR(40) NULL,
       zip INT NULL, city VARCHAR(40) NULL, created TIMESTAMP);
Чтобы импортировать данные из XML-файла в person, выполните следующий запрос LOAD XML , который определяет, что строки должны быть определены элементом <person>;
mysql> LOAD XML LOCAL INFILE 'address.xml'
    ->      INTO TABLE person
    ->      ROWS IDENTIFIED BY '<person>';
Query OK, 2 rows affected (0.00 sec)
Records: 2  Deleted: 0  Skipped: 0  Warnings: 0
Вы можете проверить, что записи были импортированы, используя SELECT:
mysql> SELECT * FROM person;
+-----------+--------+-------+---------------------+
| person_id | fname  | lname | created             |
+-----------+--------+-------+---------------------+
| 1         | Robert | Jones | 2007-07-24 17:37:06 |
| 2         | Mary   | Smith | 2007-07-24 17:37:06 |
+-----------+--------+-------+---------------------+
2 rows in set (0.00 sec)
Начиная с <address> у элементов в XML-файле нет никаких соответствующих столбцов в person, они пропущены.

Чтобы импортировать данные из элементов <address> в таблицу address, используйте LOAD XML так:

mysql> LOAD XML LOCAL INFILE 'address.xml'
    ->      INTO TABLE address
    ->      ROWS IDENTIFIED BY '<address>';
Query OK, 3 rows affected (0.00 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0
Вы можете видеть, что данные были импортированы, используя такой запрос SELECT, как этот:
mysql> SELECT * FROM address;
+------------+-----------+-----------------+-------+--------------+---------------------+
| address_id | person_id | street          | zip   | city         | created             |
+------------+-----------+-----------------+-------+--------------+---------------------+
|  1         | 1         | Mill Creek Road | 45365 | Sidney       | 2007-07-24 17:37:37 |
|  2         | 1         | Main Street     | 28681 | Taylorsville | 2007-07-24 17:37:37 |
|  3         | 2         | River Road      | 80239 | Denver       | 2007-07-24 17:37:37 |
+------------+-----------+-----------------+-------+--------------+---------------------+
3 rows in set (0.00 sec)
Данные из элемента <address>, который приложен в XML-комментариях, не импортированы. Однако, начиная со столбца person_id в таблице address, значение person_id от родительского элемента <person> для каждого <address> импортировано в таблицу address.

Соображения безопасности. Как с LOAD DATA, передача XML-файла от хоста клиента до узла сервера начата сервером MySQL. В теории исправленный сервер мог быть создан, который скажет программе клиента передавать файл, выбранный сервером, а не файл, названный клиентом в LOAD XML. Такой сервер мог получить доступ к любому файлу на хосте клиента, к которому пользователь клиента имеет доступ.

В Web клиенты обычно соединяются с MySQL от веб-сервера. Пользователь, который может выполнить любую команду сервера MySQL, может использовать LOAD XML LOCAL, чтобы читать любые файлы, к которым процесс веб-сервера имеет доступ. В этой окружающей среде клиент относительно сервера MySQL фактически веб-сервер, а не удаленная программа, выполняемая пользователем, который соединяется с веб-сервером.

Вы можете отключить загрузку XML-файлов от клиентов, запуская сервер с опциецй --local-infile=0 или --local-infile=OFF. Эта опция может также использоваться, запуская mysql, чтобы выключить LOAD XML для этого сеанса клиента.

Чтобы препятствовать тому, чтобы клиент загрузил XML-файлы из сервера, не предоставляйте привилегию FILE соответствующей учетной записи пользователя MySQL или отмените эту привилегию, если у учетной записи пользователя клиента она уже есть.

Отмена привилегии FILE (или не предоставление этого) не даст пользователю выполнять только LOAD XML INFILE (так же как LOAD_FILE() ), это не препятствует тому, чтобы пользователь выполнил LOAD XML LOCAL INFILE. Чтобы отвергнуть этот запрос, Вы должны запустить сервер или клиента с опцией --local-infile=OFF.

Другими словами, привилегия FILE затрагивает только, может ли клиент читать файлы на сервере, у этого нет никакого действия, может ли клиент считать файлы в местной файловой системе.

Для разделенных таблиц, используя механизмы хранения, которые используют табличные блокировки, например, MyISAM, любые блокировки, вызванные LOAD XML, блокируют все разделы таблицы. Это не относится к таблицам, использующим механизмы хранения, которые используют блокировку на уровне строки, например, InnoDB. См. Partitioning and Locking.

14.2.8. REPLACE

REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
Или:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,...)]
SET col_name={expr | DEFAULT}, ...
Или:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
SELECT ...
REPLACE работает точно как INSERT, за исключением того, что, если у старой строки в таблице есть то же самое значение, как новая строка для PRIMARY KEY или индекса UNIQUE, старая строка удалена прежде, чем новая строка вставлена. См. раздел 14.2.5.

REPLACE это расширение MySQL к стандарту SQL. Это вставляет или удаляет и вставляет. Для другого расширения MySQL к стандарту SQL, которое вставляет или обноввляет, см. раздел 14.2.5.3.

DELAYED вставки и замены устарели в MySQL 5.6.6. В MySQL 8.0 DELAYED не работает. Сервер признает, но игнорирует DELAYED, обрабатывает замену как неотсроченную замену, и производит предупреждение ER_WARN_LEGACY_SYNTAX_CONVERTED (REPLACE DELAYED is no longer supported. The statement was converted to REPLACE). DELAYED будет удалено в будущем выпуске.

REPLACE имеет смысл, только если у таблицы есть PRIMARY KEY или индекс UNIQUE. Иначе это становится эквивалентным INSERT, потому что нет индекса, чтобы определить, дублирует ли новая строка другую.

Значения для всех столбцов взяты от значений, определенных в REPLACE. Любые недостающие столбцы установлены в их значения по умолчанию, как это происходит для INSERT. Вы не можете обратиться к значениям от текущей строки и использовать их в новой строке. Если Вы используете такое назначение, как SET col_name = col_name+1 , ссылка на имя столбца на правой стороне обработана как DEFAULT(col_name ), таким образом, назначение эквивалентно SET col_name = DEFAULT(col_name) + 1.

Если произведенный столбец заменен явно, единственное разрешенное значение DEFAULT. Для информации о произведенных столбцах см. раздел 14.1.15.5.

Чтобы использовать REPLACE, у Вас должны быть обе привилегии INSERT и DELETE для таблицы.

REPLACE поддерживает явный выбор раздела, используя PARTITION со списком разделенных запятой значений названий разделов, подразделов или обоих. Как с INSERT , если не возможно вставить новую строку в какой-либо раздел или подраздел, REPLACE терпит неудачу с ошибкой Found a row not matching the given partition set. См. раздел 20.5.

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

Количество затронутых строк облегчает определение того, что REPLACE только добавил строку или заменял также какие-либо строки: проверьте, является ли счетчик 1 (добавил) или больше (заменил).

Если Вы используете C API, количество затронутых строк может быть получено, используя mysql_affected_rows().

Вы не можете заменять в таблице и выбрать из той же самой таблицы в подзапросе.

MySQL использует следующий алгоритм для REPLACELOAD DATA ... REPLACE):

  1. Попытайтесь вставить новую строку в таблицу.

  2. В то время как вставка терпит неудачу, потому что происходит ошибка дублирования ключа для первичного ключа или уникального индекса:

    1. Удалите из таблицы противоречивую строку, у которой есть дублирующее значение ключа.

    2. Попробуйте еще раз вставлять новую строку в таблицу.

Возможно, что в случае ключевой ошибки, механизм хранения может обработать REPLACE как обновление, а не удаление плюс вставка, но семантика та же самая. Нет никаких видимых пользователем эффектов, кроме возможной разницы в том, как механизм хранения постепенно увеличивает переменную Handler_xxx.

Поскольку результаты REPLACE ... SELECT зависят от упорядочивания строк из SELECT , и этот порядок не может всегда гарантироваться, возможно, регистрируя эти запросы для ведущего и ведомого устройств получить разный порядок. Поэтому REPLACE ... SELECT отмечены как опасный для основанной на запросе репликации. С этим изменением такие запросы производят предупреждение в журнале, используя двоичной режим журналирования STATEMENT и зарегистрированы, используя основанный на строке формат, используя режим MIXED. См. раздел 19.2.1.1.

Изменяя существующую таблицу, которая не разделена, чтобы добавить разделение или изменяя разделение уже разделенной таблицы, Вы можете рассмотреть изменение первичного ключа таблицы (см. раздел 20.6.1). Вы должны знать что, если Вы делаете это, результаты REPLACE могут быть затронуты, как если бы Вы изменили первичный ключ неразделенной таблицы. Считайте таблицу создаваемой следующим запросом CREATE TABLE:

CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT,
       data VARCHAR(64) DEFAULT NULL,
       ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON
       UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id));
Когда мы составляем эту таблицу и выполняем запросы, показанные в клиенте mysql, результаты следующие:
mysql> REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.04 sec)

mysql> REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 2 rows affected (0.04 sec)

mysql> SELECT * FROM test;
+----+------+---------------------+
| id | data | ts                  |
+----+------+---------------------+
|  1 | New  | 2014-08-20 18:47:42 |
+----+------+---------------------+
1 row in set (0.00 sec)
Теперь мы составляем вторую таблицу, почти идентичную первой , за исключением того, что первичный ключ теперь покрывает 2 столбца, как показано здесь (подчеркнутый текст):
CREATE TABLE test2 (id INT UNSIGNED NOT NULL AUTO_INCREMENT,
       data VARCHAR(64) DEFAULT NULL,
       ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON
       UPDATE CURRENT_TIMESTAMP,
       PRIMARY KEY (id, ts));
Когда мы работаем с test2, те же самые два REPLACE, как мы сделали на оригинальной таблице test, дают различный результат:
mysql> REPLACE INTO test2 VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.05 sec)

mysql> REPLACE INTO test2 VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 1 row affected (0.06 sec)

mysql> SELECT * FROM test2;
+----+------+---------------------+
| id | data | ts                  |
+----+------+---------------------+
|  1 | Old  | 2014-08-20 18:47:00 |
|  1 | New  | 2014-08-20 18:47:42 |
+----+------+---------------------+
2 rows in set (0.00 sec)
Это потому, что значения столбцов id и ts должны соответствовать таковым из существующей строки для строки, которая будет заменена, иначе строка вставлена.

В MySQL 8.0 REPLACE, затрагивающий разделенную таблицу, используя механизм хранения подобный MyISAM, блокирует на уровне таблицы только раздел, содержащий строки, которые соответствуют параметру WHERE в REPLACE, пока ни один из столбцов раздела таблицы не обновлен, иначе вся таблица заблокирована. Для механизмов хранения вроде InnoDB с блокировкой на уровне строки, никакой блокировки раздела нет. См. Partitioning and Locking.

14.2.9. SELECT

SELECT
[ALL | DISTINCT | DISTINCTROW ]
  [HIGH_PRIORITY]
  [MAX_STATEMENT_TIME = N]
  [STRAIGHT_JOIN]
  [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
  [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
  [PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
  [ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
  [ASC | DESC], ...]
[LIMIT {[offset,] row_count |
         row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
  | INTO DUMPFILE 'file_name'
  | INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
SELECT используется, чтобы получить строки, выбранные из одной или более таблиц, и может включать UNION и подзапросы. См. разделы 14.2.9.3 и 14.2.10.

Обычно используемые параметры SELECT:

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

Например:

mysql> SELECT 1 + 1;
    -> 2
Вам разрешают определить DUAL как фиктивное имя таблицы в ситуациях, где ни на какие таблицы не ссылаются:
mysql> SELECT 1 + 1 FROM DUAL;
    -> 2
DUAL просто для удобства людей, которые требуют, что все запросы SELECT должны иметь FROM и, возможно, другие параметры. MySQL может проигнорировать параметры. MySQL не требует FROM DUAL, если ни на какие таблицы не ссылаются.

Вообще, используемые пункты должны быть поданы точно в порядке, показанном в описании синтаксиса. Например, HAVING должен быть после любого GROUP BY и перед любым ORDER BY. Исключение то, что INTO может появиться как показано в описании синтаксиса или немедленно после списка select_expr. См. раздел 14.2.9.1.

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

Следующий список обеспечивает дополнительную информацию о других параметрах SELECT:

После SELECT Вы можете использовать много опций, которые затрагивают работу запроса. HIGH_PRIORITY, MAX_STATEMENT_TIME, STRAIGHT_JOIN и опции SQL_ это расширения MySQL к стандартному SQL.

В MySQL 8.0 SELECT из разделенной таблицы, используя такой механизм хранения, как MyISAM, блокируется только раздел, содержащий строки, которые соответствуют параметру WHERE в SELECT. Это не происходит с механизмами хранения вроде InnoDB, которые используют блокировку на уровне строки. См. Partitioning and Locking.

14.2.9.1. SELECT ... INTO

SELECT ... INTO позволяет результату запроса быть сохраненным в переменных или файле:

SELECT (см. раздел 14.2.9) показывает INTO около конца запроса. Также возможно использовать INTO немедленно после select_expr.

INTO не должен использоваться во вложенном SELECT потому что такой SELECT должен возвратить его результат к внешнему контексту.

INTO может назвать список из одной или более переменных, которые могут быть определяемыми пользователем переменными, параметрами хранимой процедуры или функции или местными переменными сохраненной программы. В пределах готового SELECT ... INTO OUTFILE только определяемые пользователем переменные разрешены, см. раздел 14.6.4.2.

Выбранные значения назначены на переменные. Число переменных должно соответствовать числу столбцов. Запрос должен возвратить единственную строку. Если запрос не возвращает строк, происходит предупреждение с кодом ошибки 1329 (No data), и значения переменных остаются неизменными. Если запрос возвращает много строк, происходит ошибка (Result consisted of more than one row). Если возможно, что запрос может получить много строк, Вы можете использовать LIMIT 1, чтобы ограничить набор результатов единственной строкой.

SELECT id, data INTO @x, @y FROM test.t1 LIMIT 1;
Пользовательские имена переменных не являются чувствительными к регистру. См. раздел 10.4.

SELECT ... INTO OUTFILE 'file_name' пишет выбранные строки в файл. Файл создается на сервере, таким образом, Вы должны иметь привилегию FILE . file_name не может быть существующим файлом. character_set_filesystem управляет интерпретацией имени файла.

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

Однако, если клиентское программное обеспечение MySQL установлено на удаленной машине, Вы можете вместо этого использовать команду клиента mysql -e "SELECT ..." > file_name, чтобы произвести файл на хосте клиента.

Также возможно создать получающийся файл на ином хосте кроме сервера, если к местоположению файла на удаленном хосте можно получить доступ, используя отображенный на сеть путь в файловой системе сервера. В этом случае присутствие mysql не требуется на целевом хосте.

SELECT ... INTO OUTFILE дополнение LOAD DATA INFILE. Значения столбцов записаны преобразованными в набор символов, определенный в CHARACTER SET. Если никакой такой пункт не присутствует, значения выведены, используя binary. В действительности нет никакого преобразования набора символов. Если набор результатов будет содержать столбцы в нескольких наборах символов, то файл выходных данных будет такой же, и Вы не можете перезагрузить файл правильно.

Синтаксис для export_options состоит из тех же самых FIELDS и LINES из LOAD DATA INFILE. См. раздел 14.2.6.

FIELDS ESCAPED BY управляет, как написать специальные символы. Если FIELDS ESCAPED BY не пуст, он используется, когда необходимо избежать двусмысленности как префикс, который предшествует следующим символам в выводе:

FIELDS TERMINATED BY, ENCLOSED BY, ESCAPED BY или LINES TERMINATED BY нужно экранировать, чтобы Вы могли читать файл назад.

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

Если FIELDS ESCAPED BY символ пуст, никакие символы не экранируются, NULL в выводе будет NULL, не \N. Вероятно, не хорошая идея определить пустой символ ESC, особенно если значения полей в Ваших данных содержат какой-либо из символов в списке.

Вот пример, который производит файл с отделенными запятыми значениями (формат CSV), используемый многими программами:

SELECT a, b, a+b INTO OUTFILE '/tmp/result.txt'
       FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
       LINES TERMINATED BY '\n' FROM test_table;

Если Вы используете INTO DUMPFILE вместо INTO OUTFILE, MySQL пишет только одну строку в файл, без любого столбца или завершения строки и не выполняя обработки escape. Это полезно, если Вы хотите сохранить BLOB в файл.

Любой файл, создаваемый INTO OUTFILE или INTO DUMPFILE перезаписываем всеми пользователями на сервере. Причина этого состоит в том, что сервер MySQL не может создать файл, который принадлежит никому, кроме пользователя, от учетной записи которого он работает. Вы никогда не должны выполнять mysqld как root. Файл таким образом должен быть перезаписываемым всеми, чтобы Вы могли управлять его содержанием.

Если secure_file_priv установлена в непустое имя каталога, файл, который будет написан, должен быть расположен в том каталоге.

В контексте SELECT ... INTO запросы, которые происходят как часть событий, запущенных Планировщиком Событий, сообщения диагностики (не только ошибки, но также и предупреждения) написаны в журнал ошибок и в Windows в журнал событий приложения. Для дополнительной информации см. раздел 21.4.5.

14.2.9.2. JOIN

MySQL поддерживает следующие синтаксисы JOIN для части table_references в SELECT и мультитабличных DELETE и UPDATE:

table_references:
escaped_table_reference [, escaped_table_reference] ...

escaped_table_reference:
table_reference
  | { OJ table_reference }

table_reference:
table_factor
  | join_table

table_factor:
tbl_name [PARTITION (partition_names)]
[[AS] alias] [index_hint_list]
  | table_subquery [AS] alias
  | ( table_references )

join_table:
table_reference [INNER | CROSS] JOIN table_factor
  [join_condition]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor
    ON conditional_expr
  | table_reference {LEFT|RIGHT} [OUTER] JOIN
    table_reference join_condition
  | table_reference NATURAL [INNER | {LEFT|RIGHT} [OUTER]]
    JOIN table_factor

join_condition:
ON conditional_expr
  | USING (column_list)

index_hint_list:
index_hint [, index_hint] ...

index_hint:
USE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
  | IGNORE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
  | FORCE {INDEX|KEY}
  [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)

index_list:
index_name [, index_name] ...
Табличная ссылка также известна как выражение соединения.

Табличная ссылка (когда это обращается к разделенной таблице) может содержать PARTITION, включая список разделенных запятой значений разделов. Эта опция следует за названием таблицы и предшествует любой декларации псевдонима. Эффект этой опции состоит в том, что строки выбраны только из перечисленного раздела. Другими словами, любой раздел или подраздел, не названный в списке, проигнорирован. Для получения дополнительной информации см. раздел 20.5.

Синтаксис table_factor расширен по сравнению со стандартом SQL. Последний принимает только table_reference , а не список в круглых скобках.

Это консервативное расширение, если мы рассматриваем каждую запятую в списке table_reference как эквивалент внутреннему соединению. Например:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a=t1.a AND t3.b=t1.b AND
         t4.c=t1.c)
аналогично вот этому:
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON
         (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
В MySQL JOIN, CROSS JOIN и INNER JOIN синтаксические эквиваленты (они могут заменить друг друга). В стандартном SQL они не эквивалентны. INNER JOIN используется с ON, CROSS JOIN иначе.

Вообще, круглые скобки могут быть проигнорированы в выражениях соединения, содержащих только внутренние операции соединения. MySQL также поддерживает вложенные соединения (см. раздел 9.2.1.11).

Индексные подсказки могут быть определены, чтобы затронуть, как оптимизатор MySQL использует индекс. Для получения дополнительной информации см. раздел 9.9.4.

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

Некоторые примеры соединения:

SELECT * FROM table1, table2;
SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 USING (id);
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
         LEFT JOIN table3 ON table2.id=table3.id;
Присоединитесь к изменениям обработки в MySQL 5.0.12

Естественные соединения и соединения с USING, включая внешние разновидности соединения, обработаны согласно стандарту SQL:2003. Цель состояла в том, чтобы выровнять синтаксис и семантику MySQL относительно NATURAL JOIN и JOIN ... USING согласно SQL:2003. Однако, эти изменения в обработке соединения могут привести к различным выходным столбцам для некоторых соединений. Кроме того, некоторые запросы, которые, казалось, работали правильно в более старых версиях (до 5.0.12) должны быть переписаны, чтобы выполнить стандарт.

У этих изменений есть пять основных аспектов:

Следующий список обеспечивает больше деталей относительно нескольких эффектов текущей обработки соединения против обработки в более старых версиях. Термин старые значит до MySQL 5.0.12.

14.2.9.3. UNION

SELECT ... UNION [ALL | DISTINCT] SELECT ...
           [UNION [ALL | DISTINCT] SELECT ...]
UNION используется, чтобы объединить следствие многократного SELECT в единственный набор результатов.

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

Если типы данных соответствующих столбцов SELECT не соответствуют типам и длинам столбцов в UNION, принимаются во внимание значения, полученные всеми SELECT. Например, рассмотрите следующее:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| bbbbbbbbbb    |
+---------------+
SELECT это нормальные запросы, но со следующими ограничениями:

Поведение по умолчанию для UNION: дублирующиеся строки удалены из результата. Дополнительно DISTINCT не имеет никакого эффекта кроме значения по умолчанию, потому что это также определяет удаление дублирующейся строки. С дополнительным ALL удаления дублирующейся строки не происходит, и результат включает все строки соответствия от всех SELECT.

Вы можете смешать UNION ALL и UNION DISTINCT в запросе. Смешанные UNION обработаны таким образом, что a DISTINCT переопределяет любой ALL с его левой стороны. DISTINCT может быть произведен явно при использовании UNION DISTINCT или неявно при использовании UNION без следующего DISTINCT или ALL.

Применять ORDER BY или LIMIT к отдельному SELECT можно, поместив его в круглых скобках, которые сопровождают SELECT:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Однако, использование ORDER BY для отдельного SELECT ничего не подразумевает о порядке, в котором строки появляются в окончательном результате, потому что UNION по умолчанию производит неупорядоченный набор строк. Поэтому, использование ORDER BY в этом контексте, как правило, находится в соединении с LIMIT, чтобы это использовалось, чтобы определить подмножество выбранных строк для SELECT, даже при том, что это не обязательно затрагивает порядок тех строк в финальном результате UNION. Если ORDER BY появляется без LIMIT в SELECT, это оптимизировано далеко, потому что это не будет иметь никакого эффекта так или иначе.

Используя ORDER BY или LIMIT, чтобы сортировать или ограничить все UNION, введите индивидуальный SELECT поместите ORDER BY или LIMIT после последнего. Следующий пример использует оба параметра:

(SELECT a FROM t1 WHERE a=10 AND B=1) UNION
          (SELECT a FROM t2 WHERE a=11 AND B=2)
          ORDER BY a LIMIT 10;
Запрос без круглых скобок эквивалентен одному параметру, как показано.

Этот ORDER BY не может использовать ссылки столбца, которые включают имя таблицы (то есть, имена в формате tbl_name.col_name). Вместо этого обеспечьте псевдоним столбца в первом SELECT и обратитесь к псевдониму в ORDER BY. Альтернативно, обратитесь к столбцу в ORDER BY с использованием его позиции столбца. Однако, использование позиций столбца устарело.

Кроме того, если столбец, который будет сортирован, является псевдонимом, ORDER BY должен отнестись к псевдониму, а не имени столбца. Первый из следующих запросов будет работать, но второй потерпит неудачу с ошибкой Unknown column 'a' in 'order clause':

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
При вызове строк в UNION результат будет состоять из наборов строк, полученных каждым SELECT один за другим, выберите дополнительный столбец в каждом SELECT, чтобы использовать в качестве столбца сортировки и добавить ORDER BY после последнего SELECT:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION
          (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
Чтобы дополнительно поддержать порядок сортировки в пределах SELECT, добавьте вторичный столбец к ORDER BY:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION
          (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
Использование дополнительного столбца также позволяет Вам определить, из которого SELECT каждая строка прибывает. Дополнительные столбцы могут предоставить другую информацию об идентификации также, такую как строку, которая указывает на имя таблицы.

Запросы UNION с совокупной функцией в ORDER BY отклонены с ошибкой ER_AGGREGATE_ORDER_FOR_UNION:

SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);

14.2.10. Синтаксис подзапроса

Подзапрос это SELECT в пределах другого запроса.

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

Вот пример подзапроса:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
В этом примере SELECT * FROM t1 ... внешний запрос, а (SELECT column1 FROM t2) подзапрос. Мы говорим, что подзапрос вложен в пределах внешнего запроса и фактически возможно вложить подзапросы в пределах других подзапросов на значительную глубину. Подзапрос должен всегда появляться в пределах круглых скобок.

Основные преимущества подзапросов:

Вот запрос в качестве примера, который показывает важные пункты о синтаксисе подзапроса, как определено стандартом SQL и поддержано в MySQL:

DELETE FROM t1 WHERE s11 > ANY
       (SELECT COUNT(*) /* no hint */ FROM t2
               WHERE NOT EXISTS (SELECT * FROM t3 WHERE ROW(5*t2.s1,77)=
               (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
               (SELECT * FROM t5) AS t5)));
Подзапрос может возвратить скаляр (единственное значение), единственную строку, единственный столбец или таблицу (одна или более строк одного или более столбцов). Их называют скаляром, столбцом, строкой и табличными подзапросами. Подзапросы, которые возвращают особый вид результата, часто могут использоваться только в определенных контекстах, как описано в следующих разделах.

Есть немного ограничений на тип запросов, в которых могут использоваться подзапросы. Подзапрос может содержать многие из ключевых слов, которые допустимы в рамках SELECT: DISTINCT, GROUP BY, ORDER BY, LIMIT, объединения, UNION, комментарии, функции и так далее.

Внешний запрос подзапроса может быть любым из: SELECT, INSERT, UPDATE, DELETE, SET или DO.

В MySQL Вы не можете изменить таблицу и выбрать из той же самой таблицы в подзапросе. Это относится к таким запросам, как DELETE, INSERT, REPLACE, UPDATE и (потому что подзапросы могут использоваться в SET) LOAD DATA INFILE.

14.2.10.1. Подзапрос как скалярный операнд

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

CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
INSERT INTO t1 VALUES(100, 'abcde');
SELECT (SELECT s2 FROM t1);
Подзапрос в этом SELECT возвращает единственное значение ('abcde'), у этого есть тип данных CHAR, длина 5, набор символов и сопоставление, равное значениям по умолчанию во время CREATE TABLE, и признак, что значение в столбце может быть NULL. Такие значения, выбранные скалярным подзапросом, не скопированы, потому что, если результат подзапроса пуст, результат NULL. Для показанного подзапроса, если t1 пуст, результат будет NULL даже при том, что s2 NOT NULL.

Есть несколько контекстов, в которых не может использоваться скалярный подзапрос. Если запрос разрешает только буквальное значение, Вы не можете использовать подзапрос. Например, LIMIT требует буквальных параметров целого числа, и LOAD DATA INFILE требует буквального строкового имени файла. Вы не можете использовать подзапросы, чтобы поставлять эти значения.

Когда Вы видите примеры в следующих разделах, которые содержат довольно спартанскую конструкцию (SELECT column1 FROM t1), предположите, что Ваш собственный код содержит намного более разнообразные и сложные конструкции.

Предположите, что мы делаем две таблицы:

CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);
Тогда выполните SELECT:
SELECT (SELECT s1 FROM t2) FROM t1;
Результат 2 потому что есть строка в t2, содержащая столбец s1, а у этого есть значение 2.

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

SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

14.2.10.2. Сравнения, используя подзапросы

Наиболее популярный способ использования подзапроса находится в форме:

non_subquery_operand comparison_operator
(subquery)
Здесь comparison_operator один из этих операторов:
=  >  <  >=  <=  <>  !=  <=>
Например:
... WHERE 'a' = (SELECT column1 FROM t1)
MySQL также разрешает эту конструкцию:
non_subquery_operand LIKE (subquery)
Когда-то единственное место для подзапроса было на правой стороне сравнения, и Вы могли бы все еще найти некоторые старые DBMS, которые настаивают на этом.

Вот пример сравнения подзапроса стандартной формы, которое Вы не можете сделать с соединением. Это находит все строки в таблице t1 для которых column1 равно максимальному значению в таблице t2:

SELECT * FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2);
Вот другой пример, который снова невозможен с соединением, потому что он вовлекает соединение для одной из таблиц. Это находит все строки в таблице t1, содержа значение, которое встречается дважды в данном столбце:
SELECT * FROM t1 AS t WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
Для сравнения подзапроса и скаляра подзапрос должен возвратить скаляр. Для сравнения подзапроса со строкой подзапрос должен быть подзапросом строки, который возвращает строку с тем же самым числом значений, как конструктор строки. См. раздел 14.2.10.5.

14.2.10.3. Подзапросы с ANY, IN или SOME

operand comparison_operator ANY (subquery)
operand IN (subquery)
operand comparison_operator SOME (subquery)
Здесь comparison_operator одно из:
=  >  <  >=  <=  <>  !=
ANY должно следовать за оператором сравнения, означает вернуть TRUE, если сравнение TRUE для ANY из значений в столбце, который вернул подзапрос :
SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);
Предположите, что есть строка в таблице t1, содержащая (10). Выражение TRUE, если таблица t2 содержит (21,14,7) потому, что есть значение 7 в t2, это меньше 10. Выражение FALSE, если таблица t2 содержит (20,10), или если таблица t2 пуста. Выражение неизвестно (то есть, NULL), если таблица t2 содержит (NULL,NULL,NULL).

Когда используется с подзапросом IN псевдоним для = ANY. Таким образом, эти два запроса то же самое:

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN(SELECT s1 FROM t2);
IN и = ANY не синонимы, когда используются со списком выражений. IN может взять список выражений, но = ANY нет, см. раздел 13.3.2.

NOT IN псевдоним не для <> ANY, а для <> ALL. См. раздел 14.2.10.4.

SOME псевдоним для ANY. Таким образом, эти два запроса то же самое:

SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);
Использование слова SOME редко, но этот пример показывает, почему это могло бы быть полезно. Большинству людей фраза a не равный любому b означает нет никакого b, который равен a, но это не то, что предназначается синтаксисом SQL. Синтаксис означает есть некоторый b, который не равен a. Использование <> SOME вместо этого помогает гарантировать, что все понимают значение запроса.

14.2.10.4. Подзапросы с ALL

operand comparison_operator
    ALL (subquery)
ALL, который должен следовать за оператором сравнения, означает вернуть TRUE, если сравнение TRUE для ALL значений в столбце, который вернул подзапрос:
SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);
Предположите, что есть строка в таблице t1, содержащая (10). Выражение TRUE, если таблица t2 содержит (-5,0,+5), поскольку 10 больше чем все три значения в t2. Выражение FALSE, если таблица t2 содержит (12,6,NULL,-100) потому, что есть единственное значение 12 в таблице t2, которое больше 10. Выражение неизвестно (то есть, NULL), если таблица t2 содержит (0,NULL,1).

Наконец, выражение TRUE, если таблица t2 пуста. Так, следующее выражение TRUE, когда таблица t2 пуста:

SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);
Но это выражение NULL, когда таблица t2 пуста:
SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);
Кроме того, следующее выражение NULL когда таблица t2 пуста:
SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);
Вообще, таблицы, содержащие значения NULL и пустые таблицы проблемные ситуации при написании подзапросов, всегда рассматривайте, приняли ли Вы эти две возможности во внимание.

NOT IN псевдоним для <> ALL. Таким образом, эти два запроса те же самые:

SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);

14.2.10.5. Подзапросы строки

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

=  >  <  >=  <=  <>  !=  <=>
Вот два примера:
SELECT * FROM t1 WHERE (col1,col2) = (SELECT col3, col4 FROM t2
         WHERE id = 10);
SELECT * FROM t1 WHERE ROW(col1,col2) = (SELECT col3, col4 FROM t2
         WHERE id = 10);
Для обоих запросов, если таблица t2 содержит единственную строку с id = 10, подзапрос возвращает единственную строку. Если эта строка имеет значения col3 и col4, равные col1 и col2 любых строк в t1, WHERE TRUE и каждый запрос возвращает те строки t1. Если значения строк col3 и col4 в t2 не равны значениям col1 и col2 любой строки в t1, выражение FALSE и запрос возвращает пустой набор результатов. Выражение неизвестно (то есть, NULL), если подзапрос не производит строк. Ошибка происходит, если подзапрос производит много строк, потому что подзапрос строки может возвратить самое большее одну строку.

Выражения (1,2) и ROW(1,2) иногда называются конструкторами строки. Эти два эквивалентны. Конструктор строки и строка, возвращенная подзапросом, должны содержать то же самое число значений.

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

SELECT * FROM t1 WHERE ROW(1) = (SELECT column1 FROM t2)
Конструкторы строки являются законными в других контекстах. Например, следующие два запроса семантически эквивалентны (и обработаны таким же образом оптимизатором):
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
Следующий запрос отвечает на запрос найти все строки в таблице t1, которые также существуют в таблице t2:
SELECT column1,column2,column3 FROM t1 WHERE (column1,column2,column3) IN
       (SELECT column1,column2,column3 FROM t2);

14.2.10.6. Подзапросы с EXISTS или NOT EXISTS

Если подзапрос возвращает какие-либо строки вообще, EXISTS subquery TRUE, а NOT EXISTS subquery FALSE:

SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
Традиционно подзапрос EXISTS начинается с SELECT *, но это могло начаться с SELECT 5 или SELECT column1 или вообще с чего угодно. MySQL игнорирует список SELECT в таком подзапросе, таким образом, это не имеет никакого значения.

Для предыдущего примера, если t2 содержит любые строки, даже строки только со значениями NULL, условие EXISTS TRUE. Это фактически маловероятный пример потому, что подзапрос [NOT] EXISTS почти всегда содержит корреляции. Вот некоторые более реалистические примеры:

Последний пример двоичным образом вложенный запрос NOT EXISTS. Таким образом, у этого есть NOT EXISTS в пределах NOT EXISTS. Формально это отвечает на вопрос есть ли город с хранилищем, которое не находится в Stores? Но легче сказать что вложенный NOT EXISTS отвечает на вопрос есть ли x TRUE для всех y?

14.2.10.7. Коррелированые подзапросы

Коррелированый подзапрос это подзапрос, который содержит ссылку на таблицу, которая также появляется во внешнем запросе. Например:

SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2
         WHERE t2.column2 = t1.column2);
Заметьте, что подзапрос содержит ссылку на столбец t1 даже при том, что FROM подзапроса не упоминает таблицу t1. MySQL смотрит вне подзапроса и находит t1 во внешнем запросе.

Предположите, что таблица t1 содержит строку, где column1 = 5 и column2 = 6, тем временем таблица t2 содержит строку, где column1 = 5 и column2 = 7. Простое выражение ... WHERE column1 = ANY (SELECT column1 FROM t2) было бы TRUE, но в этом примере WHERE в пределах подзапроса FALSE (потому что (5,6) не (5,7)), таким образом, выражение в целом FALSE.

Правило обзора данных: MySQL оценивает изнутри к внешней стороне. Например:

SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x
       WHERE x.column1 = (SELECT column1 FROM t3
       WHERE x.column2 = t3.column1));
В этом запросе x.column2 должен быть столбец в таблице t2 потому, что SELECT column1 FROM t2 AS x ... переименовывает t2. Это не столбец в таблице t1, потому что SELECT column1 FROM t1 ... внешний запрос, который дальше отсутствует.

Для подзапросов в HAVING или ORDER BY MySQL также ищет имена столбцов во внешнем избранном списке.

Для определенных случаев оптимизирован коррелированый подзапрос. Например:

val IN (SELECT key_val FROM
tbl_name WHERE correlated_condition)
Иначе они неэффективны и вероятны будут медленными. Запрос переписан, поскольку соединение могло бы улучшить работу.

Совокупные функции в коррелированых подзапросах могут содержать внешние ссылки, если функция содержит только внешние ссылки, и если функция не содержится в другой функции или выражении.

14.2.10.8. Подзапросы в FROM

Подзапросы являются законными в параметре FROM SELECT:

SELECT ... FROM (subquery) [AS] name ...
[AS] name принудителен, потому что каждая таблица в FROM должна иметь имя. Любые столбцы в subquery должны иметь уникальные имена.

Ради иллюстрации предположите, что у Вас есть эта таблица:

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
Вот как использовать подзапрос в FROM, используя таблицу в качестве примера:
INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3 FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1)
       AS sb WHERE sb1 > 1;
Результат: 2, '2', 4.0.

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

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
Однако, этот запрос предоставляет желаемую информацию:
SELECT AVG(sum_column1) FROM (SELECT SUM(column1) AS sum_column1
       FROM t1 GROUP BY column1) AS t1;
Заметьте, что имя столбца, использованное в пределах подзапроса (sum_column1), признано во внешнем запросе.

Подзапросы в FROM могут возвратить скаляр, столбец, строку или таблицу. Подзапросы в FROM не могут быть коррелированными подзапросами, если не используются в пределах ON в JOIN.

В MySQL 8.0 оптимизатор определяет информацию о полученных таблицах таким способом, для которого не происходит материализация их для EXPLAIN. См. раздел 9.2.1.18.3.

Возможно при определенных обстоятельствах изменить табличное использование данных, применив EXPLAIN SELECT. Это может произойти, если внешние запросы обращаются к любым таблицам, а внутренний запрос вызывает сохраненную функцию, которая изменяет одну или более строк таблицы. Предположите, что есть две таблицы t1 и t2 в базе данных d1, создаваемой как показано здесь:

mysql> CREATE DATABASE d1;
Query OK, 1 row affected (0.00 sec)

mysql> USE d1;
Database changed

mysql> CREATE TABLE t1 (c1 INT);
Query OK, 0 rows affected (0.15 sec)

mysql> CREATE TABLE t2 (c1 INT);
Query OK, 0 rows affected (0.08 sec)
Теперь мы создаем сохраненную функцию f1, которая изменяет t2:
mysql> DELIMITER //
mysql> CREATE FUNCTION f1(p1 INT) RETURNS INT
mysql>   BEGIN
mysql> INSERT INTO t2 VALUES (p1);
mysql> RETURN p1;
mysql>   END //
Query OK, 0 rows affected (0.01 sec)

mysql> DELIMITER ;
Ссылка на функцию непосредственно в EXPLAIN SELECT не имеет никакого эффекта на t2, как показано здесь:
mysql> SELECT * FROM t2;
Empty set (0.00 sec)

mysql> EXPLAIN SELECT f1(5);
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM t2;
Empty set (0.00 sec)
Это потому, что SELECT не ссылается ни на какие таблицы, как может быть замечено в столбцах table и Extra вывода. Это также верно для вложенного следующего SELECT:
mysql> EXPLAIN SELECT NOW() AS a1, (SELECT f1(5)) AS a2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | PRIMARY     | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------------------+
| Level | Code | Message                                  |
+-------+------+------------------------------------------+
| Note  | 1249 | Select 2 was reduced during optimization |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM t2;
Empty set (0.00 sec)
Однако, если внешний SELECT ссылаетя на любые таблицы, оптимизатор выполняет запрос в подзапросе также:
mysql> EXPLAIN SELECT * FROM t1 AS a1, (SELECT f1(5)) AS a2;
+----+-------------+------------------+--------+---------------+------+---------+------+------+---------------------+
| id | select_type | table            | type   | possible_keys | key  | key_len | ref  | rows | Extra               |
+----+-------------+------------------+--------+---------------+------+---------+------+------+---------------------+
|  1 | PRIMARY     | a1               | system | NULL          | NULL | NULL    | NULL | 0    | const row not found |
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL | NULL    | NULL | 1    |                     |
|  2 | DERIVED     | NULL             | NULL   | NULL          | NULL | NULL    | NULL | NULL | No tables used      |
+----+-------------+------------------+--------+---------------+------+---------+------+------+---------------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM t2;
+----+
| c1 |
+----+
| 5  |
+----+
1 row in set (0.00 sec)
Это также означает, что такой запрос EXPLAIN SELECT, как один показанный здесь, может занять много времени, чтобы выполнить, потому что функция BENCHMARK() выполнена однажды для каждой строки в t1:
EXPLAIN SELECT * FROM t1 AS a1, (SELECT BENCHMARK(1000000, MD5(NOW())));

14.2.10.9. Ошибки подзапроса

Есть некоторые ошибки, которые применяются только к подзапросам. Этот раздел описывает их.

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

14.2.10.10. Оптимизация подзапросов

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

Эти уловки могли бы заставить программы идти быстрее или медленнее. Используя средства MySQL, например, BENCHMARK(), Вы можете понять, что помогает в Вашей ситуации. См. раздел 13.14.

Некоторая оптимизация, которую делает сам MySQL:

См. также MySQL Internals: How MySQL Transforms Subqueries.

14.2.10.11. Перезапись подзапросов как соединения

Иногда есть другие способы проверить членство в ряде значений, чем использование подзапроса. Кроме того, в некоторых случаях не только возможно переписать запрос без подзапроса, но может быть более эффективно использовать некоторые из этих методов, а не использовать подзапросы. Один из них IN():

Например, этот запрос:

SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
Может быть переписан как:
SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;
Запросы:
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
Могут быть переписаны как:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
                WHERE table2.id IS NULL;
LEFT [OUTER] JOIN может быть быстрее, чем эквивалентный подзапрос, потому что сервер мог бы быть в состоянии оптимизировать это лучше. До SQL-92 не существовали внешние соединения, таким образом, подзапросы были единственным способом сделать определенные вещи. Сегодня MySQL Server и много других современных систем базы данных предлагают широкий диапазон внешних типов соединения.

MySQL Server поддерживает многотабличный DELETE, который может использоваться, чтобы эффективно удалить строки, основанные на информации от одной таблицы или даже от многих таблиц в то же самое время. Многотабличный UPDATE также поддержан. См. разделы 14.2.2 и 14.2.11.

14.2.11. UPDATE

Однотабличный вариант:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET col_name1={expr1|DEFAULT}
    [, col_name2={expr2|DEFAULT}] ...
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
Многотабличный вариант:
UPDATE [LOW_PRIORITY] [IGNORE] table_references
SET col_name1={expr1|DEFAULT}
    [, col_name2={expr2|DEFAULT}] ...
[WHERE where_condition]
Для однотабличного синтаксиса UPDATE обновляет столбцы существующих строк в названной таблице с новыми значениями. SET указывает, какие столбцы изменить и значения им нужно дать. Каждое значение может быть дано как выражение или ключевое слово DEFAULT, чтобы установить столбец явно в его значение по умолчанию. WHERE, если дано, определяет условия, которые идентифицируют который строки обновить. Без WHERE все строки обновлены. Если ORDER BY определен, строки обновлены в порядке, который определен. LIMIT устанавливает границу числа строк, которые могут быть обновлены.

Для многотабличного синтаксиса UPDATE строки обновлены в каждой таблице, названной в table_references, которая удовлетворяет условиям. Однажды обновлена каждая строка соответствия, даже если она соответствует условиям многократно. Для многотабличного синтаксиса ORDER BY и LIMIT не могут использоваться.

Для разделенных таблиц однотабличные и многотабличные формы этого запросы поддерживают использование PARTITION как часть табличной ссылки. Эта опция берет список из одного или более раздела или подраздела (или оба). Только перечисленный раздел (или подраздел) проверен на соответствия, и строка, которая не находится ни в одном этом разделе или подразделе, не обновлена, удовлетворяет ли она where_condition или нет.

В отличие от случая использования PARTITION с INSERT или REPLACE допустимый запрос UPDATE ... PARTITION считают успешным, даже если никакие строки в перечисленном разделе не соответствуют where_condition.

См. раздел 20.5.

where_condition выражение, которое оценивается к истине для каждой строки, которая будет обновлена. Для синтаксиса выражения см. раздел 10.5.

table_references и where_condition определены как описано в раздел 14.2.9.

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

UPDATE поддерживает следующие модификаторы:

UPDATE IGNORE, включая тех, которые имеют ORDER BY отмечены как опасные для основанной на запросе репликации. Это потому, что порядок, в котором обновлены строки, определяет, какие строки проигнорированы. С этим изменением такие запросы производят предупреждение в журнале, используя основанный на запросе режим и зарегистрированы, используя основанный на строке формат, используя режим MIXED (Bug #11758262, Bug #50439), см. раздел 19.2.1.3.

Если Вы получаете доступ к столбцу от таблицы, которая будет обновлена в выражении, UPDATE использует текущее значение столбца. Например, следующий запрос увеличивает col1 на единицу:

UPDATE t1 SET col1 = col1 + 1;
Второе назначение устанавливает col2 к (обновленному) текущему значению col1, а не оригинальному col1. Результат: col1 и col2 имеют то же самое значение. Это поведение отличается от стандартного SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Однотабличный UPDATE вообще оценен слева направо. Для многотабличных обновлений нет никакой гарантии, что назначения выполнены в любом особом порядке.

Если Вы устанавливаете столбец в значение, которое он в настоящее время имеет, MySQL замечает это и не обновляет его.

Если Вы обновляете столбец, который был объявлен NOT NULL, устанавливая в NULL, ошибка происходит если строгий режим SQL включен, иначе столбец установлен в неявное значение по умолчанию для типа данных столбца, и количество предупреждений увеличено. Неявное значение по умолчанию 0 для числовых типов, пустая строка ('') для строковых типов и нулевое значение для типов времени и даты. См. раздел 12.7.

Если произведенный столбец обновлен явно, единственное разрешенное значение DEFAULT. Для информации о произведенных столбцах см. раздел 14.1.15.5.

UPDATE возвращает число строк, которые были фактически изменены. mysql_info() в C API возвращает число строк, которые были соответствующими и обновлены и число предупреждений, которые произошли во время UPDATE.

Вы можете использовать LIMIT row_count, чтобы ограничить контекст UPDATE. LIMIT ограничение соответствующих строк. Запрос останавливается, как только он нашел row_count строк, которые удовлетворяют WHERE, неважно, были ли они фактически изменены.

Если UPDATE запрос включает ORDER BY, строки обновлены в порядке, определенном параметром. Это может быть полезно в определенных ситуациях, которые могли бы иначе привести к ошибке. Предположите что таблица t содержит столбец id, у которого есть уникальный индекс. Следующий запрос может потерпеть неудачу с ошибкой дубликата ключа, в зависимости от порядка, в котором обновлены строки:

UPDATE t SET id = id + 1;
Например, если таблица содержит 1 и 2 в столбце id и 1 обновлен к 2 прежде, чем 2 будет обновлен к 3, ошибка происходит. Чтобы избежать этой проблемы, добавьте ORDER BY, чтобы строки с большим id были обновлены перед теми с меньшими значениями:
UPDATE t SET id = id + 1 ORDER BY id DESC;
Вы можете также использовать UPDATE , покрывающий много таблиц. Однако, Вы не можете использовать ORDER BY или LIMIT с многотабличным UPDATE. table_references перечисляет таблицы, вовлеченные в соединение. Его синтаксис описан в разделе 14.2.9.2:
UPDATE items,month SET items.price=month.price
       WHERE items.id=month.id;
Предыдущий пример показывает внутреннее соединение, которое использует оператор запятой, но многотабличный UPDATE может использовать любой тип соединения, разрешенного в SELECT, например, LEFT JOIN .

Если Вы используете многотабличный UPDATE с таблицами, для которых есть ограничения внешнего ключа, оптимизатор MySQL мог бы обработать таблицы в порядке, который отличается от нужного из их родительских/дочерних отношений. В этом случае запрос терпит неудачу и откатывается. Вместо этого обновите единственную таблицу и положитесь на ON UPDATE, который обеспечивает InnoDB , чтобы заставить другие таблицы быть измененными соответственно. См. раздел 16.8.6.

Вы не можете обновить таблицу и выбрать из той же самой таблицы в подзапросе.

В MySQL 8.0 UPDATE на разделенной таблице, используя механизм хранения с блокировками на уровне таблицы, блокирует только раздел, содержащий строки, которые соответствуют UPDATE WHERE, пока ни один из столбцов раздела не обновлен. См. Partitioning and Locking.

14.3. Транзакционные и блокирующие запросы

MySQLподдерживает местные транзакции (в пределах данного сеанса клиента) через запросы SET autocommit, START TRANSACTION, COMMIT и ROLLBACK. См раздел 14.3.1. Операционная поддержка XA позволяет MySQL участвовать в распределенных транзакциях также. См. раздел 14.3.7.

14.3.1. START TRANSACTION, COMMIT и ROLLBACK

START TRANSACTION
[transaction_characteristic [, transaction_characteristic] ...]

transaction_characteristic:
WITH CONSISTENT SNAPSHOT
  | READ WRITE
  | READ ONLY

BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET autocommit = {0 | 1}
Эти запросы обеспечивают управление использованием транзакциями:

По умолчанию MySQL выполняется с включенным autocommit. Это означает, что как только Вы выполняете запрос, который обновляет (изменяет) таблицу, MySQL хранит обновление на диске, чтобы сделать это постоянным. Изменение не может быть удалено до прежнего уровня.

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

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
С START TRANSACTION autocommit остается отключенным, пока Вы не заканчиваете транзакцию COMMIT или ROLLBACK. Режим autocommit тогда возвращается в его предыдущий статус.

START TRANSACTION разрешает несколько модификаторов. Чтобы определить много модификаторов, отделите их запятыми.

Многие API для того, чтобы написать приложения-клиенты MySQL (такие, как JDBC), обеспечивают их собственные методы для того, чтобы они начали транзакции, которые могут (и иногда должны) использоваться вместо того, чтобы послать START TRANSACTION. См. главу 25 .

Чтобы отключить режим явно:

SET autocommit=0;
После отключения autocommit установкой переменной autocommit в 0, изменения безопасных от транзакции таблиц (таких, как InnoDB или NDB) не сделаны постоянными немедленно. Вы должны использовать COMMIT, чтобы сохранить Ваши изменения нв диск, или ROLLBACK, чтобы проигнорировать все изменения.

autocommit переменная сеанса и должна быть установлена для каждого сеанса. Чтобы отключить режим для каждого нового соединения, см. описание переменной autocommit в разделе 6.1.5.

BEGIN и BEGIN WORK поддержаны как псевдонимы START TRANSACTION, который является стандартным синтаксисом SQL, рекомендуемым способ запустить транзакцию, и разрешает модификаторы, которые в BEGIN отсутствуют.

BEGIN отличается от использования ключевого слова BEGIN, которое запускает BEGIN ... END. Последний не начинает транзакцию. См. раздел 14.6.1.

В пределах всех сохраненных программ (хранимые процедуры и функции, триггеры и события), анализатор обрабатывает BEGIN [WORK] как начало BEGIN ... END. Начните транзакцию в этом контексте с START TRANSACTION.

WORK поддержано для COMMIT и ROLLBACK, как CHAIN и RELEASE. CHAIN и RELEASE могут использоваться для дополнительного управления операционным завершением. Значение переменной completion_type определяет поведение завершения по умолчанию. См. раздел 6.1.5.

AND CHAIN заставляет новую транзакцию начинаться, как только текущяя заканчивается, и у новой транзакции будет тот же самый уровень изоляции, как у только что законченной транзакции. RELEASE заставляет сервер разъединять текущий сеанс клиента после завершения текущей транзакции. Включение ключевого слова NO подавляет завершение CHAIN или RELEASE, которое может быть полезным, если переменная completion_type установлена, чтобы вызвать завершение объединения в цепочку или выпуска по умолчанию.

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

Начало транзакции также снимает табличные блокировки, приобретенные с LOCK TABLES, как если бы Вы выполнили UNLOCK TABLES. Начало транзакции не снимает глобальную блокировку чтения, приобретенную с FLUSH TABLES WITH READ LOCK.

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

Каждая транзакция сохранена в двоичном журнале в одном куске на COMMIT. Ттранзакции, которые откатились, не зарегистрированы. Исключение: Модификации нетранзакционных таблиц не могут быть отменены. Если транзакция, которая откачена, включает модификации нетранзакционных таблиц, вся транзакция зарегистрирована с ROLLBACK в конце, чтобы гарантировать, что модификации к нетранзакционным таблицам копируются. См. раздел 6.4.4.

Вы можете изменить уровень изоляции или режим доступа для транзакций с SET TRANSACTION. См. раздел 14.3.6.

Откатывание назад может быть медленной работой, которая может произойти неявно без пользователя, явно просившего этого (например, когда ошибка происходит). Из-за этого SHOW PROCESSLIST показывает Rolling back в столбце State для сеанса, не только для явных отмен, выполненных с ROLLBACK, но также и для неявных.

В MySQL 8.0 BEGIN, COMMIT и ROLLBACK не затронуты правилами --replicate-do-db или --replicate-ignore-db.

14.3.2. Запросы, которые не могут быть отменены

Некоторые запросы не могут быть отменены. Вообще, они включают язык определения данных (DDL), такие запросы, как те, которые создают или удаляют базы данных, те, которые создают, удаляют или изменяют таблицы или сохраненные подпрограммы.

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

14.3.3. Запросы, которые неявно закрывают транзакцию

Запросы, перечисленные в этом разделе (и любые синонимы для них) неявно заканчивают любую транзакцию, активную в текущем сеансе, как будто Вы сделали COMMIT прежде, чем выполнить запрос.

Большинство этих запросов также вызывает неявное закрытие после выполнения. Намерение состоит в том, чтобы обработать каждый такой запрос в своей собственной специальной транзакции, потому что это не может быть отменено так или иначе. Операционное управление и запросы блокировки это исключения: если неявное завершение происходит перед выполнением, другое не происходит после.

14.3.4. SAVEPOINT, ROLLBACK TO SAVEPOINT и RELEASE SAVEPOINT

SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
InnoDB поддерживает запросы SQL SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT и дополнительное ключевое слово WORK для ROLLBACK.

SAVEPOINT устанавливает точку сохранения с именем identifier. Если у текущей транзакции есть точка сохранения с тем же самым именем, старая удалена, новая установлена.

ROLLBACK TO SAVEPOINT откатывает транзакцию на точку сохранения, не заканчивая транзакцию. Модификации, которые текущая транзакция сделала со строками после точки сохранения, отменены, но InnoDB не снимает блокировки строки, которые были сохранены в памяти после точки. Для новой вставленной строки информацию о блокировке переносит операционное ID, сохраненное в строке, блокировка не сохранена отдельно в памяти. В этом случае блокировка строки снята при отмене. Точки, которые были установлены в более позднее время, чем названная, удалены.

Если ROLLBACK TO SAVEPOINT возвращает следующую ошибку, это означает, что никакой точки с указанным именем не существует:

ERROR 1305 (42000): SAVEPOINT identifier does not exist
RELEASE SAVEPOINT удаляет названную точку из набора точек текущей транзакции. Завершение или отмена не происходят. Это ошибка, если точка не существует.

Все точки текущей транзакции удалены, если Вы выполняете COMMIT или ROLLBACK, который не называет точку.

Новый уровень точки создается, когда сохраненная функция вызвана, или триггер активирован. Точки на предыдущих уровнях становятся недоступными и таким образом не находятся в противоречии с точками на новом уровне. Когда функция или триггер заканчиваются, любые точки, который это создало, сняты, и предыдущий уровень точек восстановлен.

14.3.5. LOCK TABLES и UNLOCK TABLES

LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type:
READ [LOCAL]
  | [LOW_PRIORITY] WRITE
UNLOCK TABLES
MySQL позволяет сеансам клиента приобрести табличные блокировки явно с целью сотрудничества с другими сеансами для доступа к таблицам, или препятствовать тому, чтобы другие сеансы изменили таблицы во время периодов, когда сеанс требует эксклюзивного доступа к ним. Сеанс может приобрести или выпустить блокировки только для себя. Один сеанс не может приобрести блокировки за другой сеанс или выпустить блокировки, проводимые другим сеансом.

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

LOCK TABLES явно приобретает табличные блокировки. Табличные блокировки могут быть приобретены для базовых таблиц или представлений. Вы должны иметь привилегии LOCK TABLES и SELECT для каждого объекта, который будет заблокирован.

Для блокировки представления LOCK TABLES добавляет все базовые таблицы, используемые в представлении, и блокирует их автоматически. Если Вы блокируете таблицу явно с LOCK TABLES, любые таблицы, используемые в триггерах, также заблокированы неявно, как описано в разделе 14.3.5.2.

UNLOCK TABLES явно снимает любые табличные блокировки текущего сеанса. LOCK TABLES неявно снимает любые табличные блокировки, проводимые текущим сеансом прежде, чем приобрести новые блокировки.

Другое использование UNLOCK TABLES должно выпустить глобальную блокировку чтения, приобретенную с запросом FLUSH TABLES WITH READ LOCK, что позволяет Вам заблокировать все таблицы во всех базах данных. См. раздел 14.7.6.3. Это очень удобный способ получить резервные копии, если у Вас есть файловая система, такая как Veritas, которая может взять снимки вовремя.

Табличная блокировка защищает только от несоответствующих чтений или записей другими сеансами. Сеанс, держащий блокировку WRITE, может выполнить на уровне таблицы такие операции, как DROP TABLE или TRUNCATE TABLE. Для сеансов, держащих блокировку READ, операции DROP TABLE и TRUNCATE TABLE не разрешены.

Следующее обсуждение применяется только к таблицам не-TEMPORARY. LOCK TABLES разрешен (но проигнорирован) для TEMPORARY. К таблице может получить доступ свободно сеанс, в пределах которого она создавалась, независимо от того, чем другая блокировка может быть в действительности. Никакая блокировка не необходима, потому что никакой другой сеанс не может видеть таблицу.

Правила для приобретения блокировки

Чтобы приобрести табличные блокировки в пределах текущего сеанса, используйте LOCK TABLES. Следующие типы блокировки доступны:

READ [LOCAL]:

[LOW_PRIORITY] WRITE:

Если LOCK TABLES должно ждать из-за блокировок, проводимых другими сеансами на любой из таблиц, он блокируется, пока все блокировки не могут быть приобретены.

Сеанс, который требует блокировок, должен приобрести все блокировки, которые требуются в одном запросе LOCK TABLES. В то время как блокировки, полученные таким образом, проводятся, сеанс может получить доступ только к заблокированным таблицам. Например, в следующей последовательности запросов, ошибка происходит для попытки получить доступ к t2, потому что это не было заблокировано LOCK TABLES:

mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 3        |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
Таблицы в INFORMATION_SCHEMA это исключение. К ним можно получить доступ, не будучи заблокированным явно даже в то время, как сеанс считает табличные блокировки полученными LOCK TABLES.

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

mysql> LOCK TABLE t WRITE, t AS t1 READ;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;
Ошибка происходит для первого INSERT ? потому что есть две ссылки на то же самое название заблокированной таблицы. Второq INSERT преуспевает, потому что ссылки на таблицу используют различные имена.

Если Ваши запросы относятся к таблице посредством псевдонима, Вы должны заблокировать таблицу, используя тот же самый псевдоним. Это не работает, чтобы заблокировать таблицу, не определяя псевдоним:

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
Наоборот, если Вы блокируете таблицу, используя псевдоним, Вы должны обратиться к этому в Ваших запросах, используя тот псевдоним:
mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;
Блокировка WRITE обычно имеет более высокий приоритет, чем READ, чтобы гарантировать, что обновления обработаны как можно скорее. Это означает, что если один сеанс получает блокировку READ, а затем другой сеанс просит WRITE, последующая READ ждет, пока сеанс, который просил WRITE получит блокировку и выпустит ее.

LOCK TABLES приобретает блокировки следующим образом:

  1. Сортирует все таблицы, которые будут заблокированы во внутренне определенном порядке. С пользовательской точки зрения этот порядок неопределен.

  2. Если таблица должна быть заблокирована с блокировкой чтения и записи, поместит запрос блокировки записи перед запросом блокировки чтения.
  3. Заблокирует одну таблицу за один раз, пока сеанс не получает все блокировки.

Эта политика гарантирует, что табличная блокировка свободна от тупика.

LOCK TABLES или UNLOCK TABLES, когда относится к разделенной таблице, всегда блокирует всю таблицу, эти запросы не поддерживают блокировку разделов. См. Partitioning and Locking.

Правила для снятия блокировки

Когда табличные блокировки, проводимые сеансом, выпущены, они все освобождены в то же самое время. Сеанс может выпустить свои блокировки явно, или блокировки могут быть выпущены неявно при определенных условиях.

Если соединение для сеанса клиента заканчивается, сервер неявно выпускает все табличные блокировки, проводимые сеансом. Если клиент повторно соединится, то блокировок больше не будет. Кроме того, если у клиента была активная транзакция, сервер откатывает ее при разъединии, и если повторно соединяются, новый сеанс начинается, с включенным autocommit. Поэтому клиенты могут хотеть отключить автоатическое пересоединение. С auto-reconnect клиент не уведомлен, если повторно соединяется, но любые табличные блокировки или текущая транзакция будет потеряна. При выключенном auto-reconnect, если соединение удаляется, ошибка происходит для следующего сделанного запроса. Клиент может обнаружить ошибку и принять соответствующие меры, такие как переприобретение блокировок или восстановление транзакции. См. раздел 25.8.16.

Если Вы используете ALTER TABLE на заблокированной таблице, она может разблокироваться. Например, если Вы делаете попытку второго ALTER TABLE , результат может быть ошибкой Table 'tbl_name' was not locked with LOCK TABLES. Чтобы обработать это, заблокируйте таблицу снова до второго изменения. См. также раздел B.5.6.1.

14.3.5.1. Взаимодействие табличной блокировки и транзакций

LOCK TABLES и UNLOCK TABLES взаимодействуют с использованием транзакций следующим образом:

14.3.5.2. LOCK TABLES и триггеры

Если Вы блокируете таблицу явно с LOCK TABLES, любые таблицы, используемые в триггерах, также заблокированы неявно:

Предположите, что Вы блокируете две таблицы, t1 и t2, с использованием этого запроса:

LOCK TABLES t1 WRITE, t2 READ;
Если t1 или t2 имеют любые триггеры, таблицы, используемые в пределах триггеров, будут также заблокированы. Предположите, что t1 имеет триггер:
CREATE TRIGGER t1_a_ins AFTER INSERT ON t1 FOR EACH ROW
BEGIN
  UPDATE t4 SET count = count+1
  WHERE id = NEW.id AND EXISTS (SELECT a FROM t3);
  INSERT INTO t2 VALUES(1, 2);
END;
Результат LOCK TABLES: t1 и t2 заблокированы, потому что они появляются в запросе, а t3 и t4 заблокированы, потому что они используются в пределах триггера:

14.3.5.3. Блокирующие таблицу ограничения и условия

Вы можете безопасно использовать KILL , чтобы закончить сеанс, который ждет табличной блокировки. См. раздел 14.7.6.4.

LOCK TABLES и UNLOCK TABLES не может использоваться в пределах сохраненных программ.

Таблица в performance_schema не может быть заблокирована с LOCK TABLES, кроме таблиц setup_xxx.

Следующие запросы запрещены в то время, как LOCK TABLES работает: CREATE TABLE, CREATE TABLE ... LIKE, CREATE VIEW, DROP VIEW и запросы DDL о сохраненных функциях, процедурах и событиях.

Для некоторых операций нужно получить доступ к системным таблицам в базе данных mysql. Например, HELP требует содержания серверных таблиц справки, и CONVERT_TZ(), возможно, должен был бы считать таблицы часового пояса. Сервер неявно блокирует системные таблицы для того, чтобы читать по мере необходимости так, чтобы Вы не заблокировали их явно. Эти таблицы обработаны так:

mysql.help_category
mysql.help_keyword
mysql.help_relation
mysql.help_topic
mysql.proc
mysql.time_zone
mysql.time_zone_leap_second
mysql.time_zone_name
mysql.time_zone_transition
mysql.time_zone_transition_type
Если Вы хотите явно поместить блокировку WRITE блокируйте любую из тех таблиц с LOCK TABLES, таблица должна быть единственной заблокированной, никакая другая таблица не может быть заблокирована с тем же самым запросом.

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

Вы можете избегать использования LOCK TABLES во многих случаях при использовании относительных обновлений (UPDATE customer SET value=value+ new_value) или функции LAST_INSERT_ID() .

Вы можете также избежать блокировать таблицы в некоторых случаях при использовании консультативных функций блокировки на уровне пользователя GET_LOCK() и RELEASE_LOCK(). Эти блокировки сохранены в хэш-таблице в сервере и осуществлены с pthread_mutex_lock() и pthread_mutex_unlock(), см. раздел 13.18.

См. раздел 9.11.1.

14.3.6. SET TRANSACTION

SET [GLOBAL | SESSION] TRANSACTION
transaction_characteristic [, transaction_characteristic] ...

transaction_characteristic:
ISOLATION LEVEL level
  | READ WRITE
  | READ ONLY

level:
REPEATABLE READ
   | READ COMMITTED
   | READ UNCOMMITTED
   | SERIALIZABLE
Это запрос определяет параметры транзакции. Это берет список из одного или более значений, отделенных запятыми. Эти характеристики устанавливают операционный уровень изоляции или режим доступа. Уровень изоляции используется для операций на InnoDB. Режим доступа может быть определен относительно того, работают ли транзакции в чтении-записи или режиме только для чтения.

Кроме того, SET TRANSACTION может включать дополнительный параметр GLOBAL или SESSION, чтобы указать на контекст запроса.

Контекст операционных характеристик

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

Глобальное изменение операционных характеристик требует привилегии SUPER. Любой сеанс свободен изменить свои характеристики сеанса (даже в середине транзакции) или характеристики для следующей транзакции.

SET TRANSACTION без GLOBAL или SESSION не разрешен, в то время как есть активная транзакция:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)

mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ERROR 1568 (25001): Transaction characteristics can't be changed
while a transaction is in progress
Чтобы установить глобальный уровень изоляции по умолчанию при запуске сервера, используйте опцию --transaction-isolation=level для mysqld в командной строке или в файле опции. Значения level для этой опции используют тире, а не пробелы, таким образом, допустимые значения READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ или SERIALIZABLE . Например, чтобы установить уровень изоляции по умолчанию в REPEATABLE READ , используйте эти строки в разделе [mysqld] файла опций:
[mysqld]
transaction-isolation = REPEATABLE-READ
Возможно проверить или установить глобальные и операционные уровни изоляции сеанса во времени выполнения при использовании tx_isolation:
SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
SET GLOBAL tx_isolation='REPEATABLE-READ';
SET SESSION tx_isolation='SERIALIZABLE';
Точно так же, чтобы установить операционный режим доступа при запуске сервера или во время выполнения, используйте --transaction-read-only или tx_read_only. По умолчанию они OFF (режим чтение-запись), но могут быть установлен в ON для режима по умолчанию только для чтения.

Установка глобального значения или значения сеанса tx_isolation или tx_read_only эквивалентно установке уровня изоляции или режима доступа с SET GLOBAL TRANSACTION или SET SESSION TRANSACTION.

Операционные уровни изоляции

См. раздел 16.5.2.1.

Операционный режим доступа

Операционный режим доступа может быть определен с SET TRANSACTION. По умолчанию, транзакция имеет место в режиме чтения-записи с чтениями и записями, разрешенными для таблиц, используемых в транзакции. Этот режим может быть определен, явно используя режим доступа READ WRITE.

Если операционный режим доступа установлен в READ ONLY, изменения таблиц запрещены. Это может позволить механизмам хранения сделать исполнительные усовершенствования, которые возможны, когда записи не разрешены.

Не разрешено определить в том же самом запросе READ WRITE и READ ONLY.

В режиме только для чтения остается возможным изменить таблицы, составленные с TEMPORARY, используя запросы DML. Изменения, произведенные с запросами DDL, не разрешены, так же, как с постоянными таблицами.

READ WRITE и READ ONLY также могут быть определены для отдельной транзакции, используя START TRANSACTION.

14.3.7. Транзакции XA

Поддержка транзакций XA доступна для InnoDB. MySQL XA основан на X/Open CAE Distributed Transaction Processing: The XA Specification. Этот документ издан The Open Group и доступен на http://www.opengroup.org/public/pubs/catalog/c193.htm. Ограничения текущего выполнения XA описаны в раздел C.6.

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

Среди MySQL Connectors, MySQL Connector/J 5.0.0 и выше понимает XA непосредственно, посредством интерфейса класса, который обрабатывает интерфейс XA SQL для Вас.

XA поддерживает распределенные транзакции, то есть, способность разрешить многократным отдельным транзакционным ресурсам участвовать в глобальной транзакции. Транзакционные ресурсы часто RDBMS, но могут быть другими видами ресурсов.

Глобальная транзакция вовлекает несколько действий, которые являются транзакционными в себе, но что все должны завершиться успешно как группа или все быть откаченными как группа. В основном это расширяет свойства ACID так, чтобы многократные транзакции могли быть выполнены как компоненты глобальной работы, у которой также есть свойства ACID. Как с нераспределенными транзакциями, SERIALIZABLE может быть предпочтен, если Ваши приложения чувствительны, чтобы считать явления. REPEATABLE READ , возможно, не достаточно для распределенных транзакций.

Некоторые примеры распределенных транзакций:

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

Выполнение MySQL XA позволяет серверу MySQL действовать как Resource Manager, который обрабатывает транзакции XA в пределах глобальной транзакции. Программа клиента, которая соединяется с действиями сервера MySQL как менеджер по транзакции.

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

Процесс для того, чтобы выполнить глобальную транзакцию использует двухфазовую передачу (2PC). Это имеет место после того, как действия, выполненные ответвлениями глобальной транзакции, были выполнены.

  1. В первой фазе подготовлены все ответвления. Таким образом, им говорит ТМ подготовиться передавать. Как правило, это означает каждый RM, который справляется, ответвление делает запись действий для ответвления в устойчивом хранении. Ответвления указывают, в состоянии ли они сделать это, и эти результаты используются для второй фазы.

  2. Во второй фазе ТМ говорит RM передать или откатиться. Если все ответвления указали, когда они были подготовлены, что они будут в состоянии передать, всем ответвлениям говорят передать. Если какое-либо ответвление указало, когда оно было подготовлено, что оно не будет в состоянии передать, всем ответвлениям говорят откатиться.

В некоторых случаях глобальная транзакция могла бы использовать одну фазу передачи (1PC). Например, когда менеджер по транзакции находит, что глобальная транзакция состоит только из одного транзакционного ресурса (то есть, единственное ответвление), ресурсу можно сказать подготовить и передать в то же самое время.

14.3.7.1. Синтаксис XA SQL

Чтобы выполнить транзакции XA в MySQL, используйте следующие запросы:

XA {START|BEGIN} xid [JOIN|RESUME]
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
XA RECOVER [CONVERT XID]
Для XA START JOIN и RESUME не поддержаны.

Для XA END SUSPEND [FOR MIGRATE] не поддержан.

Каждый запрос XA начинается XA и большинство из них требуют значения xid. xid это операционный идентификатор XA. Это указывает, к какой транзакции запрос относится. xid поставляются клиентом или произведены сервером MySQL. xid имеет от одной до трех частей:

xid: gtrid [,
bqual [, formatID ]]
gtrid это глобальный операционный идентификатор, bqual спецификатор ответвления, и formatID число, которое идентифицирует формат, используемый gtrid и bqual. Как обозначено синтаксисом, bqual и formatID являются дополнительными. Значение по умолчанию bqual '', если не дано. Значение по умолчанию formatID 1, если не дано.

gtrid и bqual должны быть строками, каждая до 64 байтов (не символов). gtrid и bqual может быть определен несколькими способами. Вы можете использовать заключенную в кавычки строку ('ab'), шестнадцатеричную строку (X'6162', 0x6162) или битовое значение (b'nnnn').

formatID unsigned integer.

gtrid и bqual интерпретируются в байтах основными подпрограммами поддержки XA сервера MySQL. Однако, в то время, как запрос SQL, содержащмй запрос XA, разбирается, сервер работает с некоторым определенным набором символов. Чтобы быть безопасным, пишите gtrid и bqual как шестнадцатеричные строки.

xid, как правило, производятся менеджером по транзакции. Значения, произведенные одним ТМ, должны отличаться от значений, произведенных другими ТМ. Данный ТМ должен быть в состоянии признать свой собственный xid в списке значений, возвращенных XA RECOVER.

Для XA START xid запускает транзакцию XA с данным значением xid. У каждой транзакции XA должно быть уникальное значение xid, таким образом, значение не должно в настоящее время использоваться другой транзакцией XA. Уникальность оценена, используя gtrid и bqual. Все последующие запросы XA для транзакции XA должны быть определены, используя то же самое значение XA START. Если Вы используете какое-либо из тех запросов, но определяете xid, которое не соответствует некоторой существующей транзакции XA, ошибка происходит.

Одна или более транзакций XA могут быть частью той же самой глобальной транзакции. Все транзакции XA в пределах данной глобальной транзакции должны использовать то же самое значение gtrid в xid. Поэтому значения gtrid должны быть глобально уникальными так, чтобы не было никакой двусмысленности. bqual часть xid должна отличаться для каждой транзакции XA в пределах глобальной транзакции. Требование, что значения bqual должны отличаться, является ограничением текущего MySQL-выполнения XA. Это не часть спецификации XA.

XA RECOVER возвращает информацию для тех транзакций XA на сервере MySQL, которые находятся в состоянии PREPARED, см. раздел 14.3.7.2. Вывод включает строку для каждой такой транзакции XA на сервере, независимо от того, который клиент запустил это.

XA RECOVER выходные строки похожи на это (для примера xid состоит из частей 'abc', 'def' и 7):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
| 7        | 3            | 3            | abcdef |
+----------+--------------+--------------+--------+
У выходных столбцов есть следующие значения:

XID могут содержать непригодные для печати символы. XA RECOVER разрешает дополнительный параметр CONVERT XID так, чтобы клиенты могли просить значения XID в шестнадцатеричном виде.

14.3.7.2. Операционные состояния XA

Транзакция XA прогрессирует через следующие состояния:

  1. Используйте XA START, чтобы запустить транзакцию XA и перевести в статус ACTIVE.

  2. Для ACTIVE транзакций XA сделайте запросы SQL, которые составляют транзакцию, а затем XA END. XA END отправит транзакцию в состояние IDLE.
  3. Для IDLE транзакций XA Вы можете скомандовать XA PREPARE или XA COMMIT ... ONE PHASE:

  4. Для PREPARED XA транзакций Вы можете скомандовать XA COMMIT, чтобы передать и закончить транзакцию, или XA ROLLBACK для отката.

Вот простая транзакция XA, которая вставляет строку в таблицу как часть глобальной транзакции:

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)

mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)

mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
В пределах контекста данного соединения клиента транзакции XA и местные транзакции (не-XA) являются взаимоисключающими. Например, если XA START выпущен, чтобы начать транзакцию XA, местная транзакция не может быть запущена, пока транзакция XA не была передана или отменена. Наоборот, если местная транзакция была запущена с START TRANSACTION, никакие запросы XA не могут использоваться, пока транзакция не была передана или отменена.

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

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed
when global transaction is in the ACTIVE state
Запросы, к которым применяется предыдущее замечание, перечислены в разделе 14.3.3.

14.4. Запросы репликации

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

14.4.1. Запросы SQL для управления главными серверами

Этот раздел обсуждает запросы для основных серверов.

В дополнение к запросым, описанным здесь, запросы SHOW используются с главными серверами. Для информации об этих запросах см. раздел 14.7.5.

14.4.1.1. PURGE BINARY LOGS

PURGE { BINARY | MASTER } LOGS
{ TO 'log_name' | BEFORE datetime_expr }
Двоичный журнал это ряд файлов, которые содержат информацию о модификациях данных, сделанных сервером MySQL. Журнал состоит из ряда двоичных файлов системного журнала плюс индексный файл (см. раздел 6.4.4).

PURGE BINARY LOGS удаляет все двоичные файлы системного журнала, перечисленные в индексном файле журнала до указанного имени файла системного журнала или даты. BINARY и MASTER синонимы. Удаленные файлы системного журнала также удалены из списка, зарегистрированного в индексном файле, так, чтобы данный файл системного журнала стал первым в списке.

Этот запрос не имеет никакого эффекта, если сервер не был запущен с опцией --log-bin.

Примеры:

PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';
BEFORE разновидность параметра datetime_expr должен оцениваться к значению DATETIME (значение в формате 'YYYY-MM-DD hh:mm:ss').

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

Чтобы безопасно произвести чистку двоичных файлов системного журнала, следуйте за этой процедурой:

  1. На каждом ведомом сервере надо использовать SHOW SLAVE STATUS, чтобы проверить, какой файл системного журнала это читает.

  2. Получите перечисление двоичных файлов системного журнала на главном сервере с помощью SHOW BINARY LOGS .
  3. Определите самый ранний файл системного журнала среди всех ведомых устройств. Это конечный файл. Если все ведомые устройства современны, это последний файл системного журнала в списке.
  4. Сделайте резервное копирование всех файлов системного журнала, которые Вы собираетесь удалить. Этот шаг является дополнительным, но всегда желательным.
  5. Произведите чистку всех файлов системного журнала до, но не включая конечный файл.

Вы можете также установить expire_logs_days , чтобы двоичные файлы системного журнала автоматически удалялись после данного числа дней (см. раздел 6.1.5). Если Вы используете репликацию, Вы должны установить переменную не ниже, чем максимальное количество дней, на которое Ваши ведомые устройства могли бы отстать от ведущего устройства.

PURGE BINARY LOGS TO и PURGE BINARY LOGS BEFORE оба терпят неудачу с ошибкой, когда двоичные файлы системного журнала, перечисленные в файле .index, были удалены из системы некоторыми другими средствами (такими, как использование rm в Linux) (Bug #18199, Bug #18453). Чтобы обработать такие ошибки, редактируйте файл .index (который является простым текстовым файлом) вручную, чтобы гарантировать, что он перечисляет только двоичные файлы системного журнала, которые фактически присутствуют, затем выполните снова PURGE BINARY LOGS.

14.4.1.2. RESET MASTER

RESET MASTER
Удаляет все двоичные файлы системного журнала, перечисленные в индексном файле, сбрасывает двоичной индексный файл журнала и создает новый двоичной файл системного журнала.

RESET MASTER также очищает значения gtid_purged так же как глобальное значение gtid_executed (но не ее значение сеанса), то есть, выполнение этого запроса устанавливает каждое из этих значений к пустой строке (''). Этот запрос также очищает таблицу mysql.gtid_executed (см. mysql.gtid_executed Table).

Это запрос предназначен, чтобы использоваться только, когда ведущее устройство запущено впервые.

Эффекты RESET MASTER отличаются от таковых в PURGE BINARY LOGS:

  1. RESET MASTER удаляет все двоичные файлы системного журнала, которые перечислены в индексном файле, оставляя только единственный пустой двоичной файл системного журнала с числовым суффиксом .000001, тогда как нумерация не сброшена PURGE BINARY LOGS.

  2. RESET MASTER не предназначен, чтобы использоваться, в то время как любые ведомые устройства работают. Поведение RESET MASTER когда используется в то время, как ведомые устройства работают, неопределено (и таким образом неподдержано), тогда как PURGE BINARY LOGS может безопасно использоваться в то время, как ведомые устройства работают.

См. раздел 14.4.1.1.

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

  1. Запустите ведущее и ведомое устройства и запустите репликацию (см. раздел 19.1.2).

  2. Выполните несколько испытательных запросов на ведущем устройстве.
  3. Проверьте, что запросы копировались к ведомому устройству.
  4. Когда репликация работает правильно, скомандуйте STOP SLAVE и RESET SLAVE на ведомом устройстве, затем проверьте, что любые нежелательные данные больше не существуют на ведомом устройстве.
  5. Скомандуйте RESET MASTER на ведущем устройстве, чтобы очистить испытательные запросы.

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

14.4.1.3. SET sql_log_bin

SET sql_log_bin = {0|1}
sql_log_bin управляет, сделано ли журналирование к двоичному журналу. Значение по умолчанию 1 (сделано журналирование). Чтобы изменить журналирование для текущего сеанса, измените значение этой переменной. Пользователь сеанса должен иметь привилегию SUPER , чтобы установить эту переменную. Установите эту переменную в 0 для сеанса, чтобы временно отключить двоичное журналирование, производя изменения в ведущем устройстве, которые Вы не хотите копировать к ведомому устройству.

С MySQL 5.5 sql_log_bin может быть установлен как глобальная переменная или переменная сеанса. Установка sql_log_bin глобально обнаружена только, когда новый сеанс запущен. На любые ранее работающие сеансы глобальная установка не воздействует.

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

В MySQL 5.7 невозможно установить @@session.sql_log_bin в пределах транзакции или подзапроса (Bug #53437).

14.4.2. Запросы SQL для управления ведомыми серверами

В дополнение к запросам, описанным здесь, SHOW SLAVE STATUS и SHOW RELAYLOG EVENTS также используются с ведомыми устройствами ответа. Для информации об этих запросах см. разделы 14.7.5.34 и 14.7.5.32.

14.4.2.1. CHANGE MASTER TO

CHANGE MASTER TO option [, option]
       ... [ channel_option ]
option:
MASTER_BIND = 'interface_name'
  | MASTER_HOST = 'host_name'
  | MASTER_USER = 'user_name'
  | MASTER_PASSWORD = 'password'
  | MASTER_PORT = port_num
  | MASTER_CONNECT_RETRY = interval
  | MASTER_RETRY_COUNT = count
  | MASTER_DELAY = interval
  | MASTER_HEARTBEAT_PERIOD = interval
  | MASTER_LOG_FILE = 'master_log_name'
  | MASTER_LOG_POS = master_log_pos
  | MASTER_AUTO_POSITION = {0|1}
  | RELAY_LOG_FILE = 'relay_log_name'
  | RELAY_LOG_POS = relay_log_pos
  | MASTER_SSL = {0|1}
  | MASTER_SSL_CA = 'ca_file_name'
  | MASTER_SSL_CAPATH = 'ca_directory_name'
  | MASTER_SSL_CERT = 'cert_file_name'
  | MASTER_SSL_CRL = 'crl_file_name'
  | MASTER_SSL_CRLPATH = 'crl_directory_name'
  | MASTER_SSL_KEY = 'key_file_name'
  | MASTER_SSL_CIPHER = 'cipher_list'
  | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}
  | MASTER_TLS_VERSION = 'protocol_list'
  | IGNORE_SERVER_IDS = (server_id_list)

channel_option:
FOR CHANNEL channel

server_id_list:
[server_id [, server_id] ... ]
CHANGE MASTER TO изменяет параметры, которые ведомый сервер использует для того, чтобы соединиться с главным сервером, для того, чтобы считать основной двоичной журнал и считать ведомый журнал. Это также обновляет содержание основной информации и репозитариев информации журнала (см. раздел 19.2.4).

Можно использовать CHANGE MASTER TO запрос о рабочем ведомом устройстве без остановки этого, в зависимости от статуса ведомого потока SQL и ведомого потока ввода/вывода. Правила, управляющие таким использованием, обеспечены позже в этом разделе.

Используя мультипоточное ведомое устройство (другими словами, slave_parallel_workers больше 0), остановка ведомого устройства может вызвать промежутки в последовательности транзакций, которые были выполнены от журнала, независимо от того, было ли ведомое устройство остановлено преднамеренно или нет. Когда такие промежутки существуют, CHANGE MASTER TO терпит неудачу. Решение в этой ситуации состоит в том, чтобы вызвать START SLAVE UNTIL SQL_AFTER_MTS_GAPS , который гарантирует, что разрывы преодолены.

FOR CHANNEL channel позволяет Вам выбрать, к которому каналу ответа относится запрос. Если никакой пункт не установлен, и никакие дополнительные каналы не существуют, запрос относится к каналу значения по умолчанию и ведет себя как версии MySQL до 5.7.6. Обеспечение FOR CHANNEL channel применяет CHANGE MASTER TO к определенному каналу ответа и используется, чтобы добавить новый канал или изменить существующий канал. Например, чтобы добавить новый канал, названный channel2:

CHANGE MASTER TO MASTER_NAME=host1, MASTER_PORT=3002 FOR CHANNEL channel2
Используя многократные каналы ответа, если у CHANGE MASTER TO нет определенного использования канала FOR CHANNEL channel , получите ошибку. См. раздел 19.2.3.

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

MASTER_HOST, MASTER_USER, MASTER_PASSWORD и MASTER_PORT предоставляют информацию ведомому устройству о том, как соединиться с его ведущим устройством:

Опции MASTER_SSL_xxx предоставляют информацию об использовании SSL для соединения. Они соответствуют опциям --ssl-xxx, описанным в разделах 7.4.5 и 19.3.9. Эти опции могут быть изменены даже на ведомых устройствах, которые собраны без поддержки SSL. Они сохранены к основному репозитарию информации, но проигнорированы, если у ведомого устройства нет поддержки SSL.

MASTER_SSL=1 является предписывающим, не консультативным. Когда дано, соединение с ведущим устройством должно использовать SSL, или попытка соединения терпит неудачу.

MASTER_TLS_VERSION определяет протоколы шифрования, разрешенные ведущим устройством для ведомых соединений. Значение походит на это для tls_version: список разделенных запятой значений, содержащий одно или более имен протокола. Протоколы, которые могут быть названы в этой опции, зависят от библиотеки SSL, использовавшейся, чтобы собрать MySQL. Для деталей см. раздел 7.4.3.

MASTER_CONNECT_RETRY определяет, сколько секунд ждать между повторениями соединения. Значение по умолчанию 60.

MASTER_RETRY_COUNT ограничивает number число попыток пересоединения и обновляет значение столбца Master_Retry_Count в выводе SHOW SLAVE STATUS. Значение по умолчанию 24 * 3600 = 86400. MASTER_RETRY_COUNT предназначена, чтобы заменить более старую опцию --master-retry-count и является теперь привилегированным методом для того, чтобы установить этот предел. Лучше не использовать --master-retry-count в новых приложениях и, обновляясь до MySQL 8.0, обновить любые существующие приложения, которые полагаются на это, так, чтобы они использовали CHANGE MASTER TO ... MASTER_RETRY_COUNT.

MASTER_DELAY определяет, на сколько секунд от ведущего устройства ведомое устройство должно отстать. Событие от ведущего устройства не запущено, по крайней мере, interval секунд. Значение по умолчанию 0. Ошибка происходит, если interval не неотрицательное целое число в диапазоне от 0 до 231-1. См. раздел 19.3.11.

CHANGE MASTER TO, использующий опцию MASTER_DELAY может быть выполнен на рабочем ведомом устройстве, когда ведомый поток SQL остановлен.

MASTER_BIND для использования на ведомых устройствах, имеющих многократные сетевые интерфейсы, и определяет, какой из сетевых интерфейсов ведомого устройства выбран для того, чтобы соединиться с ведущим устройством.

Адрес, сконфигурированный с этой опцией, если таковой вообще имеется, может быть найден в столбце Master_Bind вывода SHOW SLAVE STATUS. Если Вы используете ведомые таблицы журнала состояния (сервер запускался с --master-info-repository=TABLE), значение может также быть найдено как столбец Master_bind таблицы mysql.slave_master_info .

MASTER_HEARTBEAT_PERIOD устанавливает интервал в секундах между тактами репликации. Всякий раз, когда двоичной журнал ведущего устройства обновлен, время ожидания для следующего такта сброшено. interval это десятичное значение, имеющее диапазон от 0 до 4294967 секунд и разрешение в миллисекунду, самое маленькое ненулевое значение 0.001. Такты посылает ведущее устройство, только если нет никаких непосланных событий в двоичном файле системного журнала в течение периода дольше interval.

Если Вы регистрируете основную информацию о соединении к таблицам, MASTER_HEARTBEAT_PERIOD может быть замечен как значение столбца Heartbeat таблицы mysql.slave_master_info.

Установка interval к 0 отключает такты вообще. Значение по умолчанию для interval равно значению slave_net_timeout , разделенному на 2.

Установка @@global.slave_net_timeout к значению меньше текущего интервала приводит к предупреждению. Эффект RESET SLAVE на интервал должен сбросить это к значению по умолчанию.

MASTER_LOG_FILE и MASTER_LOG_POS координаты, в которых ведомый поток ввода/вывода должен начать читать от ведущего устройства в следующий раз, когда поток запускается. RELAY_LOG_FILE и RELAY_LOG_POS координаты, в которых ведомый поток SQL должен начать читать из журнала реле в следующий раз, когда поток запускается. Если Вы определяете любой из MASTER_LOG_FILE или MASTER_LOG_POS, Вы не можете определить RELAY_LOG_FILE или RELAY_LOG_POS. Если Вы определяете любой из MASTER_LOG_FILE или MASTER_LOG_POS, Вы также не можете определить MASTER_AUTO_POSITION = 1 (описан позже в этом разделе). Если ни один из MASTER_LOG_FILE или MASTER_LOG_POS не определен, ведомое устройство использует последние координаты ведомого потока SQL перед CHANGE MASTER TO. Это гарантирует, что нет никакой неоднородности в ответе, даже если ведомый поток SQL был позже по сравнению с ведомым потоком ввода/вывода, когда Вы просто хотите изменить, скажем, пароль.

CHANGE MASTER TO, использующий опции RELAY_LOG_FILE, RELAY_LOG_POS или обе сразу, может быть выполнен на рабочем ведомом устройстве, когда ведомый поток SQL остановлен.

Если MASTER_AUTO_POSITION = 1 с CHANGE MASTER TO , ведомое устройство пытается соединиться с ведущим устройством, использующим протокол GTID. Эта опция может использоваться CHANGE MASTER TO только, если ведомый SQL и ведомые потоки ввода/вывода остановлены.

Используя GTID, ведомое устройство говорит ведущему устройству, какие транзакции это уже приняло, выполнило или то и другое. Чтобы вычислить этот набор, это читает глобальное значение gtid_executed и значение столбца Retrieved_gtid_set из SHOW SLAVE STATUS. Так как GTID последней переданной транзакции включен в Retrieved_gtid_set, даже если транзакция была только частично передана, последний полученный GTID вычтен из этого набора. Таким образом, ведомое устройство вычисляет следующий набор:

UNION(@@global.gtid_executed, Retrieved_gtid_set-last_received_GTID)
Этот набор посылают ведущему устройству как часть начального квитирования, а ведущее устройство отсылает назад все транзакции, которые выполнило, но которые не являются частью набора. Если какая-либо из этих транзакций была уже удалена из двоичного журнала ведущего устройства, ведущее устройство посылает ошибку ER_MASTER_HAS_PURGED_REQUIRED_GTIDS, и репликация не запускается.

Когда GTID-репликация используется, координаты, представленные MASTER_LOG_FILE и MASTER_LOG_POS не используются, и глобальные операционные идентификаторы используются вместо этого. Таким образом использование обеих опций вместе с MASTER_AUTO_POSITION будет ошибкой.

Вы можете видеть, работает ли ответ с автопозиционированием, проверяя вывод SHOW SLAVE STATUS.

gtid_mode должен также быть включен перед CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1. Иначе запрос терпит неудачу с ошибкой.

Чтобы вернуться к более старому основанному на файле протоколу после использования GTID, Вы можете скомандовать CHANGE MASTER TO, который определяет MASTER_AUTO_POSITION = 0, так же как по крайней мере один из MASTER_LOG_FILE или MASTER_LOG_POSITION.

Журналы реле сохранены, когда ни ведомый поток SQL, ни ведомый поток ввода/вывода не остановлены, если оба потока остановлены, все файлы системного журнала реле не удалены, если Вы указали по крайней мере одну из опций RELAY_LOG_FILE или RELAY_LOG_POS.

RELAY_LOG_FILE может использовать абсолютный или относительный путь, и использует то же самое базовое имя, как MASTER_LOG_FILE (Bug #12190).

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

В круговой репликации оригинальный сервер обычно действует как разделитель его собственных событий, чтобы они не были применены не раз. Таким образом, эта опция полезна в круговой рпликации, когда один из серверов удален. Предположите, что у Вас есть круговая установка репликации с 4 серверами, ID 1, 2, 3 и 4, а сервер 3 упал. Соединяя промежуток, запуская репликацию с сервера 2 на сервер 4, Вы можете включить IGNORE_SERVER_IDS = (3) в CHANGE MASTER TO на сервере 4, чтобы сказать этому использовать сервер 2 в качестве его ведущего устройства вместо сервера 3. Это причина проигнорировать, а не размножить любые запросы, которые произошли с сервером, который больше не находится в использовании.

Если CHANGE MASTER TO без IGNORE_SERVER_IDS, любой существующий список сохранен. Чтобы очистить список проигнорированных серверов, необходимо использовать опцию с пустым списком:

CHANGE MASTER TO IGNORE_SERVER_IDS = ();
RESET SLAVE ALL очищает IGNORE_SERVER_IDS. До MySQL 5.7 это не сделано.

Если IGNORE_SERVER_IDS содержит ID сервера, и сервер был запущен с --replicate-same-server-id, будет ошибка.

В MySQL 8.0 основной репозитарий информации и вывод SHOW SLAVE STATUS обеспечивает список серверов, которые в настоящее время игнорируются. Для получения дополнительной информации см. разделы 19.2.4.2 и 14.7.5.34.

В MySQL 8.0 вызов CHANGE MASTER TO вызывает запись предыдущих значений MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE и MASTER_LOG_POS в журнал ошибок, наряду с другой информацией о статусе ведомого устройства до выполнения.

В MySQL 8.0 CHANGE MASTER TO неявно закрывает продолжающиеся транзакции. См. раздел 14.3.3.

Строгое требование, чтобы выполнить STOP SLAVE до любого CHANGE MASTER TOSTART SLAVE позже) удалено. Вместо этого, в зависимости от того, остановлено ли ведомое устройство, логика CHANGE MASTER TO зависит от статуса ведомого потока SQL и ведомых потоков ввода/вывода, какой из этих потоков остановлен или работает, теперь определяют опции, которые могут или не могут использоваться с CHANGE MASTER TO в данном моменте времени. Правила для того, чтобы сделать это определение перечислены здесь:

Вы можете проверить текущее состояние ведомого SQL и потоков ввода/вывода с использованием SHOW SLAVE STATUS.

См. раздел 19.3.8.

Если Вы используете основанную на запросе репликацию и временные таблицы, это возможно для CHANGE MASTER TO после STOP SLAVE оставить позади временные таблицы на ведомом устройстве. Предупреждение (ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO ) теперь выпущено всякий раз, когда это происходит. Вы можете избежать этого удостоверяясь, что значение Slave_open_temp_tables = 0 до выполнения такого CHANGE MASTER TO.

CHANGE MASTER TO полезно для установки ведомого устройства, когда Вы имеете снимок ведущего устройства и сделали запись основных двоичных координат журнала, соответствующих времени снимка. После загрузки снимка в ведомое устройство, чтобы синхронизировать это с ведущим устройством, Вы можете выполнить CHANGE MASTER TO MASTER_LOG_FILE='log_name', MASTER_LOG_POS=log_pos на ведомом устройстве, чтобы определить координаты, в которых ведомое устройство должно начать читать основной двоичной журнал.

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

CHANGE MASTER TO MASTER_HOST='master2.mycompany.com',
       MASTER_USER='replication', MASTER_PASSWORD='bigs3cret',
       MASTER_PORT=3306, MASTER_LOG_FILE='master2-bin.001',
       MASTER_LOG_POS=4, MASTER_CONNECT_RETRY=10;
Следующий пример показывает работу, которая менее часто используется. Это используется, когда у ведомого устройства есть файлы системного журнала реле, которые Вы хотите, чтобы это выполнило снова по некоторым причинам. Вы должны использовать только CHANGE MASTER TO и запустите поток SQL (START SLAVE SQL_THREAD ):
CHANGE MASTER TO RELAY_LOG_FILE='slave-relay-bin.006',
       RELAY_LOG_POS=4025;
Вы можете даже использовать вторую операцию в установке без репликации с автономным, неведомым, сервером для восстановления после катастрофического отказа. Предположите, что Ваш сервер отказал, и Вы восстановили его из резервной копии. Вы хотите переиграть собственные двоичные файлы системного журнала сервера (не файлы системного журнала реле, а регулярные двоичные файлы системного журнала), названные (например) myhost-bin.*. Во-первых, сделайте резервную копию этих двоичных файлов системного журнала в некотором безопасном месте, в случае, если Вы точно не следуете за процедурой ниже и случайно имеете чистку двоичного журнала сервера. Используйте SET GLOBAL relay_log_purge=0 для дополнительной безопасности. Тогда запустите сервер без опции --log-bin, вместо этого используйте --replicate-same-server-id, --relay-log=myhost-bin (чтобы заставить сервер полагать, что эти регулярные двоичные файлы системного журнала это файлы системного журнала реле), и --skip-slave-start. После того, как сервер запускается, сделайте эти запросы:
CHANGE MASTER TO RELAY_LOG_FILE='myhost-bin.153',
       RELAY_LOG_POS=410, MASTER_HOST='some_dummy_string';
       START SLAVE SQL_THREAD;
Сервер читает и выполняет свои собственные двоичные файлы системного журнала, таким образом достигая восстановления катастрофического отказа. Как только восстановление закончено, выполните STOP SLAVE, закройте сервер, очистите основную информацию и репозитарии информации журнала реле, и перезапустите сервер с его оригинальными опциями.

Определение MASTER_HOST (даже с фиктивным значением) обязано заставлять сервер думать, что это ведомое устройство.

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

ОпцияМаксимальная длина
MASTER_HOST60
MASTER_USER16
MASTER_PASSWORD32
MASTER_LOG_FILE255
RELAY_LOG_FILE255
MASTER_SSL_CA255
MASTER_SSL_CAPATH255
MASTER_SSL_CERT255
MASTER_SSL_CRL255
MASTER_SSL_CRLPATH255
MASTER_SSL_KEY255
MASTER_SSL_CIPHER511

14.4.2.2. CHANGE REPLICATION FILTER

CHANGE REPLICATION FILTER filter[, filter][, ...]
filter:
REPLICATE_DO_DB = (db_list)
  | REPLICATE_IGNORE_DB = (db_list)
  | REPLICATE_DO_TABLE = (tbl_list)
  | REPLICATE_IGNORE_TABLE = (tbl_list)
  | REPLICATE_WILD_DO_TABLE = (wild_tbl_list)
  | REPLICATE_WILD_IGNORE_TABLE = (wild_tbl_list)
  | REPLICATE_REWRITE_DB = (db_pair_list)
db_list:
db_name[, db_name][, ...]
tbl_list:
db_name.table_name[, db_table_name][, ...]
wild_tbl_list:
'db_pattern.table_pattern'[, 'db_pattern.table_pattern'][, ...]
db_pair_list:
(db_pair)[, (db_pair)][, ...]
db_pair:
from_db, to_db
CHANGE REPLICATION FILTER определяет один или более фильтров на ведомом устройстве таким же образом, как при запуске ведомого устройства mysqld с опциями фильтрации --replicate-do-db или --replicate-wild-ignore-table. В отличие от случая с параметрами сервера, этот запрос не требует перезапуска сервера, чтобы вступить в силу, только чтобы ведомый поток SQL был остановлен, используя STOP SLAVE SQL_THREAD (и перезапущен через START SLAVE SQL_THREAD).

Следующий список показывает опции CHANGE REPLICATION FILTER, и как они касаются параметров сервера --replicate-*:

Точные эффекты REPLICATE_DO_DB и REPLICATE_IGNORE_DB зависят от того, основана репликация на запросе или на строке в действительности. См. раздел 19.2.5 .

Многократные правила фильтрации ответа могут быть созданы в одном запросе CHANGE REPLICATION FILTER , отделяя правила запятыми, как показано здесь:

CHANGE REPLICATION FILTER
       REPLICATE_DO_DB = (d1), REPLICATE_IGNORE_DB = (d2);
Это эквивалентно запуску ведомого устройства mysqld с опциями --replicate-do-db=d1 и --replicate-ignore-db=d2.

Если то же самое правило фильтрации определено многократно, только последнее такое правило фактически используется. Например, эти два запросы, показанные здесь, имеют точно тот же самый эффект, потому что первое правило REPLICATE_DO_DB в первом запросе проигнорировано:

CHANGE REPLICATION FILTER
       REPLICATE_DO_DB = (db1, db2), REPLICATE_DO_DB = (db3, db4);
CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db3,db4);

Это поведение отличается от поведения из опции фильтра --replicate-*, где определение той же самой опции много раз вызывает создание многократных правил фильтра.

Названия таблиц и базы данных, не содержащих любых специальных символов, не должны быть заключены в кавычки. Значения, используемые с REPLICATION_WILD_TABLE и REPLICATION_WILD_IGNORE_TABLE это строковые выражения, возможно, содержащие (специальные) подстановочные символы, и должны быть заключены в кавычки. Это показывают в следующих запросах в качестве примера:

CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db1.old%');
CHANGE REPLICATION FILTER
       REPLICATE_WILD_IGNORE_TABLE = ('db1.new%', 'db2.new%');
Значения, используемые с REPLICATE_REWRITE_DB это пары имен базы данных, каждое такое значение должно быть приложено в круглых скобках. Следующий запрос переписывает запросы, происходящие в базе данных dbA в базу данных dbB:
CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB = ((db1, db2));
Запрос содержит два набора круглых скобок, один включает пару имен базы данных, другой весь список. Это более легко видно в следующем примере, который создает два правила rewrite-db, одно переписывает база данных dbA в dbB, второе переписывает базу данных dbC в dbD:
CHANGE REPLICATION FILTER
       REPLICATE_REWRITE_DB = ((dbA, dbB), (dbC, dbD));
Этот запрос оставляет любые существующие правила фильтрации неизменными, чтобы сбросить все фильтры данного типа, установите значение фильтра в явно пустой список, как показано в этом примере, который удаляет все существующие правила REPLICATE_DO_DB и REPLICATE_IGNORE_DB:
CHANGE REPLICATION FILTER
       REPLICATE_DO_DB = (), REPLICATE_IGNORE_DB = ();
Установка фильтра таким образом удаляет все существующие правила, не создает новых и не восстанавливает набор правил при использовании запуска mysqld с опциями --replicate-*.

Значения, используемые с REPLICATE_WILD_DO_TABLE и REPLICATE_WILD_IGNORE_TABLE, должны быть в формате db_name.tbl_name.

См. раздел 19.2.5.

14.4.2.3. MASTER_POS_WAIT()

SELECT MASTER_POS_WAIT('master_log_file',
master_log_pos [, timeout][,
channel])
Это фактически функция, не запрос. Это используется, чтобы гарантировать, что ведомое устройство считало и запустило события до данной позиции в двоичном журнале ведущего устройства. См. раздел 13.18.

14.4.2.4. RESET SLAVE

RESET SLAVE [ALL] [channel_option]
channel_option:
FOR CHANNEL channel
RESET SLAVE заставляет ведомое устройство забыть свою позицию в двоичном журнале ведущего устройства. Этот запрос предназначается для чистого запуска: это очищает основную информацию и репозитарии информации журнала реле, удаляет все файлы системного журнала реле и запускает новый файл системного журнала реле. Это также сбрасывает к 0 задержку, определенную опцией MASTER_DELAY в CHANGE MASTER TO. Чтобы использовать RESET SLAVE, ведомые потоки должны быть остановлены (с использованием STOP SLAVE в случае необходимости).

Все файлы системного журнала реле удалены, даже если они не были полностью выполнены ведомым потоком SQL. Это условие, чтобы существовать на ведомом устройстве ответа, если Вы выполнили STOP SLAVE или если ведомое устройство чрезвычайно загружено.

Опция FOR CHANNEL channel позволяет Вам выбрать, к которому каналу ответа относится запрос. Если никакой пункт не установлен, и никакие дополнительные каналы не существуют, запрос относится к каналу по умолчанию и ведет себя как версии MySQL до 5.7.6. Обеспечение FOR CHANNEL channel применяет RESET SLAVE к определенному каналу. Объединение FOR CHANNEL channel с опцией ALL удаляет указанный канал. RESET SLAVE ALL без FOR CHANNEL channel, когда многократные каналы существуют, удаляет все каналы и обновляет только канал по умолчанию. См. раздел 19.2.3.

RESET SLAVE не изменяет параметров соединения, таких как основной узел, порт, пользователь или пароль, которые сохранены в памяти. Это означает, что START SLAVE может быть выпущен, не требуя CHANGE MASTER TO с RESET SLAVE.

Параметры соединения сброшены RESET SLAVE ALL. RESET SLAVE сопровождаемый перезапуском ведомого устройства mysqld также делает это.

В MySQL 8.0 RESET SLAVE неявно закрывает транзакции. См. раздел 14.3.3.

Если ведомый поток SQL был в середине мультиплицирования временных таблиц, когда это было остановлено, и RESET SLAVE выпущен, эти копируемые временные таблицы удалены на ведомом устройстве.

До MySQL 5.7.5 RESET SLAVE также имеет эффект сброса обоих периодов такта ( Slave_heartbeat_period) и SSL_VERIFY_SERVER_CERT. Эта проблема исправлена в MySQL 5.7.5 и позже (Bug #18777899, Bug #18778485).

RESET SLAVE ALL очищает список IGNORE_SERVER_IDS, установленный CHANGE MASTER TO.

14.4.2.5. SET GLOBAL sql_slave_skip_counter

SET GLOBAL sql_slave_skip_counter = N
Этот запрос пропускает следующие N событий от ведущего устройства. Это полезно для восстановления от остановок, вызванных запросом.

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

Используя этот запрос, важно понять, что двоичной журнал фактически организован как последовательность групп, известных как группы событий. Каждая группа событий состоит из последовательности событий.

Единственная транзакция может содержать изменения транзакционных и нетранзакционных таблиц.

Когда Вы используете SET GLOBAL sql_slave_skip_counter, чтобы пропускать события, и результат находится в середине группы, ведомое устройство продолжает пропускать события, пока это не достигает конца группы. Выполнение тогда запускается со следующей группы событий.

14.4.2.6. START SLAVE

START SLAVE [thread_types] [until_option]
[connection_options] [channel_option]
thread_types:
[thread_type [, thread_type] ... ]
thread_type:
IO_THREAD | SQL_THREAD
until_option:
UNTIL {{SQL_BEFORE_GTIDS | SQL_AFTER_GTIDS} = gtid_set
  |  MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
  |  RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos
  |  SQL_AFTER_MTS_GAPS  }

connection_options:
[USER='user_name'] [PASSWORD='user_pass']
[DEFAULT_AUTH='plugin_name']
[PLUGIN_DIR='plugin_dir']
channel_option:
FOR CHANNEL channel
gtid_set:
uuid_set [, uuid_set] ... | ''
uuid_set:
uuid:interval[:interval]...
uuid:
hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh
h: [0-9,A-F]
interval:
n[-n]
(n >= 1)
START SLAVE без thread_type запускает оба ведомых потока. Поток ввода/вывода читает события из главного сервера и хранит их в журнале реле. Поток событий SQL читает из журнала реле и выполняет их. START SLAVE требует привилегии SUPER.

Если START SLAVE преуспевает в том, чтобы запустить ведомые потоки, это возвращается без ошибки. Однако, даже в этом случае, могло бы случиться так, что ведомые потоки запускаются и затем останавливаются позже (например, потому что им не удается соединиться с ведущим устройством или считать двоичной журнал). START SLAVE не предупреждает Вас об этом. Вы должны проверить журнал ошибок ведомого устройства на сообщения об ошибках, произведенные ведомыми потоками, или проверить, что они работают удовлетворительно с помощью SHOW SLAVE STATUS.

START SLAVE неявно передает продолжающиеся транзакции. См. раздел 14.3.3.

gtid_next должен быть установлен в AUTOMATIC прежде, чем сделать этот запрос.

FOR CHANNEL channel позволяет Вам выбрать, к которому каналу ответа относится запрос. Если не установлен, и никакие дополнительные каналы не существуют, запрос относится к каналу по умолчанию и ведет себя как MySQL до 5.7.6. Обеспечение FOR CHANNEL channel применяет START SLAVE к определенному каналу. Если START SLAVE не определяли канал, используя многократные каналы, это запрос запускает указанные потоки для всех каналов. Этот запрос отвергнут для канала group_replication_recovery. См. раздел 19.2.3.

MySQL 8.0 поддерживает аутентификацию пользовательского пароля с START SLAVE с параметрами USER, PASSWORD, DEFAULT_AUTH и PLUGIN_DIR, как описано в следующем списке:

Вы не можете использовать SQL_THREAD, определяя любой из параметров USER, PASSWORD, DEFAULT_AUTH или PLUGIN_DIR, если IO_THREAD также предоставлена.

См. раздел 7.3.9.

Если опасное соединение используется с какими-либо этими опциями, сервер выдает предупреждение Sending passwords in plain text without SSL/TLS is extremely insecure.

START SLAVE ... UNTIL поддерживает две дополнительных опции для использования с глобальными операционными идентификаторами (GTID) (см. раздел 19.1.3). Каждая из них берет один или более глобальных операционных идентификаторов gtid_set как аргумент.

Когда не определен thread_type, START SLAVE UNTIL SQL_BEFORE_GTIDS заставляет ведомый поток SQL обрабатывать транзакции, пока он не достигнет первой транзакции, GTID которой перечислен в gtid_set. START SLAVE UNTIL SQL_AFTER_GTIDS заставляет ведомые потоки обрабатывать все транзакции до последней транзакции в gtid_set. Другими словами, START SLAVE UNTIL SQL_BEFORE_GTIDS заставляет ведомый поток SQL обрабатывать все транзакции, происходящие перед первым GTID в gtid_set, а START SLAVE UNTIL SQL_AFTER_GTIDS заставляет ведомые потоки обрабатывать все транзакции, включая те, GTID которых найдены в gtid_set, пока не столкнутся с транзакцией, GTID которой не часть набора. SQL_BEFORE_GTIDS и SQL_AFTER_GTIDS поддерживают опции SQL_THREAD и IO_THREAD, хотя использование IO_THREAD с ними в настоящее время не имеет никакого эффекта.

Например, START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS = 3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56 заставляет ведомый поток SQL обрабатывать все транзакции, происходящие от ведущего устройства, чей server_uuid 3E11FA47-71CA-11E1-9E33-C80AA9429562, пока это не сталкивается с транзакцией, имеющей порядковый номер 11, это тогда останавливается, не обрабатывая эту транзакцию. Другими словами, все транзакции до и включая транзакцию с порядковым номером 10 обработаны. Выполнение START SLAVE SQL_THREAD UNTIL SQL_AFTER_GTIDS = 3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56 с другой стороны заставил бы ведомый поток SQL получать все транзакции от ведущего устройства, включая все транзакции, имеющие порядковые номера 11-56, а затем останавливаться, не обрабатывая дополнительных транзакций, то есть, транзакция, имеющая порядковый номер 56, была бы последней транзакцией, принесенной ведомым потоком SQL.

Используя мультипоточное ведомое устройство, есть шанс промежутков в последовательности транзакций, которые выполнены от реле. Это следующие случаи:

Используйте START SLAVE UNTIL SQL_AFTER_MTS_GAPS, чтобы заставить потоки мультипоточного ведомого устройства работать только до промежутков в журнале реле, и затем остановиться. Этот запрос может взять опцию SQL_THREAD, но эффект запроса остается неизменным. Это не имеет никакого эффекта на ведомый поток ввода/вывода (и не может использоваться с IO_THREAD).

START SLAVE на мультипоточном ведомом устройстве с промежутками в последовательности транзакций, выполненных от журнала, производит предупреждение. В такой ситуации решение состоит в том, чтобы использовать START SLAVE UNTIL SQL_AFTER_MTS_GAPS, затем RESET SLAVE, чтобы удалить любые остающиеся журналы реле. См. раздел 19.4.1.34.

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

START SLAVE UNTIL SQL_AFTER_MTS_GAPS;
SET @@GLOBAL.slave_parallel_workers = 0;
START SLAVE SQL_THREAD;

Возможно рассмотреть весь текст выполнения START SLAVE ..., включая любые значения USER или PASSWORD, в выводе SHOW PROCESSLIST. Это также верно для текста выполнения CHANGE MASTER TO, включая любые значения MASTER_USER или MASTER_PASSWORD.

START SLAVE посылает признание пользователю после того, как поток ввода/вывода и поток SQL запустились. Однако, поток ввода/вывода еще, возможно, не соединился. Поэтому успешный START SLAVE показывает в SHOW SLAVE STATUS Slave_SQL_Running=Yes, но это не гарантирует, что Slave_IO_Running=Yes (поскольку Slave_IO_Running=Yes только, если поток ввода/вывода работает и соединен). Для получения дополнительной информации см. разделы 14.7.5.34 и 19.1.7.1.

Вы можете добавить опции IO_THREAD и SQL_THREAD, чтобы назвать, который из потоков запустить. Опция SQL_THREAD отвергнута, определяя любой из параметров USER, PASSWORD, DEFAULT_AUTH или PLUGIN_DIR, если опция IO_THREAD задана.

UNTIL (until_option в предыдущей грамматике) может быть добавлен, чтобы определить, что ведомое устройство должно запуститься и работать, пока поток SQL не достигает данной точки в основном двоичном журнале, определенной опциями MASTER_LOG_POS и MASTER_LOG_FILE, или пункта в ведомом журнале реле, обозначенного опциями RELAY_LOG_POS и RELAY_LOG_FILE. Когда поток SQL достигает определенной точки, это останавливается. Если опция SQL_THREAD определена в запросе, она запускает только поток SQL. Иначе, это запускает оба ведомых потока. Если поток SQL работает, UNTIL проигнорирован, и предупреждение выпущено. Вы не можете использовать UNTIL с опцией IO_THREAD.

Также возможно с START SLAVE UNTIL определить остановку относительно данного GTID или набора GTID с использованием одной из опций SQL_BEFORE_GTIDS или SQL_AFTER_GTIDS, как объяснено ранее в этом разделе. Используя одну из этих опций, Вы можете определить SQL_THREAD, IO_THREAD, оба из них, или ни один из них. Если Вы определяете только SQL_THREAD, тогда только ведомый поток SQL затронут запросом, если только IO_THREAD используется, тогда только ведомый поток ввода/вывода затронут. Если используются оба SQL_THREAD и IO_THREAD , или если ни один из них не используется, то потоки SQL и ввода/вывода затронуты запросом.

UNTIL не поддержан для мультипоточных ведомых устройств кроме тех случаев, когда также используется SQL_AFTER_MTS_GAPS.

Для UNTIL Вы должны определить любое из следующего:

Не смешивайте ведущее устройство и опции журнала реле. Не смешивайте опции файла системного журнала с опциями GTID.

Любое условие UNTIL сброшено последующим STOP SLAVE, START SLAVE, который не включает UNTIL, или перезапуском сервера.

Определяя файл системного журнала и позицию, Вы можете использовать IO_THREAD с START SLAVE ... UNTIL даже при том, что только поток SQL затронут этим запросом. Опция IO_THREAD проигнорирована в таких случаях. Предыдущее ограничение не применяется, используя одну из опций GTID (SQL_BEFORE_GTIDS и SQL_AFTER_GTIDS), опции GTID поддерживают обоих SQL_THREAD и IO_THREAD, как объяснено ранее в этом разделе.

UNTIL может быть полезным для того, чтобы отладить репликацию. Например, если неблагоразумный DROP TABLE был выполнен на ведущем устройстве, Вы можете использовать UNTIL, чтобы сказать ведомому устройству выполнять до того пункта, но не дальше. Чтобы найти событие, используйте mysqlbinlog с основным двоичным журналом или ведомым журналом реле, или используйте SHOW BINLOG EVENTS.

Если Вы используете UNTIL, чтобы ведомый процесс копировал запросы в разделах, рекомендуется, чтобы Вы запустили ведомое устройство с опцией --skip-slave-start , чтобы препятствовать тому, чтобы поток SQL работал, когда ведомый сервер запускается. Вероятно, лучше использовать эту опцию в файле опций, а не в командной строке, чтобы неожиданный перезапуск сервера не заставил это забыть.

SHOW SLAVE STATUS включает выходные поля, которые выводят на экран текущее значение UNTIL.

В очень старых версиях MySQL (перед 4.0.5) этот запрос назывался SLAVE START. В MySQL 8.0 этот синтаксис производит ошибку.

14.4.2.7. STOP SLAVE

STOP SLAVE [thread_types]
thread_types:
[thread_type [, thread_type] ... ]
thread_type: IO_THREAD | SQL_THREAD
channel_option:
FOR CHANNEL channel
Останавливает ведомые потоки. STOP SLAVE требует привилегию SUPER. Рекомендуемая практика должна выполнить STOP SLAVE на ведомом устройстве прежде, чем остановить ведомый сервер (см. раздел 6.1.12.

Используя основанный на строке формат журналирования : Вы должны выполнить STOP SLAVE или STOP SLAVE SQL_THREAD на ведомом устройстве до закрытия ведомого сервера, если Вы копируете какие-либо таблицы, которые используют нетранзакционной механизм хранения.

Как START SLAVE, этот запрос может использоваться с IO_THREAD и SQL_THREAD, чтобы назвать поток или потоки, которые будут остановлены.

В MySQL 8.0 STOP SLAVE неявно передает продолжающиеся транзакции. См. раздел 14.3.3.

gtid_next должен быть установлен в AUTOMATIC прежде, чем сделать это запрос.

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

Некоторые запросы CHANGE MASTER TO позволены в то время, как ведомое устройство работает, в зависимости от статуса ведомого SQL и потоков ввода/вывода. Однако, использование STOP SLAVE до выполнения CHANGE MASTER TO в таких случаях все еще поддержано. См. разделы 14.4.2.1 и 19.3.8.

FOR CHANNEL channel позволяет Вам выбрать, к которому каналу относится запрос. Если никакой пункт не установлен, и никакие дополнительные каналы не существуют, запрос относится к каналу по умолчанию и ведет себя как версии MySQL до 5.7. Обеспечение FOR CHANNEL channel применяет STOP SLAVE к определенному каналу. Если STOP SLAVE не определяли канал, используя многократные каналы, этот запрос останавливает указанные потоки для всех каналов. Этот запрос не может использоваться с каналом group_replication_recovery. См. раздел 19.2.3.

Используя основанную на запросе репликацию: изменение ведущего устройства, в то время как у этого есть открытые временные таблицы, потенциально опасно. Это одна из причин, почему основанная на запросе репликация временных таблиц не рекомендуется. Вы можете узнать, есть ли какие-либо временные таблицы на ведомом устройстве, проверяя значение Slave_open_temp_tables, используя основанную на запросе репликацию, это значение должно быть 0 перед выполнением CHANGE MASTER TO. Если есть какие-либо временные таблицы, открытые на ведомом устройстве, CHANGE MASTER TO после STOP SLAVE вызовет предупреждение ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO.

Используя мультипоточное ведомое устройство ( slave_parallel_workers не 0), любые разрывы в последовательности транзакций, выполненных от журнала реле, преодолены как часть остановки рабочего потока. Если ведомое устройство неожиданно остановлено (например из-за ошибки в рабочем потоке) в то время, как STOP SLAVE выполняется, последовательность выполненных транзакций от журнала реле может стать непоследовательной. См. раздел 19.4.1.34.

В MySQL 8.0 STOP SLAVE ждет, пока текущая группа событий, затрагивающая одну или более нетранзакционных таблиц, не закончит выполняться (если есть какая-либо такая группа) или не будет команды KILL QUERY или KILL CONNECTION (Bug #319, Bug #38205).

14.4.3. Запросы SQL для управления группами репликации

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

14.4.3.1. START GROUP_REPLICATION

START GROUP_REPLICATION
Запускает группу репликации.

14.4.3.2. STOP GROUP_REPLICATION

STOP GROUP_REPLICATION
Останваливает группу репликации.

14.5. Подготовленные запросы SQL

MySQL 8.0 оказывает поддержку для подготовленных запросов стороны сервера. Эта поддержка использует эффективный протокол двоичной синхронной передачи данных клиент-сервер. Использование готовые запросы с заполнителями для параметра значения обладает следующими преимуществами:

Готовые запросы в приложениях

Вы можете использовать подготовленные запросы стороны сервера через клиента, программирующего интерфейсы, включая MySQL C API client library или MySQL Connector/C для C-программ, MySQL Connector/J для Java и MySQL Connector/Net для .NET. Например, C API обеспечивает ряд вызовов функций, которые составляют готовый запрос API. См. раздел 25.8.8. Другие языковые интерфейсы могут оказать поддержку для готовых запросов, которые используют протокол двоичной синхронной передачи данных в библиотеке клиента C, один пример, mysqli extension, доступен в PHP 5.0 и выше.

Готовые запросы в скриптах SQL

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

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

PREPARE, EXECUTE и DEALLOCATE PREPARE

Синтаксис SQL для готовых запросов основан на трех запросах SQL:

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

Первый пример показывает, как создать готовый запрос при использовании буквальной строки, чтобы поставлять текст запроса:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2)+POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|  5         |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
Второй пример подобен, но поставляет текст запроса как пользовательскую переменную:
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10         |
+------------+
mysql> DEALLOCATE PREPARE stmt2;
Вот дополнительный пример, который демонстрирует, как выбрать таблицу, на которой можно выполнить запрос во время выполнения, храня название таблицы как пользовательскую переменную:
mysql> USE test;
mysql> CREATE TABLE t1 (a INT NOT NULL);
mysql> INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql> SET @table = 't1';
mysql> SET @s = CONCAT('SELECT * FROM ', @table);
mysql> PREPARE stmt3 FROM @s;
mysql> EXECUTE stmt3;
+----+
| a  |
+----+
|  4 |
|  8 |
| 11 |
| 32 |
| 80 |
+----+
mysql> DEALLOCATE PREPARE stmt3;
Готовый запрос является определенным для сеанса, в котором он создавался. Если Вы заканчиваете сеанс, не освобождая ранее готовый запрос, сервер освобождает это автоматически.

Готовый запрос также глобален для сеанса. Если Вы создаете готовый запрос в пределах сохраненной подпрограммы, это не освобождено, когда сохраненная подпрограмма заканчивается.

Чтобы принять меры против слишком многих готовых запросов, создаваемых одновременно, установите max_prepared_stmt_count. Чтобы предотвратить использование готовых запросов, установите значение в 0.

Синтаксис SQL, позволенный в готовых запросах

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

ALTER TABLE
ALTER USER
ANALYZE TABLE
CACHE INDEX
CALL
CHANGE MASTER
CHECKSUM {TABLE | TABLES}
COMMIT
{CREATE | DROP} INDEX
{CREATE | RENAME | DROP} DATABASE
{CREATE | DROP} TABLE
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
DELETE
DO
FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
  | LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES}
GRANT
INSERT
INSTALL PLUGIN
KILL
LOAD INDEX INTO CACHE
OPTIMIZE TABLE
RENAME TABLE
REPAIR TABLE
REPLACE
RESET {MASTER | SLAVE | QUERY CACHE}
REVOKE
SELECT
SET
SHOW {WARNINGS | ERRORS}
SHOW BINLOG EVENTS
SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
SHOW {MASTER | BINARY} LOGS
SHOW {MASTER | SLAVE} STATUS
SLAVE {START | STOP}
TRUNCATE TABLE
UNINSTALL PLUGIN
UPDATE
Для согласия со стандартом SQL, который заявляет, что запросы диагностики не могут быть предварительно подготовленными, MySQL не поддерживает следующие запросы как подготовленные:

Другие запросы не поддержаны в MySQL 8.0.

Вообще, запросы, не разрешенные в подготовленных запросах SQL, также не разрешены в сохраненных программах. Исключения отмечены в разделе C.1.

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

Заполнители могут использоваться для параметров LIMIT, используя подготовленные запросы. См. раздел 14.2.9 .

В готовом CALL, используемом с PREPARE и EXECUTE, поддержка заполнителя параметров OUT и INOUT доступна, начиная с MySQL 8.0. См. раздел 14.2.1 для примера и обходного решения для более ранних версий. Заполнители могут использоваться для IN независимо от версии.

Синтаксис SQL для готовых запросов не может использоваться вложенным способом. Таким образом, запрос для PREPARE не может самостоятельно быть PREPARE, EXECUTE или DEALLOCATE PREPARE.

Синтаксис SQL для готовых запросов отличен от использования готового вызова API. Например, Вы не можете использовать C API mysql_stmt_prepare(), чтобы подготовить PREPARE, EXECUTE или DEALLOCATE PREPARE.

Синтаксис SQL для готовых запросов может использоваться в пределах хранимых процедур, но не в сохраненных функциях или триггерах. Однако, курсор не может использоваться для динамического запроса, который подготовлен и ыполнен с PREPARE и EXECUTE. Запрос для курсора проверено во время создания курсора, таким образом, запрос не может быть динамическим.

Синтаксис SQL для готовых запросов не поддерживает мультизапросы (то есть, много запросов в пределах единственной строки, отделенных ;).

Готовые запросы используют кэш запроса при условиях, описанных в described in разделе 9.10.3.1.

Чтобы писать программы на C, которые используют CALL, чтобы выполнить хранимые процедуры, которые содержат готовые запросы, флаг CLIENT_MULTI_RESULTS должен быть включен. Это потому, что каждый CALL возвращает результат, чтобы указать на состояние требования, в дополнение к любым наборам результатов, которые могли бы быть возвращены запросами в пределах процедуры.

CLIENT_MULTI_RESULTS может быть включен, когда Вы вызываете mysql_real_connect() , явно, передавая флаг CLIENT_MULTI_RESULTS, или неявно, передавая CLIENT_MULTI_STATEMENTS (который также включает CLIENT_MULTI_RESULTS). См. раздел 14.2.1 .

14.5.1. PREPARE

PREPARE stmt_name FROM preparable_stmt
PREPARE готовит запрос SQL и назначает ему имя stmt_name, которым можно сослаться на запрос позже. Готовый запрос выполнен с EXECUTE и выпущен с DEALLOCATE PREPARE. См. раздел 14.5.

Имена запросов не являются чувствительными к регистру. preparable_stmt буквальная строка или пользовательская переменная, которая содержит текст запроса SQL. Текст должен представить единственный запрос, не многократные запросы. В пределах запроса символы ? могут использоваться в качестве маркеров параметра, чтобы указать, где значения данных должны быть связаны с запросом позже, когда Вы выполняете его. Символы ? не должны быть приложены в пределах кавычек, даже если Вы намереваетесь обязать их представлять значения в виде строки. Маркеры параметра могут использоваться только там, где значения данных должны появиться, не для ключевых слов SQL, идентификаторов и т.д.

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

Контекст готового запроса это сеанс, в пределах которого он создается, это имеет несколько значений:

14.5.2. EXECUTE

EXECUTE stmt_name
[USING @var_name [, @var_name] ...]
После подготовки запроса с PREPARE Вы выполняете это с EXECUTE, который относится к имени готового запроса. Если готовый запрос содержит какие-либо маркеры параметра, Вы должны поставлять USING, который перечисляет пользовательские переменные, содержащие значения, которые будут связаны с параметрами. Значения параметра могут поставляться только пользовательскими переменными, и USING должен назвать точно столько переменных, как число маркеров параметра в запросе.

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

См. раздел 14.5.

14.5.3. DEALLOCATE PREPARE

{DEALLOCATE | DROP} PREPARE stmt_name
Чтобы освободить готовый запрос, произведенный с PREPARE, используйте DEALLOCATE PREPARE, который относится к готовому имени запроса. Попытка выполнить готовый запрос после освобождения приводит к ошибке. Если слишком много готовых запросов создаются и не освобождаются DEALLOCATE PREPARE или концом сеанса, Вы могли бы столкнуться с верхним пределом, проведенным в жизнь max_prepared_stmt_count.

См. раздел 14.5.

14.6. Синтаксис составного запроса

Этот раздел описывает синтаксис для составного запроса BEGIN ... END и другие запросы, которые могут использоваться в теле сохраненных программ: хранимые процедуры и функции, триггеры и события. Эти объекты определены с точки зрения кода SQL, который сохранен на сервере для более позднего неспешного потребления (см. главу 21).

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

14.6.1. BEGIN ... END

[begin_label:] BEGIN
[statement_list]
END [end_label]
BEGIN ... END используется для того, чтобы написать составные запросы, которые могут появиться в пределах сохраненных программ (хранимые процедуры и функции, триггеры и события). Составной запрос может содержать многократные запросы в BEGIN и END. statement_list представляет список из одного или более запросов, каждый закончен точкой с запятой (;). statement_list непосредственно является дополнительным, таким образом, пустой составной запрос (BEGIN END) допустим.

BEGIN ... END могут быть вложены.

Использование многократных запросов требует, чтобы клиент был в состоянии послать строки запроса, содержащие разделитель ;. В mysql это обработано командой delimiter. Изменение разделителя конца запроса ; (например, на //) позволяет ; использоваться в теле программы. Для примера см. раздел 21.1.

Блок BEGIN ... END может быть маркирован. См. раздел 14.6.2 .

[NOT] ATOMIC не поддержан. Это означает, что никакая транзакционная точка восстановления не установлена в начале блока инструкций, и BEGIN, используемый в этом контексте, не имеет никакого эффекта на текущую транзакцию.

В пределах всех сохраненных программ анализатор обрабатывает BEGIN [WORK] как начало BEGIN ... END. Чтобы начать транзакцию в этом контексте, надо использовать START TRANSACTION.

14.6.2. Метки запросов

[begin_label:] BEGIN
[statement_list]
END [end_label]

[begin_label:] LOOP
statement_list
END LOOP [end_label]

[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]

[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
Для меток разрешают BEGIN ... END блоки, а также команды LOOP, REPEAT и WHILE. Использование метки для тех запросов следует этим правилам:

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

CREATE PROCEDURE doiterate(p1 INT)
BEGIN
  label1: LOOP
SET p1 = p1 + 1;
IF p1 < 10 THEN ITERATE label1; END IF;
LEAVE label1;
  END LOOP label1;
END;
Контекст метки блока не включает код для обработчиков, объявленных в пределах блока. Для деталей см. раздел 14.6.7.2.

14.6.3. DECLARE

DECLARE используется, чтобы определить различные элементы, местные для программы:

DECLARE разрешен только внутри BEGIN ... END и должен быть в его начале перед любыми другими запросыми.

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

14.6.4. Переменные в сохраненных программах

Системные переменные и определяемые пользователем переменные могут использоваться в сохраненных программах, как они могут использоваться вне контекста сохраненной программы. Кроме того, сохраненные программы могут использовать DECLARE, чтобы определить местные переменные, а сохраненные подпрограммы (процедуры и функции) могут объявлять параметры, которые сообщают значения между подпрограммой и ее вызывающим.

См. раздел 14.6.4.2.

Не разрешено назначить значение DEFAULT местным переменным в хранимой процедуре или функциональным параметрам (например, с SET var_name = DEFAULT). В MySQL 8.0 это приводит к синтаксической ошибке.

14.6.4.1. Местная переменная DECLARE

DECLARE var_name [, var_name] ...
type [DEFAULT value]
Этот запрос объявляет местные переменные в пределах сохраненных программ. Чтобы обеспечить значение по умолчанию для переменной, включайте DEFAULT. Значение может быть определено как выражение, это не должна быть константа. Если DEFAULT нет, начальное значение NULL.

Местные переменные обработаны как сохраненные обычные параметры относительно проверки переполнения и типа данных. См. раздел 14.1.13.

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

Местные имена переменной не являются чувствительными к регистру. Допустимые символы и правила заключения в кавычки те же самое, что касаются других идентификаторов, как описано в разделе 10.2.

Контекст местной переменной это блок BEGIN ... END в пределах которого это объявлено. Переменная может быть упомянута в блоках, вложенных в пределах блока объявления, кроме тех блоков, которые объявляют переменную с тем же самым именем.

См. раздел 14.6.4.2.

14.6.4.2. Местный контекст и разрешение переменных

Контекст местной переменной это блок BEGIN ... END в пределах которого это объявлено. Переменная может быть упомянута в блоках, вложенных в пределах блока объявления, кроме тех блоков, которые объявляют переменную с тем же самым именем.

Поскольку местные переменные находятся в контексте только во время выполнения сохраненной программы, ссылки на них не разрешены в готовых запросах, создаваемых в пределах сохраненной программы. Контекст готового запроса это текущий сеанс, а не сохраненная программа, таким образом, запрос может быть выполнен после конца программы, а тогда переменные больше не будут в контексте. Например, SELECT ... INTO local_var не может использоваться в качестве готового запроса. Это ограничение также относится к хранимой процедуре и функциональным параметрам. См. раздел 14.5.1.

У местной переменной не должно быть того же самого имени как у столбца таблицы. Если запрос SQL, например, SELECT ... INTO, содержит ссылку на столбец и заявленную местную переменную с тем же самым именем, MySQL в настоящее время интерпретирует ссылку как название переменной. Рассмотрите следующее определение процедуры:

CREATE PROCEDURE sp1 (x VARCHAR(5))
BEGIN
  DECLARE xname VARCHAR(5) DEFAULT 'bob';
  DECLARE newname VARCHAR(5);
  DECLARE xid INT;
  SELECT xname, id INTO newname, xid FROM table1 WHERE xname = xname;
  SELECT newname;
END;
MySQL понимает xname в SELECT как ссылку на переменную xname, а не на столбец xname. Следовательно, когда процедура sp1() вызвана, переменная newname возвращает значение 'bob' независимо от значения table1.xname.

Точно так же определение курсора в следующей процедуре содержит SELECT, который относится к xname. MySQL интерпретирует это как ссылку на переменную, а не на столбец.

CREATE PROCEDURE sp2 (x VARCHAR(5))
BEGIN
  DECLARE xname VARCHAR(5) DEFAULT 'bob';
  DECLARE newname VARCHAR(5);
  DECLARE xid INT;
  DECLARE done TINYINT DEFAULT 0;
  DECLARE cur1 CURSOR FOR SELECT xname, id FROM table1;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  OPEN cur1;
  read_loop: LOOP
    FETCH FROM cur1 INTO newname, xid;
    IF done THEN
       LEAVE read_loop;
    END IF;
    SELECT newname;
  END LOOP;
  CLOSE cur1;
END;
См. раздел C.1.

14.6.5. Запросы управления потоками

MySQL поддерживает конструкции IF, CASE, ITERATE, LEAVE LOOP, WHILE и REPEAT для управления потоками в пределах сохраненных программ. Это также поддерживает RETURN в пределах сохраненных функций.

Многие из этих конструкций содержат другие запросы, как обозначено техническими требованиями грамматики в следующих разделах. Такие конструкции могут быть вложены. Например, IF мог бы содержать WHILE, который непосредственно содержит CASE.

MySQL не поддерживает циклы FOR.

14.6.5.1. CASE

CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
Или:
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
CASE для сохраненных программ осуществляет сложную условную конструкцию.

Есть также CASE expression, который отличается от CASE statement, описанного здесь. См. раздел 13.4 . CASE не может иметь ELSE NULL и это закончено с END CASE вместо END.

Для первого синтаксиса case_value является выражением. Это значение сравнивается с when_value в каждом WHEN до равенства одному из них. Когда равное when_value найдено, соответствующий THEN statement_list выполнен. Если нет равного when_value, выполнен ELSE statement_list, если есть. Если его нет, то не выполнено ничего.

Этот синтаксис не может использоваться, чтобы проверить на равенство с NULL, так как NULL = NULL будет false. См. раздел 4.3.4.6.

Для второго синтаксиса каждый WHEN search_condition оценено, пока не истина, в какой THEN statement_list передать выполнение. Если нет равного when_value, выполнен ELSE statement_list, если есть. Если его нет, то не выполнено ничего.

Если нет when_value или search_condition, которое соответствует проверенному значению, и CASE не содержит ELSE, будет ошибка Case not found for CASE statement.

Каждый statement_list состоит из одного или более запросов SQL, пустой statement_list запрещен.

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

DELIMITER |

CREATE PROCEDURE p()
BEGIN
  DECLARE v INT DEFAULT 1;

  CASE v
    WHEN 2 THEN SELECT v;
    WHEN 3 THEN SELECT 0;
    ELSE BEGIN
    END;
  END CASE;
END;
|

14.6.5.2. IF

IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
IF для сохраненных программ осуществляет основную условную конструкцию.

Есть также функция IF(), которая отличается от запроса IF. См. раздел 13.4. Запрос IF может иметь THEN, ELSE и ELSEIF, и это закончено с END IF.

Если search_condition true, соответствующий THEN или ELSEIF statement_list выполняется. Если нет подходящего search_condition, выполнен ELSE statement_list.

Каждый statement_list состоит из одного или более запросов SQL: пустой statement_list запрещен.

IF ... END IF, как все другие блоки управления потоками, используемые в пределах сохраненных программ, должен быть закончен точкой с запятой, как показано в этом примере:

DELIMITER //

CREATE FUNCTION SimpleCompare(n INT, m INT)
  RETURNS VARCHAR(20)
  BEGIN
    DECLARE s VARCHAR(20);
    IF n > m THEN SET s = '>';
       ELSEIF n = m THEN SET s = '=';
       ELSE SET s = '<';
    END IF;
    SET s = CONCAT(n, ' ', s, ' ', m);
    RETURN s;
  END //

DELIMITER ;
Как с другими конструкциями управления потоками, блоки IF ... END IF могут быть вложены в пределах других конструкций управления потоками, включая другой запрос IF. Каждый IF должен быть закончен его собственным END IF и точкой с запятой. Вы можете использовать углубление, чтобы сделать вложенные блоки управления потоками более легко читаемыми людьми (хотя это не требуется MySQL), как показано здесь:
DELIMITER //

CREATE FUNCTION VerboseCompare (n INT, m INT)
  RETURNS VARCHAR(50)
  BEGIN
    DECLARE s VARCHAR(50);
    IF n = m THEN SET s = 'equals';
    ELSE
      IF n > m THEN SET s = 'greater';
      ELSE SET s = 'less';
      END IF;
      SET s = CONCAT('is ', s, ' than');
    END IF;
    SET s = CONCAT(n, ' ', s, ' ', m, '.');
  RETURN s;
  END //

DELIMITER ;
В этом примере внутренний IF оценен только, если n не равно m.

14.6.5.3. ITERATE

ITERATE label
ITERATE может появиться только в пределах LOOP, REPEAT и WHILE. ITERATE значит запустить повтор цикла.

См. раздел 14.6.5.5.

14.6.5.4. LEAVE

LEAVE label
Этот запрос используется, чтобы выйти из конструкции управления потоками, у которой есть данная метка. Если метка для наиболее удаленного сохраненного блока программы, LEAVE выходит из программы.

LEAVE может использоваться в пределах BEGIN ... END или конструкции цикла (LOOP, REPEAT, WHILE).

См. раздел 14.6.5.5.

14.6.5.5. LOOP

[begin_label:] LOOP
statement_list
END LOOP [end_label]
LOOP осуществляет простую конструкцию цикла, включая повторное выполнение списка запросов, который состоит из одного или более запросов, каждый завершенный точкой с запятой (;). Ззапросы повторены, пока цикл не закончен. Обычно это достигнуто с помощью LEAVE . В пределах сохраненной функции RETURN может также использоваться, чтобы выйти из функции полностью.

Если не включать запрос завершения цикла, цикл станет бесконечным.

LOOP может быть маркирован. Для правил относительно использования меток см. раздел 14.6.2.

Пример:

CREATE PROCEDURE doiterate(p1 INT)
BEGIN
  label1: LOOP
    SET p1 = p1 + 1;
    IF p1 < 10 THEN ITERATE label1;
    END IF;
    LEAVE label1;
  END LOOP label1;
  SET @x = p1;
END;

14.6.5.6. REPEAT

[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
Список запросов в пределах REPEAT повторено, пока выражение search_condition не станет истиной. Таким образом, REPEAT всегда вводит цикл, по крайней мере, однажды. statement_list состоит из одного или более запросов, каждый закрыт точкой с запятой (;).

REPEAT может быть маркирован. Для правил относительно использования меток см. раздел 14.6.2.

Пример:

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)
    -> BEGIN
    ->   SET @x = 0;
    ->   REPEAT
    -> SET @x = @x + 1;
    ->   UNTIL @x > p1 END REPEAT;
    -> END
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> CALL dorepeat(1000)//
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x//
+------+
| @x   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)

14.6.5.7. RETURN

RETURN expr
RETURN заканчивает выполнение сохраненной функции и возвращает значение expr вызвавшему. Должен быть по крайней мере один RETURN в сохраненной функции. Может быть больше, чем один, если у функции есть много пунктов выхода.

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

14.6.5.8. WHILE

[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
Список запросов в пределах WHILE повторен, пока search_condition true. statement_list состоит из одного или более запросов SQL, каждый закончен точкой с запятой (;).

WHILE может быть маркирован. Для правил относительно использования меток см. раздел 14.6.2.

Пример:

CREATE PROCEDURE dowhile()
BEGIN
  DECLARE v1 INT DEFAULT 5;
  WHILE v1 > 0 DO
    ...
    SET v1 = v1 - 1;
  END WHILE;
END;

14.6.6. Курсоры

MySQL поддерживает курсоры в сохраненных программах. Синтаксис как во встроенном SQL. У курсоров есть эти свойства:

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

Пример:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  OPEN cur1;
  OPEN cur2;
  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN LEAVE read_loop;
    END IF;
    IF b < c THEN
       INSERT INTO test.t3 VALUES (a,b);
       ELSE INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;
  CLOSE cur1;
  CLOSE cur2;
END;

14.6.6.1. Курсор CLOSE

CLOSE cursor_name
Закрывает ранее открытый курсор. Для примера см. раздел 14.6.6.

Ошибка происходит, если курсор не открыт.

Если не закрыт явно, курсор закрыт в конце блока BEGIN ... END, в котором это было объявлено.

14.6.6.2. Курсор DECLARE

DECLARE cursor_name CURSOR FOR select_statement
Этот запрос объявляет курсор и связывает с SELECT, который получает строки, которые будут пересечены курсором. Чтобы принести строки позже, используйте FETCH. Число столбцов, полученных SELECT, должно соответствовать числу выходных переменных, определенных в FETCH.

SELECT не может иметь INTO.

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

Сохраненная программа может содержать многократные декларации курсора, но у каждого курсора, объявленного в данном блоке, должно быть уникальное имя. Для примера см. раздел 14.6.6.

Для информации, доступной через SHOW, возможно во многих случаях получить эквивалентную информацию при использовании курсора с таблицей INFORMATION_SCHEMA.

14.6.6.3. Курсор FETCH

FETCH [[NEXT] FROM] cursor_name INTO
var_name [, var_name] ...
Этоn запрос приносит следующую строку для SELECT, связанным с указанным курсором (который должен быть открыт) и обновляет указатель курсора. Если строка существует, принесенные столбцы сохранены в названных переменных. Число столбцов, полученных SELECT, должно соответствовать числу выходных переменных, определенных в FETCH.

Если больше строк не доступно, происходит состояние No Data condition с SQLSTATE value '02000'. Чтобы обнаружить это условие, Вы можете настроить обработчик для этого (или для условия NOT FOUND ). См. раздел 14.6.6.

Знайте, что другая работа, такая как SELECT или другой FETCH, может также заставить обработчик выполняться, поднимая то же самое условие. Если необходимо различить, какая работа подняла условие, поместите работу в пределах его собственного блока BEGIN ... END, чтобы это могло быть связано с собственным обработчиком.

14.6.6.4. Курсор OPEN

OPEN cursor_name
Этот запрос открывает ранее заявленный курсор. Для примера см. раздел 14.6.6.

14.6.7. Обработка условия

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

Чтобы назвать условие, используйте DECLARE ... CONDITION. Чтобы объявить обработчик, используйте DECLARE ... HANDLER. См. разделы 14.6.7.1 и раздел 14.6.7.2.

Чтобы поднять условие, используйте SIGNAL. Чтобы изменить информацию об условии в пределах обработчика условия, надо использовать RESIGNAL. См. разделы 14.6.7.1 и 14.6.7.2.

Чтобы получить информацию из области диагностики, используйте GET DIAGNOSTICS (см. раздел 14.6.7.3). Для информации об области диагностики см. раздел 14.6.7.7.

14.6.7.1. DECLARE ... CONDITION

DECLARE condition_name CONDITION FOR condition_value
condition_value:
mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
DECLARE ... CONDITION объявляет названное состояние ошибки, связывая имя с условием, которое нуждается в определенной обработке. Имя может быть упомянуто в последующем DECLARE ... HANDLER (см. раздел 14.6.7.2).

Декларации условия должны появиться перед декларациями обработчика или курсором.

condition_value для DECLARE ... CONDITION указывает на особое условие или класс условий, связанный с именем условия. Это может принять следующие формы:

Имена условия, упомянутые в SIGNAL или RESIGNAL, должны быть связаны со значениями SQLSTATE, а не кодами ошибки MySQL.

Использование названия условий может помочь сделать код программы более ясным. Например, этот обработчик относится к попыткам удалить несуществующую таблицу, но это очевидно, только если Вы знаете, что 1051 это код ошибки MySQL для unknown table:

DECLARE CONTINUE HANDLER FOR 1051
  BEGIN
-- body of handler
  END;
Объявляя название условия, цель обработчика замечена с большей точностью:
DECLARE no_such_table CONDITION FOR 1051;
DECLARE CONTINUE HANDLER FOR no_such_table
  BEGIN
-- body of handler
  END;
Вот названное условие для того же самого условия, но основанное на соответствующем значении SQLSTATE, а не коде ошибки MySQL:
DECLARE no_such_table CONDITION FOR SQLSTATE '42S02';
DECLARE CONTINUE HANDLER FOR no_such_table
  BEGIN
-- body of handler
  END;

14.6.7.2. DECLARE ... HANDLER

DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement

handler_action:
CONTINUE
  | EXIT
  | UNDO

condition_value:
mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
DECLARE ... HANDLER определяет обработчик, который имеет дело с одним или более условиями. Если одно из этих условий происходит, указанный statement выполнится. statement может быть простым запросом таким, как SET var_name = value, или составным запросом из BEGIN и END (см. раздел 14.6.1).

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

handler_action указывает на то, что обработчик предпринимает после выполнения запроса обработчика:

condition_value для DECLARE ... HANDLER указывает на особое условие или класс условий, который активирует обработчик. Это может принять следующие формы:

См. раздел 14.6.7.6.

Если условие происходит, для которого не был объявлен обработчик, предпринятые меры зависят от класса условия:

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

mysql> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter //
mysql> CREATE PROCEDURE handlerdemo ()
    -> BEGIN
    ->   DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
    ->   SET @x = 1;
    ->   INSERT INTO test.t VALUES (1);
    ->   SET @x = 2;
    ->   INSERT INTO test.t VALUES (1);
    ->   SET @x = 3;
    -> END;
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> CALL handlerdemo()//
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x//
+----+
| @x |
+----+
| 3  |
+----+
1 row in set (0.00 sec)
Заметьте, что @x = 3 после того, как процедура выполняется, что показывает, что выполнение продолжалось до конца процедуры после ошибки. Если DECLARE ... HANDLER не присутствовало, MySQL предпримет меры по умолчанию (EXIT) после второго INSERT неудавшегося из-за PRIMARY KEY и SELECT @x возвратил бы 2.

Чтобы проигнорировать условие, объявите обработчик CONTINUE для этого и свяжите его с пустым блоком. Например:

DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
Контекст метки блока не включает код для обработчиков, объявленных в пределах блока. Поэтому, запрос, связанный с обработчиком, не может использовать ITERATE или LEAVE, чтобы обратиться к меткам для блоков, которые прилагают декларацию обработчика. Рассмотрите следующий пример, где у блока REPEAT есть метка retry:
CREATE PROCEDURE p ()
BEGIN
  DECLARE i INT DEFAULT 3;
retry:
  REPEAT BEGIN
    DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN
      ITERATE retry;    # illegal
    END;
    IF i < 0 THEN
       LEAVE retry;# legal
    END IF;
    SET i = i - 1;
  END;
  UNTIL FALSE END REPEAT;
END;
Метка retry находится в контексте IF в пределах блока. Это не находится в контексте для обработчика CONTINUE , таким образом, ссылка там недопустима и приводит к ошибке:
ERROR 1308 (42000): LEAVE with no matching label: retry
Чтобы избежать ссылок на внешние метки в обработчиках, используйте одну из этих стратегий:

14.6.7.3. GET DIAGNOSTICS

GET [CURRENT | STACKED] DIAGNOSTICS
{
statement_information_item
[, statement_information_item] ...
  | CONDITION condition_number
condition_information_item
[, condition_information_item] ...
}

statement_information_item:
target = statement_information_item_name
condition_information_item:
target = condition_information_item_name

statement_information_item_name:
NUMBER
  | ROW_COUNT

condition_information_item_name:
CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | RETURNED_SQLSTATE
  | MESSAGE_TEXT
  | MYSQL_ERRNO
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME

condition_number, target:
(see following discussion)
Запросы SQL производят диагностическую информацию, которая заполняет область диагностики. GET DIAGNOSTICS позволяет приложениям смотреть эту информацию. Вы можете также использовать SHOW WARNINGS или SHOW ERRORS, чтобы видеть условия или ошибки.

Никакие специальные привилегии не нужны для GET DIAGNOSTICS.

CURRENT позволяет получить информацию из текущей области диагностики. Ключевое слово STACKED позволяет получить информацию из второй области диагностики, которая доступна, только если текущий контекст это обработчик условия. Если никакое ключевое слово не дано, значение по умолчанию должно использовать текущую область диагностики.

GET DIAGNOSTICS, как правило, используется в обработчике в пределах сохраненной программы. Это расширение MySQL, для GET [CURRENT] DIAGNOSTICS разрешен внешний контекст обработчика, чтобы проверить выполнение любого запроса SQL. Например, если Вы вызываете mysql, Вы можете ввести эти запросы:

mysql> DROP TABLE test.no_such_table;
ERROR 1051 (42S02): Unknown table 'test.no_such_table'
mysql> GET DIAGNOSTICS CONDITION 1
    ->     @p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;
mysql> SELECT @p1, @p2;
+-------+------------------------------------+
| @p1   | @p2                                |
+-------+------------------------------------+
| 42S02 | Unknown table 'test.no_such_table' |
+-------+------------------------------------+
Это расширение применяется только к текущей области диагностики. Это не относится к второй области диагностики потому, что GET STACKED DIAGNOSTICS разрешен, только если текущий контекст обработчик условия. Если это не так, происходит ошибка GET STACKED DIAGNOSTICS when handler not active.

См. раздел 14.6.7.7. Кратко, это содержит два вида информации:

Для запроса, который производит три условия, область диагностики содержит запрос и информацию об условии:

Statement information:
  row count
  ... other statement information items ...
Condition area list:
  Condition area 1:
error code for condition 1
error message for condition 1
... other condition information items ...
  Condition area 2:
error code for condition 2:
error message for condition 2
... other condition information items ...
  Condition area 3:
error code for condition 3
error message for condition 3
... other condition information items ...
GET DIAGNOSTICS может получить запрос или информацию об условии, но не обоих в том же самом запросе:

Список извлечения определяет один или больше target = item_name, отделенных запятыми. Каждое назначение называет целевую переменную и любой указатель statement_information_item_name или condition_information_item_name, в зависимости от того, получает ли запрос информацию об условии или запрос.

Допустимые указатели target для того, чтобы хранить информацию элемента могут быть хранимой процедурой или функциональными параметрами, местными переменными, объявленными с DECLARE, или определяемыми пользователем переменными.

Допустимые указатели condition_number могут быть хранимой процедурой или функциональными параметрами, местными перемеными, объявленными с DECLARE , определяемыми пользователем переменными, системными переменными или литералами. Символьный литерал может включать _charset. Предупреждение происходит, если номер условия не находится в диапазоне от 1 до числа областей условия, у которых есть информация. В этом случае предупреждение добавлено к области диагностики, не очищая ее.

Когда условие происходит, MySQL не заполняет все элементы условия, признанные GET DIAGNOSTICS:

mysql> GET DIAGNOSTICS CONDITION 1
    ->     @p5 = SCHEMA_NAME, @p6 = TABLE_NAME;
mysql> SELECT @p5, @p6;
+-----+-----+
| @p5 | @p6 |
+-----+-----+
|     |     |
+-----+-----+
В стандартном SQL, если есть многократные условия, первое условие касается SQLSTATE для предыдущего запроса SQL. В MySQL это не гарантируется. Чтобы получить основную ошибку, Вы не можете сделать этого:
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;
Вместо этого получите количество условий сначала, затем используйте это, чтобы определить, которое условие смотреть:
GET DIAGNOSTICS @cno = NUMBER;
GET DIAGNOSTICS CONDITION @cno @errno = MYSQL_ERRNO;
См. раздел 14.6.7.7.2 .

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

CREATE PROCEDURE do_insert(value INT)
BEGIN
  -- Declare variables to hold diagnostics area information
  DECLARE code CHAR(5) DEFAULT '00000';
  DECLARE msg TEXT;
  DECLARE rows INT;
  DECLARE result TEXT;
  -- Declare exception handler for failed insert
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
  GET DIAGNOSTICS CONDITION 1
  code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
END;
  -- Perform the insert
  INSERT INTO t1 (int_col) VALUES(value);
  -- Check whether the insert was successful
  IF code = '00000' THEN
     GET DIAGNOSTICS rows = ROW_COUNT;
     SET result = CONCAT('insert succeeded, row count = ',rows);
  ELSE
    SET result = CONCAT('insert failed, error = ',code,', message = ',msg);
  END IF;
  -- Say what happened
  SELECT result;
END;
Предположите, что t1.int_col столбец целого числа, который объявлен как NOT NULL. Процедура приводит к этим результатам когда вызвана, чтобы вставить значения не-NULL и NULL, соответственно:
mysql> CALL do_insert(1);
+---------------------------------+
| result                          |
+---------------------------------+
| insert succeeded, row count = 1 |
+---------------------------------+

mysql> CALL do_insert(NULL);
+-------------------------------------------------------------------------+
| result                                                                  |
+-------------------------------------------------------------------------+
| insert failed, error = 23000, message = Column 'int_col' cannot be null |
+-------------------------------------------------------------------------+
Когда обработчик условия активируется, обращение к стеку области диагностики происходит:

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

В пределах хранимой процедуры p() мы пытаемся вставить два значения в таблицу, которая содержит столбец TEXT NOT NULL. Первое значение не-NULL строка, второе NULL. Столбец запрещает NULL, таким образом, первая вставка преуспевает, но вторая дает исключение. Процедура включает обработчик исключения, который отображает попытки вставить NULL:

DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 TEXT NOT NULL);
DROP PROCEDURE IF EXISTS p;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  -- Declare variables to hold diagnostics area information
  DECLARE errcount INT;
  DECLARE errno INT;
  DECLARE msg TEXT;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
  -- Here the current DA is nonempty because no prior statements
  -- executing within the handler have cleared it
    GET CURRENT DIAGNOSTICS CONDITION 1
    errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'current DA before mapped insert' AS op, errno, msg;
    GET STACKED DIAGNOSTICS CONDITION 1
    errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA before mapped insert' AS op, errno, msg;
    -- Map attempted NULL insert to empty string insert
    INSERT INTO t1 (c1) VALUES('');
    -- Here the current DA should be empty (if the INSERT succeeded),
    -- so check whether there are conditions before attempting to
    -- obtain condition information
    GET CURRENT DIAGNOSTICS errcount = NUMBER;
    IF errcount = 0 THEN
       SELECT 'mapped insert succeeded, current DA is empty' AS op;
    ELSE
      GET CURRENT DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
      SELECT 'current DA after mapped insert' AS op, errno, msg;
    END IF;
    GET STACKED DIAGNOSTICS CONDITION 1
    errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA after mapped insert' AS op, errno, msg;
  END;
  INSERT INTO t1 (c1) VALUES('string 1');
  INSERT INTO t1 (c1) VALUES(NULL);
END;
//
delimiter ;
CALL p();
SELECT * FROM t1;
Когда обработчик активируется, копия текущей области диагностики продвинута к стеку области диагностики. Обработчик показывает содержание текущей и стековой областей диагностики, которые являются тем же самым первоначально:
+---------------------------------+-------+----------------------------+
| op                              | errno | msg                        |
+---------------------------------+-------+----------------------------+
| current DA before mapped insert |  1048 | Column 'c1' cannot be null |
+---------------------------------+-------+----------------------------+

+---------------------------------+-------+----------------------------+
| op                              | errno | msg                        |
+---------------------------------+-------+----------------------------+
| stacked DA before mapped insert |  1048 | Column 'c1' cannot be null |
+---------------------------------+-------+----------------------------+
Запросы, выполняющиеся после GET DIAGNOSTICS, могут сбросить текущую область диагностики. Например, обработчик отображает вставку NULL к пустой строке, вставляет и выводит на экран результат. Новая вставка следует и очищает текущую область диагностики, но стековая область диагностики остается неизменной и все еще содержит информацию об условии, которое активировало обработчик:
+----------------------------------------------+
| op                                           |
+----------------------------------------------+
| mapped insert succeeded, current DA is empty |
+----------------------------------------------+

+--------------------------------+-------+----------------------------+
| op                             | errno | msg                        |
+--------------------------------+-------+----------------------------+
| stacked DA after mapped insert |  1048 | Column 'c1' cannot be null |
+--------------------------------+-------+----------------------------+
Когда обработчик условия заканчивается, его текущая область диагностики убрана из стека, и стековая область диагностики становится текущей областью диагностики в хранимой процедуре.

После возвращений процедуры таблица содержит две строки. Пустая строка следует из попытки вставить NULL, что было отображено на пустую строку:

+----------+
| c1       |
+----------+
| string 1 |
|          |
+----------+
В предыдущем примере первые два GET DIAGNOSTICS в пределах обработчика условия получают информацию из текущей и стековой областей диагностики и возвращают те же самые значения. Это не будет иметь место, если выполняются запросы, которые сбрасывают текущую область диагностики ранее в пределах обработчика. Предположите, что p() переписана, чтобы поместить DECLARE в пределах определения обработчика вместо того, чтобы предшествовать этому:
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    -- Declare variables to hold diagnostics area information
    DECLARE errcount INT;
    DECLARE errno INT;
    DECLARE msg TEXT;
    GET CURRENT DIAGNOSTICS CONDITION 1
    errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'current DA before mapped insert' AS op, errno, msg;
    GET STACKED DIAGNOSTICS CONDITION 1
    errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA before mapped insert' AS op, errno, msg;
    ...
В этом случае результат зависит от версии:

Чтобы избегать этой проблемы в пределах обработчика условия, стремясь получить информацию об условии, которое активировало обработчик, убедитесь, что получили доступ к стековой области диагностики, а не текущей области диагностики.

14.6.7.4. RESIGNAL

RESIGNAL [condition_value]
[SET signal_information_item
[, signal_information_item] ...]

condition_value:
SQLSTATE [VALUE] sqlstate_value
  | condition_name

signal_information_item:
condition_information_item_name = simple_value_specification

condition_information_item_name:
CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | MESSAGE_TEXT
  | MYSQL_ERRNO
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME

condition_name, simple_value_specification:
(see following discussion)
RESIGNAL передает информацию о состоянии ошибки, которая доступна во время выполнения обработчика условия в пределах составного запроса в хранимой процедуре или функции, триггере или событии. RESIGNAL может изменить некоторую или всю информацию перед передачей этого. RESIGNAL связан с SIGNAL, но вместо того, чтобы породить условие как SIGNAL, RESIGNAL передает существующую информацию об условии, возможно после изменения этого.

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

Никакие специальные привилегии не требуются для RESIGNAL.

Все формы RESIGNAL требуют, чтобы текущий контекст был обработчиком условия. Иначе RESIGNAL будет ошибка RESIGNAL when handler not active.

См. разделы 14.6.7.3 и 14.6.7.7.

Для condition_value и signal_information_item определения и правила как для RESIGNAL и SIGNAL. Например, condition_value может быть SQLSTATE, значение могут указать на ошибки, предупреждения или not found . См. раздел 14.6.7.5.

RESIGNAL берет condition_value и SET, оба являются дополнительными. Это приводит к нескольким возможным применениям:

Эти случаи использования изменяют области условия и диагностики:

Есть стек областей диагностики. Когда обработчик берет на себя управление, он продвигает область диагностики к вершине стека, таким образом во время выполнения обработчика есть две области диагностики:

Максимальное количество областей условия в области диагностики определено значением max_error_count . См. раздел 14.6.7.7.5.

14.6.7.4.1. RESIGNAL

Простой RESIGNAL означает, что передает ошибку без изменений. Это восстанавливает последнюю область диагностики и делает это текущей областью диагностики. Таким образом, это помещает области диагностики в стек.

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

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN
       RESIGNAL;
    END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
CALL p();
Предположите, что запрос DROP TABLE xx терпит неудачу. Стек области диагностики похож на это:
DA 1. ERROR 1051 (42S02): Unknown table 'xx'
Тогда выполнение вызывает обработчик EXIT. Это запускается, продвигая область диагностики к вершине стека, который теперь похож на это:
DA 1. ERROR 1051 (42S02): Unknown table 'xx'
DA 2. ERROR 1051 (42S02): Unknown table 'xx'
В этом пункте содержание первых (текущих) и вторых областей диагностики то же самое. Первая область диагностики может быть изменена запросами, выполняющимися впоследствии в пределах обработчика.

Обычно запрос процедуры очищает первую область диагностики. BEGIN исключение, это не очищает, это ничего не делает. SET не исключение, это очищает, выполняет работу и приводит к результату success. Стек области диагностики теперь похож на это:

DA 1. ERROR 0000 (00000): Successful operation
DA 2. ERROR 1051 (42S02): Unknown table 'xx'
В этом пункте, если @a = 0, RESIGNAL помещает область диагностики в стек, который теперь похож на это:
DA 1. ERROR 1051 (42S02): Unknown table 'xx'
И именно это видит вызывающий.

Если @a не 0, обработчик просто заканчивается, что означает, что нет больше использования для текущей области диагностики (все обработано). Таким образом, это может быть выброшено, заставляя стековую область диагностики стать текущей областью диагностики снова. Стек области диагностики похож на это:

DA 1. ERROR 0000 (00000): Successful operation
Детали заставляют это выглядеть сложным, но конечный результат довольно полезен: обработчики могут выполниться, не разрушая информацию об условии, которое вызвало активацию обработчика.

14.6.7.4.2. RESIGNAL с новой информацией о сигнале

RESIGNAL с SET предоставляет новую информацию о сигнале, таким образом, запрос означает, что ошибку передают с изменениями:

RESIGNAL SET signal_information_item
         [, signal_information_item] ...;
Как с RESIGNAL идея состоит в том, чтобы вытолкать стек области диагностики так, чтобы оригинальная информация была снаружи. В отличие от простого RESIGNAL, что-либо определенное в SET вносит изменения.

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN
       RESIGNAL SET MYSQL_ERRNO = 5;
    END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
CALL p();
Помните из предыдущего обсуждения, что RESIGNAL результаты в области диагностики складывает как это:
DA 1. ERROR 1051 (42S02): Unknown table 'xx'
RESIGNAL SET MYSQL_ERRNO = 5 приводит к этому стеку:
DA 1. ERROR 5 (42S02): Unknown table 'xx'
Другими словами, это изменяет код ошибки и ничто иное.

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

14.6.7.4.3. RESIGNAL со значением условия и дополнительной новой информацией о сигнале

RESIGNAL с условием означает, что условие продвигают в текущую область диагностики . Если есть SET, он также изменяет информацию об ошибке.

RESIGNAL condition_value
         [SET signal_information_item
         [, signal_information_item] ...];
Эта форма RESIGNAL восстанавливает последнюю область диагностики и делает это текущей областью диагностики. Таким образом, это поднимает стек области диагностики, который является тем же самым, как в простом RESIGNAL. Однако, это также изменяет область диагностики в зависимости от значения условия или информации о сигнале.

Пример:

DROP TABLE IF EXISTS xx;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SET @error_count = @error_count + 1;
    IF @a = 0 THEN
       RESIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=5;
    END IF;
  END;
  DROP TABLE xx;
END//
delimiter ;
SET @error_count = 0;
SET @a = 0;
SET @@max_error_count = 2;
CALL p();
SHOW ERRORS;
Это подобно предыдущему примеру и эффекты те же самые, за исключением того, что если RESIGNAL происходит, область текущего положения выглядит по-другому в конце. Причина: условие добавляется, а не заменяет существующее значение условия.

RESIGNAL включает значение условия (SQLSTATE '45000'), таким образом, это добавляет новую область условия, приводящую к стеку области диагностики, который похож на это:

DA 1. (condition 2) ERROR 1051 (42S02): Unknown table 'xx'
      (condition 1) ERROR 5 (45000) Unknown table 'xx'
Результат CALL p() и SHOW ERRORS:
mysql> CALL p();
ERROR 5 (45000): Unknown table 'xx'
mysql> SHOW ERRORS;
+-------+------+--------------------+
| Level | Code | Message            |
+-------+------+--------------------+
| Error | 1051 | Unknown table 'xx' |
| Error |    5 | Unknown table 'xx' |
+-------+------+--------------------+
14.6.7.4.4. RESIGNAL требует контекста обработчика условия

Все формы RESIGNAL требуют, чтобы текущий контекст был обработчиком условия. Иначе RESIGNAL происходит ошибка RESIGNAL when handler not active:

mysql> CREATE PROCEDURE p () RESIGNAL;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL p();
ERROR 1645 (0K000): RESIGNAL when handler not active
Here is a more difficult example:
delimiter //
CREATE FUNCTION f () RETURNS INT
BEGIN
  RESIGNAL;
  RETURN 5;
END//

CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @a=f();
  SIGNAL SQLSTATE '55555';
END//
delimiter ;
CALL p();
RESIGNAL происходит в пределах сохраненной функции f(). Хотя f() непосредственно вызван в пределах контекста обработчика EXIT, выполнение в пределах f() имеет его собственный контекст, который не является контекстом обработчика. Таким образом, RESIGNAL в пределах f() приводит к ошибке handler not active.

14.6.7.5. SIGNAL

SIGNAL condition_value
[SET signal_information_item
[, signal_information_item] ...]

condition_value:
SQLSTATE [VALUE] sqlstate_value
  | condition_name

signal_information_item:
condition_information_item_name = simple_value_specification

condition_information_item_name:
CLASS_ORIGIN
  | SUBCLASS_ORIGIN
  | MESSAGE_TEXT
  | MYSQL_ERRNO
  | CONSTRAINT_CATALOG
  | CONSTRAINT_SCHEMA
  | CONSTRAINT_NAME
  | CATALOG_NAME
  | SCHEMA_NAME
  | TABLE_NAME
  | COLUMN_NAME
  | CURSOR_NAME
condition_name, simple_value_specification:
(see following discussion)
SIGNAL это способ вернуть ошибку. SIGNAL предоставляет информацию об ошибке обработчику, внешней части приложения или клиенту. Кроме того, это обеспечивает управление характеристиками ошибки (код ошибки, SQLSTATE, сообщение). Без SIGNAL необходимо обратиться к обходным решениям, таким как преднамеренное обращение к несуществующей таблице, чтобы заставить подпрограмму возвращать ошибку.

condition_value в SIGNAL указывает на ошибочное значение, которое будет возвращено. Это может быть SQLSTATE (5-символьная строка) или condition_name, которое обращается к названному условию, ранее определенному с DECLARE ... CONDITION (см. раздел 14.6.7.1).

SQLSTATE может указать на ошибки, предупреждения или not found. Первые два символа значения указывают на его ошибочный класс, как обсуждено в разделе 14.6.7.5.1. Некоторый сигнал оценивает завершение запроса, см. раздел 14.6.7.5.2.

SQLSTATE для SIGNAL не должно начинаться с '00' потому, что такие значения указывают на успех и недопустимы для того, чтобы сигнализировать ошибку. Это истина для указания SQLSTATE в SIGNAL или в названном условии, упомянутом в запросе. Если значение недопустимо, будет ошибка Bad SQLSTATE.

SIGNAL произвольно включает SET, который содержит многократные элементы сигнала в списке разделенных запятой значений condition_information_item_name = simple_value_specification.

Каждый condition_information_item_name может быть определен только однажды в SET. Иначе будет ошибка Duplicate condition information item.

Допустимые указатели simple_value_specification могут быть определены, используя хранимую процедуру или функциональные параметры, местные переменные, объявленные с DECLARE, определяемые пользователем переменные, системные переменные или литералы. Символьный литерал может включать _charset.

См. раздел 14.6.7.5.1 .

Следующая процедура сигнализирует ошибку или предупреждение в зависимости от значения pval:

CREATE PROCEDURE p (pval INT)
BEGIN
  DECLARE specialty CONDITION FOR SQLSTATE '45000';
  IF pval = 0 THEN SIGNAL SQLSTATE '01000';
  ELSEIF pval = 1 THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = 'An error occurred';
  ELSEIF pval = 2 THEN
    SIGNAL specialty
    SET MESSAGE_TEXT = 'An error occurred';
  ELSE
    SIGNAL SQLSTATE '01000'
    SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
  END IF;
END;
Если pval = 0, p() сигнализирует предупреждение, потому что значения SQLSTATE, которые начинаются с '01' это сигналы в классе предупреждения. Предупреждение не заканчивает процедуру, и может быть замечено с SHOW WARNINGS после завершения процедуры.

Если pval = 1, p() сигнализирует ошибку и устанавливает MESSAGE_TEXT. Ошибка заканчивает процедуру, и текст возвращен с информацией об ошибке.

Если pval = 2, та же самая ошибка сообщена, хотя значение SQLSTATE определено, используя названное условие в этом случае.

Если pval что-то другое, p() сначала выдает предупреждение и ставит текст сообщения с кодом ошибки. Это предупреждение не заканчивает процедуру, таким образом, выполнение продолжается и p() сигнализирует ошибку. Ошибка действительно заканчивает процедуру. Текст сообщения и код ошибки, установленный предупреждением, заменены значениями, установленными ошибкой, которые возвращены с информацией об ошибке.

SIGNAL, как правило, используется в пределах сохраненных программ, но это расширение MySQL, потому что этому разрешают внешний контекст обработчика. Например, если Вы вызываете mysql, Вы можете ввести любой из этих запросов при подсказке:

mysql> SIGNAL SQLSTATE '77777';
mysql> CREATE TRIGGER t_bi BEFORE INSERT ON t
    ->        FOR EACH ROW SIGNAL SQLSTATE '77777';
mysql> CREATE EVENT e ON SCHEDULE EVERY 1 SECOND
    ->        DO SIGNAL SQLSTATE '77777';
SIGNAL выполняет согласно следующим правилам:

Если SIGNAL указывает на SQLSTATE, то значение используется, чтобы сигнализировать определенное условие. Пример:

CREATE PROCEDURE p (divisor INT)
BEGIN
  IF divisor = 0 THEN
     SIGNAL SQLSTATE '22012';
  END IF;
END;
Если SIGNAL использует названное условие, это условие должно быть объявлено в некотором контексте, который относится к SIGNAL, и должно быть определено, используя значение SQLSTATE, а не код ошибки MySQL. Пример:
CREATE PROCEDURE p (divisor INT)
BEGIN
  DECLARE divide_by_zero CONDITION FOR SQLSTATE '22012';
  IF divisor = 0 THEN
     SIGNAL divide_by_zero;
  END IF;
END;
Если названное условие не существует в пределах SIGNAL, будет ошибка Undefined CONDITION.

Если SIGNAL обращается к названному условию, которое определено с кодом ошибки MySQL, а не значением SQLSTATE, будет ошибка SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE. Следующие запросы вызывают эту ошибку, потому что названное условие связано с кодом ошибки MySQL:

DECLARE no_such_table CONDITION FOR 1051;
SIGNAL no_such_table;
Если условие с именем объявлено многократно в различных контекстах, декларация с самым местным контекстом применяется. Рассмотрите следующую процедуру:
CREATE PROCEDURE p (divisor INT)
BEGIN
  DECLARE my_error CONDITION FOR SQLSTATE '45000';
  IF divisor = 0 THEN BEGIN
     DECLARE my_error CONDITION FOR SQLSTATE '22012';
     SIGNAL my_error;
  END;
  END IF;
  SIGNAL my_error;
END;
Если divisor = 0, первый SIGNAL выполняется. Самая внутренняя декларация условия my_error применяется, поднимая SQLSTATE '22012'.

Если divisor не 0, второй SIGNAL выполняется. Наиболее удаленная декларация условия my_error применяется, поднимая SQLSTATE '45000'.

См. раздел 14.6.7.6.

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

CREATE PROCEDURE p ()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    SIGNAL SQLSTATE VALUE '99999'
    SET MESSAGE_TEXT = 'An error occurred';
  END;
  DROP TABLE no_such_table;
END;
CALL p() достигает DROP TABLE . Нет никакой таблицы no_such_table, таким образом, ошибочный обработчик активирован. Ошибочный обработчик разрушает оригинальную ошибку (no such table) и делает новую ошибку с SQLSTATE '99999' и сообщением An error occurred.

14.6.7.5.1. Единицы информации условия сигнала

Следующая таблица приводит названия единиц информации условия области диагностики, которые могут быть установлены в SIGNAL (или RESIGNAL). Все элементы стандартный SQL кроме MYSQL_ERRNO, который является расширением MySQL. Для получения дополнительной информации об этих элементах см. раздел 14.6.7.7.

Item Name           Definition
---------           ----------
CLASS_ORIGIN        VARCHAR(64)
SUBCLASS_ORIGIN     VARCHAR(64)
CONSTRAINT_CATALOG  VARCHAR(64)
CONSTRAINT_SCHEMA   VARCHAR(64)
CONSTRAINT_NAME     VARCHAR(64)
CATALOG_NAME        VARCHAR(64)
SCHEMA_NAME         VARCHAR(64)
TABLE_NAME          VARCHAR(64)
COLUMN_NAME         VARCHAR(64)
CURSOR_NAME         VARCHAR(64)
MESSAGE_TEXT        VARCHAR(128)
MYSQL_ERRNO         SMALLINT UNSIGNED
Набор символов для символьных элементов UTF-8.

Незаконно назначить NULL к единице информации условия в SIGNAL.

SIGNAL всегда определяет SQLSTATE, непосредственно или косвенно, обращаясь к названному условию, определенному с SQLSTATE. Первые два символа SQLSTATE это его класс, он определяет значение по умолчанию для единиц информации условия:

Для допустимых классов другие единицы информации условия установлены следующим образом:

CLASS_ORIGIN = SUBCLASS_ORIGIN = '';
CONSTRAINT_CATALOG = CONSTRAINT_SCHEMA = CONSTRAINT_NAME = '';
CATALOG_NAME = SCHEMA_NAME = TABLE_NAME = COLUMN_NAME = '';
CURSOR_NAME = '';
Ошибочные значения, которые доступны после выполнения SIGNAL передают значение SQLSTATE, поднятое SIGNAL и его элементы MESSAGE_TEXT и MYSQL_ERRNO. Эти значения доступны из C API:

Из SQL вывод SHOW WARNINGS и SHOW ERRORS указывает значения MYSQL_ERRNO и MESSAGE_TEXT в столбцах Code и Message.

Чтобы получить информацию из области диагностики, используйте GET DIAGNOSTICS (см. раздел 14.6.7.3).

14.6.7.5.2. Эффект сигналов на обработчиках, курсорах и запросах

Сигналы имеют различные эффекты на выполнение запросов в зависимости от класса сигнала. Класс определяет, насколько серьезна ошибка. MySQL игнорирует значение sql_mode, в частности, строгий режим SQL не имеет значения. MySQL также игнорирует IGNORE: SIGNAL должен поднять произведенную пользователем ошибку явно, таким образом, сигнал никогда не игнорируется.

В следующих описаниях unhandled значит, что никакой обработчик для сообщенного SQLSTATE не было определен с DECLARE ... HANDLER.

Пример:

mysql> delimiter //
mysql> CREATE FUNCTION f () RETURNS INT
    -> BEGIN
    ->   SIGNAL SQLSTATE '01234';  -- signal a warning
    ->   RETURN 5;
    -> END//
mysql> delimiter ;
mysql> CREATE TABLE t (s1 INT);
mysql> INSERT INTO t VALUES (f());
Результат состоит в том, что строка, содержащая 5, вставлена в таблицу t. Предупреждение, которое сообщено, может быть рассмотрено с SHOW WARNINGS.

14.6.7.6. Правила контекста для обработчиков

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

Многократные обработчики могут быть объявлены в различных контекстах и с различными спецификами. Например, мог бы быть определенный обработчик кода ошибки MySQL во внешнем блоке и общий обработчик SQLWARNING во внутреннем блоке. Или могли бы быть обработчики для определенного кода ошибки MySQL и общий для класса SQLWARNING в том же самом блоке.

Активирован ли обработчик, зависит не только от его собственного контекста и значения условия, но и от того, что присутствуют другие обработчики. Когда условие происходит в сохраненной программе, сервер ищет применимые обработчики в текущем контексте (текущем блоке BEGIN ... END). Если нет никаких применимых обработчиков, поиск продолжается направленный наружу с обработчиками в каждом последовательном контексте (блоке). Когда сервер находит один или более применимых обработчиков в данном контексте, он выбирает среди них, исходя из приоритета:

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

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

Следующие примеры демонстрируют, как MySQL применяет правила выбора обработчика.

Эта процедура содержит два обработчика, один для определенного значения SQLSTATE ('42S02') происходит для попыток удалить несуществующую таблицу, и один для общего класса SQLEXCEPTION:

CREATE PROCEDURE p1()
BEGIN
  DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
  SELECT 'SQLSTATE handler was activated' AS msg;
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
  SELECT 'SQLEXCEPTION handler was activated' AS msg;
  DROP TABLE test.t;
END;
Оба обработчика объявлены в том же самом блоке и имеют тот же самый контекст. Однако, SQLSTATE имеет приоритет над SQLEXCEPTION, так что, если таблица t не существует, DROP TABLE поднимает условие, которое активируется SQLSTATE:
mysql> CALL p1();
+--------------------------------+
| msg                            |
+--------------------------------+
| SQLSTATE handler was activated |
+--------------------------------+
Эта процедура содержит те же самые два обработчика. Но на сей раз, DROP TABLE и SQLEXCEPTION находятся во внутреннем блоке относительно SQLSTATE:
CREATE PROCEDURE p2()
BEGIN -- outer block
  DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
  SELECT 'SQLSTATE handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;
    DROP TABLE test.t; -- occurs within inner block
  END;
END;
В этом случае обработчик, который является более местным, где условие происходит, имеет приоритет. SQLEXCEPTION активируется, даже при том, что это является более общим, чем SQLSTATE:
mysql> CALL p2();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+
В этой процедуре один из обработчиков объявлен в блоке, внутреннем к контексту DROP TABLE:
CREATE PROCEDURE p3()
BEGIN -- outer block
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
  SELECT 'SQLEXCEPTION handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
    SELECT 'SQLSTATE handler was activated' AS msg;
  END;
  DROP TABLE test.t; -- occurs within outer block
END;
Только SQLEXCEPTION применяется, потому что другой не находится в контексте для условия, поднятого DROP TABLE:
mysql> CALL p3();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+
В этой процедуре оба обработчика объявлены в блоке, внутреннем к контексту DROP TABLE:
CREATE PROCEDURE p4()
BEGIN -- outer block
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
    SELECT 'SQLSTATE handler was activated' AS msg;
  END;
  DROP TABLE test.t; -- occurs within outer block
END;
Никакой обработчик не применяется, потому что они не находятся в контексте для DROP TABLE. Условие, поднятое запросом, идет необработанное и заканчивает процедуру с ошибкой:
mysql> CALL p4();
ERROR 1051 (42S02): Unknown table 'test.t'

14.6.7.7. Область диагностики MySQL

Запросы SQL производят диагностическую информацию, которая заполняет область диагностики. У стандартного SQL есть стек области диагностики, содержащий область диагностики для каждого вложенного контекста выполнения. Стандартный SQL также поддерживает GET STACKED DIAGNOSTICS для того, чтобы обратиться к второй области диагностики во время выполнения обработчика условия. MySQL поддерживает STACKED с MySQL 5.7.

Этот раздел описывает структуру области диагностики в MySQL, единицы информации, признанные MySQL, как запросы, устанавливает область диагностики и то, как области диагностики продвинуты в стек.

14.6.7.7.1. Структура области диагностики

Область диагностики содержит два вида информации:

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

Statement information:
  row count
  ... other statement information items ...
Condition area list:
  Condition area 1:
error code for condition 1
error message for condition 1
... other condition information items ...
  Condition area 2:
error code for condition 2:
error message for condition 2
... other condition information items ...
  Condition area 3:
error code for condition 3
error message for condition 3
... other condition information items ...
14.6.7.7.2. Элементы информации в области диагностики

Область диагностики содержит единицы информации условия и запрос. Числовые элементы это целые числа. Набор символов для символьных элементов UTF-8. Никакой элемент не может быть NULL. Если элемент запросы или условия не установлены запросом, который заполняет область диагностики, ее значение 0 или пустая строка, в зависимости от типа данных элемента.

Часть информации о запросе области диагностики содержит эти элементы:

Часть информации об условии области диагностики содержит область условия для каждого условия. Области условия пронумерованы от 1 до значения NUMBER. Если NUMBER = 0, нет никаких областей условия.

Каждая область условия содержит элементы в следующем списке. Все элементы из стандарта SQL, кроме MYSQL_ERRNO, который является расширением MySQL. Определения просят условия, произведенные не сигналом (то есть, SIGNAL или RESIGNAL). Для условий не от сигнала MySQL заполняет только те элементы условия, которые не описаны как всегда пустые. Эффекты сигналов на области условия описаны позже.

Для RETURNED_SQLSTATE, MESSAGE_TEXT и MYSQL_ERRNO для особых ошибок см. раздел B.3.

Если SIGNAL (или RESIGNAL) заполняет область диагностики, SET может назначить любую единицу информации условия, кроме RETURNED_SQLSTATE. SIGNAL также ставит RETURNED_SQLSTATE, но не непосредственно в SET. То значение прибывает из параметра SQLSTATE SIGNAL.

SIGNAL также ставит единицы информации запроса. Если number = 1, то ROW_COUNT = -1 для ошибок и 0 иначе.

14.6.7.7.3. Как заполнена область диагностики

Недиагностические запросы SQL заполняют область диагностики автоматически, ее содержание может быть установлено явно с SIGNAL и RESIGNAL. Область диагностики может быть исследована с GET DIAGNOSTICS, чтобы извлечь определенные элементы, или с SHOW WARNINGS или SHOW ERRORS, чтобы видеть условия или ошибки.

Запросы SQL определяют область диагностики следующим образом:

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

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

DROP TABLE очищает область диагностики и заполняет ее, когда условие происходит:

mysql> DROP TABLE IF EXISTS test.no_such_table;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------------+
| Level | Code | Message                            |
+-------+------+------------------------------------+
| Note  | 1051 | Unknown table 'test.no_such_table' |
+-------+------+------------------------------------+
1 row in set (0.00 sec)
SET производит ошибку, таким образом, очищает и заполняет область диагностики:
mysql> SET @x = @@x;
ERROR 1193 (HY000): Unknown system variable 'x'

mysql> SHOW WARNINGS;
+-------+------+-----------------------------+
| Level | Code | Message                     |
+-------+------+-----------------------------+
| Error | 1193 | Unknown system variable 'x' |
+-------+------+-----------------------------+
1 row in set (0.00 sec)
SET произвел единственное условие, таким образом, 1 это единственное допустимое число условий для GET DIAGNOSTICS . Следующий запрос использует число условия 2, которое производит предупреждение, добавленное к области диагностики, не очищая ее:
mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------+
| Level | Code | Message                      |
+-------+------+------------------------------+
| Error | 1193 | Unknown system variable 'xx' |
| Error | 1753 | Invalid condition number     |
+-------+------+------------------------------+
2 rows in set (0.00 sec)
Теперь есть два условия в области диагностики, таким образом, тот же самый GET DIAGNOSTICS работает:
mysql> GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @p;
+--------------------------+
| @p                       |
+--------------------------+
| Invalid condition number |
+--------------------------+
1 row in set (0.01 sec)
14.6.7.7.4. Как работает стек области диагностики

Когда происходит помещение области диагностики в стек, первая (текущая) область диагностики становится второй областью диагностики, и новая текущая область диагностики создается как копия этого. Области диагностики продвинуты в стек и извлечены из стека при следующих обстоятельствах:

14.6.7.7.5. Системные переменные, связанные с областью диагностики

Определенные системные переменные управляют или связаны с некоторыми аспектами области диагностики:

Пример: Если max_error_count = 10, область диагностики может содержать максимум 10 областей условия. Предположите, что запрос поднимает 20 условий, 12 из которых являются ошибками. В этом случае область диагностики содержит первые 10 условий, NUMBER = 10, warning_count = 20, error_count = 12.

Изменения max_error_count не имеют никакого эффекта до следующей попытки изменить область диагностики. Если область диагностики содержит 10 областей условия и max_error_count = 5, это не имеет никакого непосредственного эффекта на размер или контент области диагностики.

14.7. Запросы управления базами данных

14.7.1. Запросы управления учетными записями

Информация учетной записи MySQL хранится в таблицах базы данных mysql. Эта база данных и система управления доступом обсуждены в главе 6.

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

Когда read_only включена, запросы управления требуют привилегии SUPER в дополнение к любым другим необходимым привилегиям. Это потому, что они изменяют таблицы в базе данных mysql.

14.7.1.1. ALTER USER

ALTER USER [IF EXISTS]
user_specification [, user_specification] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...

ALTER USER [IF EXISTS]
USER() IDENTIFIED BY 'auth_string'

ALTER USER [IF EXISTS]
user DEFAULT ROLE
{NONE | ALL | role [, role ] ...}

user_specification:
user [ auth_option ]

auth_option: {
IDENTIFIED BY 'auth_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin AS 'hash_string'
}

tls_option: {
   SSL
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'
}

resource_option: {
MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}

password_option: {
PASSWORD EXPIRE
  | PASSWORD EXPIRE DEFAULT
  | PASSWORD EXPIRE NEVER
  | PASSWORD EXPIRE INTERVAL N DAY
}

lock_option: {
ACCOUNT LOCK
  | ACCOUNT UNLOCK
}
ALTER USER изменяет учетные записи MySQL. Это позволяет аутентификации, SSL/TLS, пределу ресурсов и свойствам пароля быть измененными для существующих учетных записей и включает блокировку учетной записи.

За исключением DEFAULT ROLE, ALTER USER требует глобальной привилегии CREATE USER или UPDATE для базы данных mysql. Для DEFAULT ROLE ALTER USER требует этих привилегий:

Когда включена read_only , ALTER USER требует привилегию SUPER.

Ошибка происходит, если Вы пытаетесь изменить учетную запись, которая не существует. IF EXISTS заставляет запрос производить предупреждение для каждой названной учетной записи, которая не существует, а не ошибку.

ALTER USER меняет строку таблицы mysql.user для каждой затронутой учетной записи согласно опциям, определенным в запросе. Неуказанные свойства сохраняют свое текущее значение.

Пример 1: Измените пароль учетной записи. В результате пользователь должен соединиться с названным паролем и выбрать новый в следующем соединении:

ALTER USER 'jeffrey'@'localhost'
      IDENTIFIED BY 'new_password' PASSWORD EXPIRE;
Пример 2: Измените учетную запись для применения ее плагина аутентификации sha256_password и данного пароля. Потребуйте, чтобы новый пароль был выбран каждые 180 дней:
ALTER USER 'jeffrey'@'localhost'
      IDENTIFIED WITH sha256_password BY 'new_password'
      PASSWORD EXPIRE INTERVAL 180 DAY;
Пример 3: Заблокируйте или разблокируйте учетную запись:
ALTER USER 'jeffrey'@'localhost' ACCOUNT LOCK;
ALTER USER 'jeffrey'@'localhost' ACCOUNT UNLOCK;
Пример 4: Потребуйте, чтобы учетная запись использовала SSL и установите предел 20 соединений в час:
ALTER USER 'jeffrey'@'localhost'
      REQUIRE SSL WITH MAX_CONNECTIONS_PER_HOUR 20;

При некоторых обстоятельствах ALTER USER может быть зарегистрирован в журналах сервера или на стороне клиента в файле истории, например, в ~/.mysql_history, что означает, что пароли открытого текста могут быть считаны любым имеющим доступ к этой информации. Для информации об условиях, при которых это происходит для журналов сервера и как управлять этим см. раздел 7.1.2.3. Для подобной информации о клиентском журналировании см. раздел 5.5.1.3.

Каждое имя учетной записи использует формат, описанный в разделе 7.2.3. Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'. Также возможно определить CURRENT_USER или CURRENT_USER(), чтобы ссылаться на учетную запись, связанную с текущим сеансом.

Для одного синтаксиса учетная запись может быть определена с помощью USER():

ALTER USER USER() IDENTIFIED BY 'auth_string';
Этот синтаксис позволяет изменить Ваш собственный пароль, не называя Вашу учетную запись буквально.

Каждый параметр user_specification состоит из имени учетной записи и дополнительного auth_option, которое определяет, как учетная запись подтверждает подлинность. Эти значения позволяют плагинам аутентификации учетной записи быть определенными. Каждый auth_option применяется только к пользователю, названному перед этим.

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

Пример: Это запрос изменяет пароль для jeffrey, но не для jeanne. Для обеих учетных записей соединения обязаны использовать SSL, и каждая учетная запись может использоваться максимум для двух одновременных соединений:

ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'new_password',
      'jeanne'@'localhost' REQUIRE SSL WITH MAX_USER_CONNECTIONS 2;
В отсутствие особого типа опции учетная запись остается неизменной в этом отношении. Например, без опции блокировки, статус блокировки учетной записи не изменен.

Есть несколько аспектов ALTER USER, описанных в этом разделе:

Опции аутентификации

Имя учетной записи может сопровождаться опцией аутентификации, которая определяет плагин аутентификации учетной записи:

ALTER USER разрешает такие форматы auth_option:

Плагин по умолчанию mysql_native_password, если переменная default_authentication_plugin не установлена иначе. Для описаний каждого плагина см. раздел 7.5.1.

Пример 1: Определите пароль как открытый текст, плагин по умолчанию используется:

ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';
Пример 2: Определите плагин аутентификации, наряду со значением пароля открытого текста:
ALTER USER 'jeffrey'@'localhost' IDENTIFIED WITH mysql_native_password
      BY 'mypass';
Пример 3: Определите плагин аутентификации, наряду с хешированным значением пароля:
ALTER USER 'jeffrey'@'localhost' IDENTIFIED WITH mysql_native_password
      AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
Опции SSL/TLS

MySQL может проверить признаки сертификата X509 в дополнение к обычной аутентификации, которая основана на имени пользователя и пароле. Для вводной информации об использовании SSL с MySQL см. раздел 7.4.

Чтобы определить опции SSL для учетной записи MySQL, используйте REQUIRE, который определяет одну или больше tls_option.

ALTER USER разрешает значения tls_option:

SUBJECT, ISSUER и CIPHER могут быть объединены в REQUIRE:

ALTER USER 'jeffrey'@'localhost'
      REQUIRE SUBJECT '/C=SE/ST=Stockholm/L=Stockholm/
      O=MySQL demo client certificate/
      CN=client/emailAddress=client@example.com' AND
      ISSUER '/C=SE/ST=Stockholm/L=Stockholm/
      O=MySQL/CN=CA/emailAddress=ca@example.com' AND
      CIPHER 'EDH-RSA-DES-CBC3-SHA';
Порядок опций не имеет значения, но никакая опция не может быть определена дважды. AND является дополнительным между опциями REQUIRE.

Опции предела ресурса

Возможно установить границы использования ресурсов сервера учетной записью, как обсуждено в разделе 7.3.5. Чтобы сделать так, используйте WITH, который определяет одно или больше значений resource_option:

ALTER USER допускает такие значения resource_option:

Пример:

ALTER USER 'jeffrey'@'localhost'
      WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
Если данный предел ресурса определен многократно, последний случай имеет приоритет.

Опции истечения пароля

ALTER USER поддерживает несколько password_option для управления истечением пароля, чтобы истечь пароль учетной записи или установить его логику. Стратегические опции не истекают пароль, вместо этого они определяют, как сервер применяет автоматическое истечение к учетной записи (см. раздел 7.3.7).

Время жизни пароля оценено с даты и времени последнего изменения.

ALTER USER позволяет эти значения password_option:

Если многократные опции истечения пароля определены, последняя имеет приоритет.

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

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

Блокирующие учетную запись опции

MySQL поддерживает блокировку учетной записи через ACCOUNT LOCK и ACCOUNT UNLOCK, которые определяют статус блокировки для учетной записи. Для дополнительного обсуждения см. раздел 7.3.11.

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

Ролевые опции

ALTER USER ... DEFAULT ROLE определяет, какие роли становятся активными, когда запрос SET ROLE DEFAULT выполнен во время сеанса для данного пользователя. После успешной пользовательской аутентификации сервер неявно выполняет SET ROLE DEFAULT.

Следующий запрос назначает 'joe'@'10.0.0.1' роли по умолчанию administrator и developer:

ALTER USER 'joe'@'10.0.0.1' DEFAULT ROLE administrator, developer;

14.7.1.2. CREATE ROLE

CREATE ROLE [IF NOT EXISTS] role [, role ] ...
CREATE ROLE создает одну или более ролей, которые называют наборами привилегий. Чтобы использовать это запрос, у Вас должна быть глобальная привилегия CREATE ROLE или CREATE USER.

Ошибка происходит, если Вы пытаетесь создать роль, которая уже существует. IF NOT EXISTS заменяет ошибку предупреждением.

Если CREATE ROLE называет многократные роли, это преуспевает для всех названных ролей или откатывается и не имеет никакого эффекта, если ошибка происходит.

Роль при создании заблокирована, не имеет никакого пароля, и ей назначен плагин аутентификации по умолчанию.

Для ролевых примеров использования см. раздел 7.3.4.

14.7.1.3. CREATE USER

CREATE USER [IF NOT EXISTS]
user_specification [, user_specification] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...

user_specification:
user [ auth_option ]

auth_option: {
IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY PASSWORD 'hash_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin AS 'hash_string'
}

tls_option: {
   SSL
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'
}

resource_option: {
MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}

password_option: {
PASSWORD EXPIRE
  | PASSWORD EXPIRE DEFAULT
  | PASSWORD EXPIRE NEVER
  | PASSWORD EXPIRE INTERVAL N DAY
}

lock_option: {
ACCOUNT LOCK
  | ACCOUNT UNLOCK
}
CREATE USER создает новые учетные записи MySQL. Это позволяет аутентификации, SSL/TLS, пределу ресурса и свойствам истечения пароля быть установленными для новых учетных записей, а также управляет, заблокированы ли учетные записи первоначально или нет.

У учетной записи когда создается нет никаких привилегий и роль по умолчанию NONE.

Чтобы использовать CREATE USER , Вы должны иметь глобальную привилегию CREATE USER или привилегию INSERT для базы данных mysql. При включенной переменной read_only CREATE USER дополнительно требует SUPER.

Ошибка происходит, если Вы пытаетесь создать учетную запись, которая уже существует. IF NOT EXISTS превращает ошибку в предупреждение.

Для каждой учетной записи CREATE USER создает новую строку в таблице mysql.user. Строка отражает свойства, определенные в запросе. Неуказанные свойства установлены в их значения по умолчанию.

Пример 1: Создайте учетную запись, которая использует плагин аутентификации по умолчанию и данный пароль. Отметьте пароль как истекший, чтобы пользователь выбрал новый в первом соединении с сервером:

CREATE USER 'jeffrey'@'localhost'
       IDENTIFIED BY 'new_password' PASSWORD EXPIRE;
Пример 2: Создайте учетную запись, которая использует плагин аутентификации sha256_password и данный пароль. Потребуйте, чтобы новый пароль был выбран каждые 180 дней:
CREATE USER 'jeffrey'@'localhost'
       IDENTIFIED WITH sha256_password BY 'new_password'
       PASSWORD EXPIRE INTERVAL 180 DAY;

При некоторых обстоятельствах CREATE USER может быть зарегистрирован в журналах сервера или на стороне клиента в файле истории ~/.mysql_history, что означает, что пароли открытого текста могут быть считаны любым имеющим доступ к этой информации. Для информации об условиях, при которых это происходит для журналов сервера и как управлять ею, см. раздел 7.1.2.3.

См. разделы 7.3.6 и 7.3.9.

Каждое имя учетной записи использует формат, описанный в разделе 7.2.3:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';
Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'.

Каждый user_specification состоит из имени учетной записи и дополнительного значения auth_option, которое определяет, как учетная запись подтверждает подлинность. Эти значения позволяют плагинам аутентификации учетной записи быть определенными. Каждое значение auth_option применяется только к пользователю, названному перед этим.

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

Пример: этот запрос создает две учетных записи, каждую с плагином аутентификации по умолчанию и паролем. Для обеих учетных записей соединения должны быть сделаны, используя допустимый сертификат X509, и разрешены до 60 запросов в час. Обе учетных записи заблокированы первоначально и не могут использоваться, пока администратор не разблокирует их:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'new_password1',
       'jeanne'@'localhost' IDENTIFIED BY 'new_password2'
       REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60 ACCOUNT LOCK;
Для опущенных опций используются эти значения по умолчанию:

Есть несколько аспектов CREATE USER:

Все они в целом аналогичны описанным для команды ALTER USER.

14.7.1.4. DROP ROLE

DROP ROLE [IF EXISTS] role [, role ] ...
DROP ROLE удаляет одну или более ролей (наборов привилегий). Чтобы использовать этот запрос, у Вас должна быть глобальная привилегия DROP ROLE или привилегия CREATE USER .

Ошибка происходит, если Вы пытаетесь удалить роль, которая не существует. IF EXISTS заставляет запрос производить предупреждение, а не ошибку для каждой названной роли, которая не существует.

Если DROP ROLE названо много ролей, это преуспевает для всех названных ролей или откатывается и не имеет никакого эффекта, если ошибка происходит.

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

14.7.1.5. DROP USER

DROP USER [IF EXISTS] user [, user] ...
DROP USER удаляет одну или более учетных записей MySQL и их привилегии. Это удаляет строки привилегии для учетной записи из всех таблиц.

Для применения DROP USER Вы должны иметь глобальную привилегию CREATE USER или привилегию DELETE для базы данных mysql. При включенной опции read_only DROP USER дополнительно требует привилегию SUPER.

Ошибка происходит, если Вы пытаетесь удалить учетную запись, которая не существует. IF EXISTS превращает ошибку в предупреждение.

Каждое имя учетной записи использует формат, описанный в разделе 7.2.3:

DROP USER 'jeffrey'@'localhost';
Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'.

DROP USER автоматически не закрывает открытых пользовательских сеансов. Когда пользователь с открытым сеансом удален, запрос не вступает в силу до закрытия сеанса пользователя. Как только сеанс закрыт, пользователь удален, и следующая попытка пользователя войти в систему потерпит неудачу.

DROP USER автоматически не удаляет базы данных или объекты в их пределах, которых создал старый пользователь. Это включает сохраненные программы или представления, для которых DEFINER это удаленный пользователь. Попытки получить доступ к таким объектам могут произвести ошибку, если они выполняются в контексте безопасности определителя. Для информации о контексте безопасности см. раздел 21.6.

14.7.1.6. GRANT

GRANT
priv_type [(column_list)]
  [, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH {GRANT OPTION | resource_option} ...]

GRANT PROXY ON user_specification
TO user_specification [, user_specification] ...
[WITH GRANT OPTION]

GRANT role [, role] ...
TO user [, user] ...
[WITH ADMIN OPTION]

object_type: {
TABLE
  | FUNCTION
  | PROCEDURE
}

priv_level: {
*
  | *.*
  | db_name.*
  | db_name.tbl_name
  | tbl_name
  | db_name.routine_name
}

user_specification:
user [ auth_option ]
auth_option: {
IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY PASSWORD 'hash_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin AS 'hash_string'
}

tls_option: {
SSL
  | X509
  | CIPHER 'cipher'
  | ISSUER 'issuer'
  | SUBJECT 'subject'
}

resource_option: {
  | MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}
GRANT позволяет системным администраторам предоставить привилегии и роли, которые они могут предоставить учетным записям пользователя и ролям. Эти ограничения синтаксиса применяются:

Разрешено назначить привилегии и роли учетной записи, но Вы должны использовать отдельные запросы GRANT для ролей и привилегий.

Чтобы использовать GRANT Вы должны иметь привилегию GRANT OPTION и у Вас должны быть привилегии, которые Вы предоставляете. Когда включена переменная read_only, GRANT дополнительно требует привилегию SUPER.

REVOKE связан с GRANT и позволяет администраторам удалить привилегии учетной записи. См. раздел 14.7.1.8.

Обычно администратор базы данных сначала использует CREATE USER, чтобы создать учетную запись и определить такие ее характеристики, как пароль, использует ли это безопасные соединения и ограничения на доступ к ресурсам сервера, затем использует GRANT, чтобы определить привилегии. ALTER USER может использоваться, чтобы изменить характеристики существующих учетных записей. Например:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost';
ALTER USER 'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 90;

Примеры, показанные здесь, не включают IDENTIFIED. Предполагается, что Вы устанавливаете пароли с CREATE USER во время создания учетной записи, чтобы избежать создавать опасные учетные записи.

Если учетную запись называют в GRANT , но она не существует, GRANT может создать это при условиях, описанных позже в обсуждении режима SQL NO_AUTO_CREATE_USER . Также возможно использовать GRANT , чтобы определить такие характеристики, как использует ли учетная запись безопасные соединения и пределы доступа к ресурсам сервера.

Однако, использование GRANT, чтобы создать учетные записи или определить характеристики устарело. Вместо этого выполните эти задачи с использованием CREATE USER или ALTER USER.

Из mysql GRANT отвечает Query OK, 0 rows affected, когда выполнен успешно. Чтобы определить, какие привилегии даны, надо использовать SHOW GRANTS. См. раздел 14.7.5.21.

Есть несколько аспектов GRANT:

GRANT понимает имена хоста до 60 символов в длину. База данных, таблица, столбец и имена подпрограмм могут быть до 64 символов. Имена пользователей могут быть до 32 символов.

Допустимая длина для имен пользователя не может быть изменена, изменяя mysql.user. Попытка сделать так приведет к непредсказуемому поведении, которое может даже лишить возможности пользователей входить в систему. Вы никогда не должны изменять структуру таблиц в базе данных mysql в любой манере вообще, кроме процедуры, описанной в разделе 5.4.5.

Привилегии, поддержанные MySQL

Следующая таблица суммирует допустимые типы привилегии priv_type, которые могут быть определены для GRANT и REVOKE, и уровни, на которых можно предоставить каждую привилегию. Для дополнительной информации об этих привилегиях см. раздел 7.2.1.

Таблица 14.3. Допустимые привилегии для GRANT и REVOKE

Привилегия Значение и уровни
ALL [PRIVILEGES]Предоставить все привилегии на указанном уровне доступа, кроме GRANT OPTION
ALTER Включает использование ALTER TABLE. Уровни: глобальный, база данных, таблица.
ALTER ROUTINEПозволяет сохраненным подпрограммам быть измененными или удаленными. Уровни: глобальный, база данных, процедура.
CREATE Включает создание таблиц и баз данных. Уровни: глобальный, база данных, таблица.
CREATE ROUTINEВключает создание сохраненных подпрограмм. Уровни: глобальный, база данных.
CREATE TABLESPACEПозволяет создавать, изменять или удалять табличные пространства и группы файлов системного журнала. Уровень: глобальный.
CREATE TEMPORARY TABLESРазрешает использовать CREATE TEMPORARY TABLE. Уровни: глобальный, база данных.
CREATE USERПозволяет использование CREATE USER, DROP USER, RENAME USER и REVOKE ALL PRIVILEGES. Уровень: глобальный.
CREATE VIEWПозволяет создавать или изменять представления. Уровни: глобальный, база данных, таблица.
DELETE Разрешает использовать DELETE . Уровни: глобальный, база данных, таблица.
DROP Позволяет удалять базы данных, таблицы и представления. Уровни: глобальный, база данных, таблица.
EVENT Включает использование событий для Event Scheduler. Уровни: глобальный, база данных.
EXECUTE Позволяет пользователю выполнить сохраненные подпрограммы. Уровни: глобальный, база данных, таблица.
FILE Позволяет пользователю заставить сервер читать или писать файлы. Уровень: глобальный.
GRANT OPTIONПозволяет предоставлять или удалять привилегии из других учетных записей. Уровни: глобальный, база данных, таблица, процедура, proxy.
INDEX Включает создание или удаление индекса. Уровни: глобальный, база данных, таблица.
INSERT Разрешает INSERT. Уровни: глобальный, база данных, таблица, столбец.
LOCK TABLESВключить использование LOCK TABLES на таблицах, для которых Вы имеете привилегию SELECT. Уровни: глобальный, база данных.
PROCESS Позволяет пользователю видеть все процессы с SHOW PROCESSLIST. Уровень: глобальный.
PROXY Включает пользователю proxying. Уровень: От пользователя пользователю.
REFERENCES Включает создание внешнего ключа. Уровни: глобальный, база данных, таблица, столбец.
RELOAD Включает использование FLUSH . Уровень: глобальный.
REPLICATION CLIENTПозволяет пользователю запросить основные или ведомые серверы. Уровень: глобальный.
REPLICATION SLAVEПозволяет ведомым устройствам читать двоичные события журнала с ведущего устройства. Уровень: глобальный.
SELECT Включает использование SELECT . Уровни: глобальный, база данных, таблица, столбец.
SHOW DATABASESПозволяет SHOW DATABASES показать все базы данных. Уровень: Глобальный.
SHOW VIEW Позволяет SHOW CREATE VIEW. Уровни: глобальный, база данных, таблица.
SHUTDOWN Позволяет mysqladmin shutdown. Уровень: Глобальный.
SUPER Позволяет использование других административных задач: CHANGE MASTER TO, KILL, PURGE BINARY LOGS, SET GLOBAL и mysqladmin debug . Уровень: Глобальный.
TRIGGER Включить работу с триггерами. Уровни: глобальный, база данных, таблица.
UPDATE Разрешает UPDATE. Уровни: глобальный, база данных, таблица, столбец.
USAGE Синоним для no privileges.

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

В GRANT ALL [PRIVILEGES] или PROXY привилегию нужно назвать отдельно, она не может быть определена наряду с другими привилегиями. ALL [PRIVILEGES] синоним для всех привилегий, доступных для уровня, на котором привилегии предоставлены, за исключением GRANT OPTION и PROXY.

USAGE может быть определен, чтобы создать пользователя, у которого нет никаких привилегий, или определить REQUIRE или WITH для учетной записи, не изменяя ее существующие привилегии. Однако, использование GRANT, чтобы определить такие характеристики устарело в MySQL 5.7.6. Используйте CREATE USER или ALTER USER.

Информация учетной записи MySQL хранится в таблицах базы данных mysql. Подробности в разделе 7.2.

Если таблицы содержат строки привилегии, которые содержат имена базы данных или имена таблиц смешанного регистра и lower_case_table_names не 0, REVOKE не может использоваться, чтобы отменить эти привилегии. Будет необходимо управлять таблицами непосредственно. ( GRANT не будет создавать такие строки, когда установлена lower_case_table_names, но такие строки, возможно, были созданы до установки этой переменной.

Привилегии можно предоставить на нескольких уровнях, в зависимости от синтаксиса, используемого для ON. Для REVOKE ON определяет, которые привилегии удалить.

Для уровней глобального, базы данных, таблицы и подпрограммы GRANT ALL назначает только привилегии, которые существуют на уровне, который Вы предоставляете. Например, GRANT ALL ON db_name .* на уровне базы данных, таким образом, это не предоставляет специфических глобальных привилегий, например, FILE. Предоставление ALL не назначает GRANT OPTION или PROXY.

object_type, если есть, должен быть определен как TABLE, FUNCTION или PROCEDURE, когда следующий объект это таблица, сохраненная функция или хранимая процедура.

Привилегии для базы данных, таблицы, столбца или подпрограммы сформированы совокупно как логическое OR из привилегий на каждом из уровней. Например, если у пользователя есть глобальный SELECT, привилегия не может отрицаться отсутствием привилегии на уровне базы данных, таблицы или столбца. Детали проверяющей привилегию процедуры представлены в разделе 7.2.6.

Если Вы используете привилегии таблицы, столбца или подпрограммы даже для одного пользователя, сервер исследует привилегии таблицы, столбца и подпрограммы для всех пользователей, а это немного замедляет MySQL. Точно так же, если Вы ограничиваете число запросов, обновлений или соединений для каких-либо пользователей, сервер должен контролировать эти значения.

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

MySQL автоматически не отменяет привилегий, когда Вы удаляете базу данных или таблицу. Однако, если Вы удаляете подпрограмму, любые привилегии, предоставленные для этой подпрограммы, отменяются.

Глобальные привилегии

Глобальные привилегии являются административными или относятся ко всем базам данных по данному серверу. Чтобы назначить глобальные привилегии, надо использовать ON *.*:

GRANT ALL ON *.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';
CREATE TABLESPACE , CREATE USER, FILE, PROCESS, RELOAD, REPLICATION CLIENT , REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN и SUPER являются административными и могут быть предоставлены только глобально.

Другие привилегии можно предоставить глобально или на более определенных уровнях.

MySQL хранит глобальные привилегии в таблице mysql.user.

Привилегии базы данных

Привилегии базы данных относятся ко всем объектам в данной базе данных. Чтобы назначить привилегии на уровне базы данных, надо использовать ON db_name.*:

GRANT ALL ON mydb.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';
Если Вы используете ON * (вместо ON *.*) и Вы выбрали базу данных по умолчанию, привилегии назначены на уровне базы данных для базы данных по умолчанию. Ошибка происходит, если нет никакой базы данных по умолчанию.

CREATE, DROP, EVENT, GRANT OPTION, LOCK TABLES и REFERENCES могут быть определены на уровне базы данных. Привилегии таблицы или подпрограммы также могут быть определены на уровне базы данных, когда они относятся ко всем таблицам или подпрограммам в базе данных.

MySQL хранит привилегии базы данных в таблице mysql.db.

Табличные привилегии

Табличные привилегии относятся ко всем столбцам в данной таблице. Чтобы назначить привилегии на уровне таблицы, надо использовать ON db_name.tbl_name:

GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';
Если Вы определяете tbl_name вместо db_name.tbl_name, запрос относится к tbl_name в базе данных по умолчанию. Ошибка происходит, если нет никакой базы данных по умолчанию.

Допустимые значения priv_type на табличном уровне: ALTER, CREATE VIEW, CREATE, DELETE, DROP, GRANT OPTION, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER и UPDATE.

MySQL хранит табличные привилегии в таблице mysql.tables_priv.

Привилегии столбца

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

GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';
Допустимые значения priv_type для столбца (то есть, когда Вы используете column_list): INSERT, REFERENCES, SELECT и UPDATE.

MySQL хранит привилегии столбца в таблице mysql.columns_priv.

Привилегии сохраненных подпрограмм

ALTER ROUTINE, CREATE ROUTINE, EXECUTE и GRANT OPTION относятся к сохраненным подпрограммам (процедуры и функции). Их можно предоставить на глобальных уровнях и уровнях базы данных. За исключением CREATE ROUTINE, эти привилегии можно предоставить для отдельных подпрограмм.

GRANT CREATE ROUTINE ON mydb.* TO 'someuser'@'somehost';
GRANT EXECUTE ON PROCEDURE mydb.myproc TO 'someuser'@'somehost';
Допустимые priv_type на уровне подпрограмм: ALTER ROUTINE, EXECUTE и GRANT OPTION. CREATE ROUTINE не привилегия на обычном уровне, потому что у Вас должна быть эта привилегия, чтобы создать подпрограмму

MySQL хранит привилегии для подпрограмм в таблице mysql.procs_priv.

Привилегии Proxy

PROXY позволяет одному пользователю быть полномочием для другого. Пользователь является олицетворением или берет личность proxy-пользователя.

GRANT PROXY ON 'localuser'@'localhost' TO 'externaluser'@'somehost';
Когда PROXY предоставлена, это должна быть единственная привилегия, названная в GRANT, REQUIRE не может быть дан, и разрешен единственный параметр WITH: WITH GRANT OPTION.

Это требует, чтобы пользователь по доверенности подтвердил подлинность через плагин, который возвращает имя proxied пользователя к серверу, когда пользователь по доверенности соединяется, и что пользователь по доверенности имеет привилегию PROXY. Подробности в разделе 7.3.10.

MySQL хранит привилегии proxy в таблице mysql.proxies_priv.

Имена учетной записи и пароли

user_specification называет пользователя и произвольно предоставляет информацию об аутентификации, такую как пароль.

user указывает на учетную запись MySQL, к которой GRANT применяется. Чтобы приспособить предоставление прав пользователям от произвольных узлов, MySQL поддерживает определение user в формате user_name@host_name. Если user_name или host_name является законным как идентификатор, Вы не должны заключить его в кавычки. Однако, кавычки необходимы, чтобы определить user_name, содержащее специальные символы (например, -) или если host_name содержит специальные или подстановочные символы (например, %). Заключите в кавычки имя пользователя и имя хоста отдельно.

Вы можете определить подстановочные знаки в имени хоста. Например, user_name@'%.example.com' относится к user_name для любого узла в домене example.com, а user_name@'192.168.1.%' относится к user_name для любого узла в подсети 192.168.1 класса C.

Простая форма user_name это синоним для user_name@'%'.

MySQL не поддерживает подстановочные знаки в именах пользователей. Чтобы обратиться к анонимному пользователю, определите учетную запись с пустым именем пользователя с помощью GRANT:

GRANT ALL ON test.* TO ''@'localhost' ...;
В этом случае, любому пользователю, который соединяется от местного узла с правильным паролем для анонимного пользователя, разрешат доступ с привилегиями, связанными с анонимной учетной записью пользователя.

См. раздел 7.2.3.

Чтобы определить заключенные в кавычки значения, заключите в кавычки базу данных, таблицу или столбец как идентификаторы. Имена пользователя и хоста берутся в кавычки как идентификаторы или как строки. Пароли берутся в кавычки как строки. Для заключения в кавычки строк и идентификаторов см. разделы 10.1.1 и 10.2.

_ и % разрешены, определяя имена базы данных в GRANT, которые предоставляют привилегии на уровне базы данных. Это означает, например, что, если Вы хотите использовать _ как часть имени базы данных, Вы должны определить это как \_ в GRANT, чтобы предотвратить возможность доступа к дополнительным базам данных, соответствующих подстановочному образцу, например, GRANT ... ON `foo\_bar`.* TO ....

Если Вы разрешаете анонимным пользователям соединяться с сервером MySQL, Вы должны также предоставить привилегии всем местным пользователям как user_name@localhost. Иначе анонимная учетная запись пользователя для localhost в таблице mysql.user (создаваемая во время установки MySQL) используется, когда названный пользователь пытается войти в систему MySQL с местной машины. Для деталей см. раздел 7.2.5.

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

SELECT Host, User FROM mysql.user WHERE User='';
Чтобы избежать этой проблемы, удалите местную анонимную учетную запись пользователя, используя этот запрос:
DROP USER ''@'localhost';

Чтобы указать, как пользователь должен подтвердить подлинность, соединяясь с сервером, значение user_specification может включать IDENTIFIED, чтобы определить плагин аутентификации, пароль или обоих. Синтаксис пользовательской спецификации тот же самый, что в CREATE USER. См. раздел 14.7.1.3.

Если задан IDENTIFIED BY и у Вас есть глобальная привилегия (GRANT OPTION), пароль становится новым паролем для учетной записи, даже если учетная запись существует и уже имеет пароль. Без IDENTIFIED BY пароль учетной записи остается неизменным.

Неявное создание учетной записи

Если учетную запись называют в GRANT , но она не существует, предпринятые меры зависят от значения режима SQL NO_AUTO_CREATE_USER :

Если учетная запись уже существует, IDENTIFIED WITH запрещен, потому что это предназначено только для использования, создавая новые учетные записи.

Другие характеристики учетной записи

MySQL может проверить признаки сертификата X509 в дополнение к обычной аутентификации, которая основана на имени пользователя. Для вводной информации об использовании SSL с MySQL см. раздел 7.4.

REQUIRE определяет опции SSL для учетной записи MySQL. Синтаксис тот же самый, что и в CREATE USER, см. раздел 14.7.1.3.

WITH используется в этих целях:

WITH GRANT OPTION дает пользователю способность дать другим пользователям любые привилегии, которые пользователь имеет на указанном уровне привилегии.

Чтобы предоставить GRANT OPTION учетной записи, иначе не изменяя ее привилегии, сделайте это:

GRANT USAGE ON *.* TO 'someuser'@'somehost' WITH GRANT OPTION;
Два пользователя с различными привилегиями могут быть в состоянии объединить привилегии!

Вы не можете предоставить другому пользователю привилегию, которую сами не имеете, GRANT OPTION позволяет Вам назначить только те привилегии, которыми Вы обладаете сами.

Знайте что, когда Вы предоставляете пользователю GRANT OPTION на особом уровне привилегии, любые привилегии, которыми пользователь обладает (или может получить в будущем) на этом уровне, могут быть предоставлены им другим пользователям. Предположите, что Вы предоставляете пользователю привилегию INSERT на базе данных. Если Вы потом предоставляете привилегию SELECT на базе данных м указываете WITH GRANT OPTION, тот пользователь может дать другим пользователям не только SELECT, но и INSERT. Если Вы позже предоставляете UPDATE на базе данных, пользователь может предоставить INSERT, SELECT и UPDATE.

Для неадминистративного пользователя Вы не должны предоставить ALTER глобально или для базы данных mysql. Если Вы делаете это, пользователь может попытаться ниспровергать систему привилегий, переименовывая таблицы!

См. раздел 7.2.1.

Возможно установить границы использования ресурсов сервера учетной записью, как обсуждено в разделе 7.3.5. Используйте WITH с параметром resource_option. Не определенные пределы сохраняют свое текущее значение. Синтаксис тот же самый, что в CREATE USER, см. раздел 14.7.1.3.

Версии GRANT в MySQL и стандартном SQL

Самые большие различия между MySQL и стандартными версиями SQL GRANT:

14.7.1.7. RENAME USER

RENAME USER old_user TO new_user
[, old_user TO new_user] ...
RENAME USER переименовывает существующие учетные записи MySQL. Ошибка происходит для старых учетных записей, которые не существуют, или новых учетных записей, которые уже существуют.

Чтобы использовать RENAME USER , у Вас должна быть глобальная привилегия CREATE USER или привилегия UPDATE для базы данных mysql. Если включена read_only, RENAME USER требует привилегии SUPER.

Каждое имя учетной записи использует формат, описанный в разделе 7.2.3:

RENAME USER 'jeffrey'@'localhost' TO 'jeff'@'127.0.0.1';
Если Вы определяете только часть имени пользователя имени учетной записи, используется часть имени хоста '%'.

RENAME USER копирует привилегии старого пользователя новому. Однако, RENAME USER автоматически не удаляет базы данных или объекты, которые создал старый пользователь. Это включает сохраненные программы или представления, для которых DEFINER это старый пользователь. Попытки получить доступ к таким объектам могут произвести ошибку, если они выполняют в контексте безопасности определителя (см. раздел 21.6).

Изменения привилегий вступают в силу как обозначено в разделе 7.2.7.

14.7.1.8. REVOKE

REVOKE
priv_type [(column_list)]
  [, priv_type [(column_list)]] ...
ON [object_type] priv_level
FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION
FROM user [, user] ...

REVOKE PROXY ON user
FROM user [, user] ...

REVOKE role [, role ] ...
FROM user [, user ] ...
REVOKE позволяет системным администраторам отменить привилегии и роли, которые он может отменить от учетных записей пользователя и ролей.

При включенной переменной read_only REVOKE требует привилегии SUPER.

Каждое имя учетной записи использует формат, описанный в разделе 7.2.3:

REVOKE INSERT ON *.* FROM 'jeffrey'@'localhost';
Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'.

Для деталей об уровнях, на которых привилегии существуют, допустимых значениях priv_type, priv_level и object_type см. раздел 14.7.1.6.

Чтобы использовать первый вариант REVOKE, Вы должны иметь привилегию GRANT OPTION, и у Вас должны быть привилегии, которые Вы отменяете.

Чтобы отменить все привилегии, используйте второй синтаксис, который удаляет все привилегии глобальные, базы данных, таблицы и столбца для названного пользователя или пользователей: named user or users:

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user
[, user] ...
Чтобы использовать этот вариант REVOKE , у Вас должна быть глобальная привилегия CREATE USER или привилегия UPDATE на базе данных mysql.

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user не отменяет ролей.

REVOKE удаляет привилегии, но не удаляет записи таблицы mysql.user. Чтобы удалить учетную запись пользователя полностью, надо использовать DROP USER (см. раздел 14.7.1.5) или DELETE.

Если таблицы содержат строки привилегии, которые содержат имена базы данных или имена таблиц в смешанном регистре и lower_case_table_names не 0, REVOKE не может использоваться, чтобы отменить эти привилегии. Будет необходимо управлять таблицами непосредственно. GRANT не будет создавать такие строки, когда lower_case_table_names установлена, но такие строки, возможно, были созданы до установки переменной.

Когда успешно выполнено из mysql, REVOKE отвечает Query OK, 0 rows affected. Чтобы определить результат команды, используйте SHOW GRANTS . См. раздел 14.7.5.21.

14.7.1.9. REVOKE ROLE

REVOKE ROLE
{
auth_id [, auth_id ] ...
  | ALL ROLES
}
FROM auth_id [, auth_id ] ...
auth_id: user_name[@host_name]
Это раздел образца.

14.7.1.10. SET DEFAULT ROLE

SET DEFAULT ROLE
{NONE | ALL | role [, role ] ...}
TO role [, role ] ...
Этот запрос альтернативный синтаксис для ALTER USER ... DEFAULT ROLE (см. раздел 14.7.1.1). Это определяет, какие роли становятся активными, когда SET ROLE DEFAULT выполнен во время сеанса для каждой role немедленно после TO.

DEFAULT ROLE может иметь эти значения:

14.7.1.11. SET PASSWORD

SET PASSWORD [FOR user] = password_option
password_option: {
PASSWORD('auth_string')
  | 'auth_string'
}
SET PASSWORD назначает пароль на учетную запись пользователя MySQL, определенный как открытый текст (не зашифрован) или как зашифрованное значение:

SET PASSWORD может использоваться с или без явно названной учетной записи пользователя:

При включенной опции read_only SET PASSWORD требует привилегию SUPER.

Если FOR user дан, имя учетной записи использует формат, описанный в разделе 7.2.3. user должно быть дано как 'user_name'@'host_name' , где 'user_name' и 'host_name' точно как перечислены в столбцах User и Host строки таблицы mysql.user. Если Вы определяете только имя пользователя, имя хоста '%'. Например, чтобы установить пароль для учетной записи с User и Host соответственно 'bob' и '%.example.org':

SET PASSWORD FOR 'bob'@'%.example.org' = PASSWORD('auth_string');
Пароль может быть определен этими способами:

См. раздел 7.3.6.

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

Значение Метод хеширования пароля Связанный плагин аутентификации
0MySQL 4.1 native mysql_native_password
2SHA-256 sha256_password

Если Вы используете MySQL Replication, в настоящее время, пароль, используемый ведомым устройством в качестве части CHANGE MASTER TO ограничен 32 символами в длину, если пароль больше, любые лишние символы усечены. Это не происходит ни из-за какого предела, наложенного сервером MySQL вообще, а скорее является проблемой, определенной для MySQL Replication (см. Bug #43439).

14.7.1.12. SET ROLE

SET ROLE
{
DEFAULT
  | NONE
  | ALL
  | ALL EXCEPT role [, role ] ...
  | role [, role ] ...
}
SET ROLE изменяет эффективные привилегии текущего пользователя. Запрос разрешает эти ролевые спецификаторы:

14.7.2. Запросы обслуживания таблиц

14.7.2.1. ANALYZE TABLE

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE
tbl_name [, tbl_name] ...
ANALYZE TABLE анализирует и хранит ключевое распределение для таблицы. Во время анализа таблица заблокирована с блокировкой чтения для InnoDB и MyISAM. Этот запрос работает с InnoDB, NDB и MyISAM. Для MyISAM этот запрос эквивалентен использованию myisamchk --analyze . Этот запрос не работает с представлениями.

Для получения дополнительной информации о том, как анализ работает в пределах InnoDB см. разделы 16.6.10.1, 16.6.10.3 и 16.8.7. В частности, когда Вы включаете опцию innodb_stats_persistent, Вы должны выполнить ANALYZE TABLE после загрузки существенных данных в InnoDB или создания нового индекса.

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

Это запрос требует привилегии SELECT и INSERT на таблице.

ANALYZE TABLE поддержан для разделенных таблиц, и Вы можете использовать ALTER TABLE ... ANALYZE PARTITION, чтобы проанализировать один или более раздела, для получения дополнительной информации см. разделы 14.1.7 и 20.3.4.

ANALYZE TABLE возвращает набор результатов со следующими столбцами.

СтолбецЗначение
TableИмя таблицы
OpВсегда analyze
Msg_typestatus, error, info, note или warning
Msg_text Соответствующее информационное сообщение

Вы можете проверить сохраненное ключевое распределение с SHOW INDEX, см. раздел 14.7.5.22.

Если таблица не изменилась, начиная с последнего ANALYZE TABLE, она не проанализирована снова.

По умолчанию сервер пишет ANALYZE TABLE в двоичный журнал, чтобы они копировались к ведомым устройствам репликации. Чтобы подавить журналирование, определите дополнительное ключевое слово NO_WRITE_TO_BINLOG или его псевдоним LOCAL.

14.7.2.2. CHECK TABLE

CHECK TABLE tbl_name [, tbl_name]
      ... [option] ... option = {
FOR UPGRADE
  | QUICK
  | FAST
  | MEDIUM
  | EXTENDED
  | CHANGED
}
CHECK TABLE проверяет таблицу или таблицы на ошибки. CHECK TABLE работает для таблиц InnoDB, MyISAM, ARCHIVE и CSV. Для MyISAM ключевые статистические данные обновлены также.

Перед выполнением CHECK TABLE на InnoDB см. здесь .

Чтобы проверить таблицу, у Вас должна быть некоторая привилегия для этого.

CHECK TABLE может также проверить представления на проблемы, такие как таблицы, на которые ссылаются в определении представления, которые больше не существуют.

CHECK TABLE поддержан для разделенных таблиц, и Вы можете использовать ALTER TABLE ... CHECK PARTITION, чтобы проверять один или более разделов, для получения дополнительной информации см. разделы 14.1.7 и 20.3.4.

CHECK TABLE игнорирует произведенные виртуальные столбцы, которые не индексированы.

Вывод

CHECK TABLE возвращает набор результатов со следующими столбцами.

СтолбецЗначение
TableИмя таблицы
OpВсегда check
Msg_typestatus, error, info, note или warning
Msg_text Соответствующее информационное сообщение

Запрос может произвести много строк информации для каждой проверенной таблицы. У последней строки есть Msg_type status и Msg_text обычно должен быть OK. Если это не OK или Table is already up to date для MyISAM, Вы должны обычно выполнять ремонт таблицы. См. раздел 8.6. Table is already up to date сообщает, что механизм хранения для таблицы указал, что не было никакой потребности проверить таблицу.

Проверка совместимости вариантов

FOR UPGRADE проверяет, совместимы ли названные таблицы с текущей версией MySQL. С FOR UPGRADE сервер проверяет каждую таблицу, чтобы определить, были ли какие-либо несовместимые изменения в каком-либо из типов данных таблицы или индексе после того, как таблица была составлена. Если есть возможная несовместимость, сервер осуществляет полную проверку таблицы (которая может занять время).

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

FOR UPGRADE обнаруживает эти несовместимости:

Проверка последовательности данных

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

ТипСмысл
QUICKНе просматривать строки, чтобы проверить на неправильные ссылки. Относится к таблицам InnoDB и MyISAM и представлениям.
FASTПроверить только таблицы, которые не были закрыты должным образом. Применяется только к MyISAM таблицам и представлениям, проигнорирован для InnoDB.
CHANGEDПроверка только таблиц, которые были изменены, начиная с последней проверки или не были закрыты должным образом. Применяется только к MyISAM таблицам и представлениям, проигнорирован для InnoDB.
MEDIUMСканировать строки, чтобы проверить, которые удаленные ссылки допустимы. Это также вычисляет ключевую контрольную сумму для строк и проверяет это с расчетной контрольной суммой для ключей. Применяется только к MyISAM, проигнорирован для InnoDB.
EXTENDEDСделать полный ключевой поиск для всех ключей для каждой строки. Это гарантирует, что таблица на 100% последовательна, но занимает много времени. Применяется только к MyISAM, проигнорирован для InnoDB.

Если ни одна из опций QUICK, MEDIUM или EXTENDED не определены, тип проверки по умолчанию для динамического формата MyISAM MEDIUM . У этого есть тот же самый результат, как у myisamchk --medium-check tbl_name. Тип проверки по умолчанию также MEDIUM для статического формата MyISAM, если CHANGED или FAST заданы. В этом случае значение по умолчанию QUICK. Просмотр строки пропущен для CHANGED и FAST, так как строки очень редко повреждаются.

Вы можете объединить опции проверки, как в следующем примере, который делает быструю проверку на таблице, чтобы определить, было ли это закрыто должным образом:

CHECK TABLE test_table FAST QUICK;

Если CHECK TABLE не находит проблем с таблицей, которая отмечена как corrupted или not closed properly , CHECK TABLE может удалить метку.

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

Если Вы только хотите проверить таблицу, которую Вы считаете нормальной, Вы не должны использовать опции проверки или QUICK. Последняя должна использоваться, когда Вы спешите и можете взять на себя очень маленький риск, что QUICK не находит ошибку в файле с данными. В большинстве случаев при нормальном использовании MySQL должен найти любую ошибку в файле с данными. Если это происходит, таблица отмечена как corrupted и не может использоваться, пока она не восстановлена.

FAST и CHANGED главным образом предназначены, чтобы использоваться из скрипта (например, из cron ), если Вы хотите проверить таблицы время от времени. В большинстве случаев FAST должен быть предпочтен CHANGED. Единственный случай, когда это не так, это когда Вы подозреваете, что нашли ошибку в коде MyISAM.

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

Использование CHECK TABLE ... EXTENDED может влиять на план выполнения, произведенный оптимизатором.

Некоторые проблемы, сообщенные CHECK TABLE не могут быть исправлены автоматически:

Примечания использования CHECK TABLE с InnoDB

Следующие примечания относятся к таблицам InnoDB:

14.7.2.3. CHECKSUM TABLE

CHECKSUM TABLE tbl_name [, tbl_name]
         ... [ QUICK | EXTENDED ]
CHECKSUM TABLE сообщает контрольную сумму для содержания таблицы. Во время работы контрольной суммы таблица заблокирована с блокировкой чтения для InnoDB и MyISAM. Вы можете использовать этот запрос, чтобы проверить, что содержание то же самое прежде и после резервного копирования, отката или другой работы, которая предназначена, чтобы привести данные в известный статус. Это запрос требует привилегии SELECT для таблицы.

Этот запрос не поддержано для представлений. Если Вы выполняете CHECKSUM TABLE на представлении, значение Checksum всегда NULL и будет предупреждение.

Исполнительные соображения

По умолчанию, вся таблица читается построчно, и контрольная сумма вычислена. Для больших таблиц это может занять много времени, таким образом, Вы будете только иногда выполнять эту работу. Это вычисление аналогично тому, что Вы получаете с EXTENDED в InnoDB и всех других механизмах хранения, кроме MyISAM, а также таблицах MyISAM, не созданных с CHECKSUM=1.

Для таблиц MyISAM, созданных с CHECKSUM=1, CHECKSUM TABLE или CHECKSUM TABLE ... QUICK вернет текущую контрольную сумму таблицы, которая может быть возвращена очень быстро. Если таблица не удовлетворяет всем этим условиям, QUICK возвращает NULL. См. раздел 14.1.15.

Для несуществующей таблицы CHECKSUM TABLE вернет NULL и предупреждение.

Значение контрольной суммы зависит от формата строки таблицы. Если формат строки изменяется, контрольная сумма также изменяется. Например, формат хранения для таких временных типов, как TIME, DATETIME и TIMESTAMP изменен в MySQL 5.6, так что при обновлении таблиц с 5.5 до 5.6 значение контрольной суммы может измениться.

Если контрольные суммы для двух таблиц отличаются, то почти бесспорно, что таблицы отличаются в некотором роде. Однако, потому что хеширующая функция, используемая CHECKSUM TABLE , не гарантирована от столкновения, есть небольшой шанс, что две таблицы, которые не идентичны, могут произвести ту же самую контрольную сумму.

14.7.2.4. OPTIMIZE TABLE

OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE
tbl_name [, tbl_name] ...
Реорганизует физическое хранение табличных данных и связанных индексных данных, чтобы уменьшить место для хранения и улучшить эффективность ввода/вывода, получая доступ к таблице. Точные изменения, произведенные в каждой таблице, зависят от механизма хранения, используемого этой таблицей. Этот запрос не работает с представлениями.

Используйте OPTIMIZE TABLE в этих случаях, в зависимости от типа таблицы:

Этот запрос требует табличных привилегий SELECT и INSERT.

OPTIMIZE TABLE также поддержан для разделенных таблиц. Для информации об использовании этого запроса с разделенными таблицами см. раздел 20.3.4.

OPTIMIZE TABLE работает с таблицами InnoDB, MyISAM и ARCHIVE.

По умолчанию OPTIMIZE TABLE не работает для других механизмов хранения и возвращает результат, указывающий на это. Вы можете сделать, чтобы OPTIMIZE TABLE работал для других механизмов хранения, запуская mysqld с опцией --skip-new. В этом случае OPTIMIZE TABLE отображен на ALTER TABLE.

Детали InnoDB

Для InnoDB OPTIMIZE TABLE отображен на ALTER TABLE ... FORCE, который пересоздает таблицу, чтобы обновить индексную статистику и свободное неиспользуемое место в кластеризируемом индексе. Это выведено на экран в выводе OPTIMIZE TABLE, когда Вы выполняете это на InnoDB:

mysql> OPTIMIZE TABLE foo;
+----------+----------+----------+-------------------------------------------------------------------+
| Table    | Op       | Msg_type | Msg_text                                                          |
+----------+----------+----------+-------------------------------------------------------------------+
| test.foo | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| test.foo | optimize | status   | OK                                                                |
+----------+----------+----------+-------------------------------------------------------------------+
OPTIMIZE TABLE использует online DDL (ALGORITHM=INPLACE) для таблиц InnoDB. Это блокирует таблицу только на краткое время, что уменьшает время простоя для параллельных операций DML.

OPTIMIZE TABLE продолжает использовать ALGORITHM=COPY при следующих условиях:

OPTIMIZE TABLE, используя online DDL (ALGORITHM=INPLACE), не поддержан для таблиц InnoDB с индексами FULLTEXT. Тут нужен ALGORITHM=COPY.

InnoDB хранит данные, используя метод распределения страницы и не страдают от фрагментации, как MyISAM. Оптимизатор рассматривает рабочую нагрузку транзакций, которые обработает Ваш сервер:

Детали MyISAM

Для таблиц MyISAM OPTIMIZE TABLE работает так:

  1. Если таблица удалила или разделила строки, восстановит таблицу.

  2. Если индексные страницы не сортированы, сортирует их.
  3. Если статистические данные таблицы не современны (и ремонт не может быть достигнут, сортируя индекс), обновит их.

Другие соображения

OPTIMIZE TABLE возвращает набор результатов со следующими столбцами.

СтолбецЗначение
ТаблицаИмя таблицы
OpВсегда optimize
Msg_typestatus, error, info, note или warning
Msg_text Соответствующее информационное сообщение

Для таблиц InnoDB до 5.7.4 и других табличных типов MySQL блокирует таблицу в течение времени работы OPTIMIZE TABLE. OPTIMIZE TABLE выполнен онлайн для обычных и разделенных таблиц InnoDB.

По умолчанию сервер пишет OPTIMIZE TABLE в двоичный журнал так, чтобы они копировались к ведомым устройствам. Чтобы подавить журналирование, определите дополнительный параметр NO_WRITE_TO_BINLOG или LOCAL.

OPTIMIZE TABLE не сортирует R-дерево индекса, такое как пространственный индекс на столбцах POINT (Bug #23578).

OPTIMIZE TABLE ловит и бросает любые ошибки, которые происходят, копируя табличную статистику от старого файла в недавно созданный. Например. если пользовательский ID владельца файла .MYD или .MYI отличается от пользовательского ID процесса mysqld, OPTIMIZE TABLE производит ошибку "cannot change ownership of the file", если mysqld не запущен от имени root.

14.7.2.5. REPAIR TABLE

REPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE
tbl_name [, tbl_name] ...
[QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE восстанавливает возможно поврежденную таблицу, для определенных механизмов хранения. По умолчанию это имеет тот же самый эффект, как myisamchk --recover tbl_name. REPAIR TABLE работает для таблиц MyISAM, ARCHIVE и CSV, см. разделы 17.2 17.5 и 17.4. Этот запрос не работает с представлениями.

Нужны привилегии SELECT и INSERT на уровне таблицы.

Вы можете использовать ALTER TABLE ... REPAIR PARTITION, чтобы восстановить один или более разделов, см. разделы 14.1.7 и 20.3.4.

Хотя обычно Вам никогда не придется выполнять REPAIR TABLE, этот запрос, очень вероятно, возвратит все Ваши данные из таблицы MyISAM. Если Ваши таблицы становятся поврежденными часто, попытайтесь найти причину этого, чтобы избавиться от необходимости использовать REPAIR TABLE. См. разделы B.5.3.3 и 17.2.4.

Сделайте резервное копирование таблицы прежде, чем выполнить работу по ремонту таблицы: при некоторых обстоятельствах эта работа может вызвать потерю данных. Возможные причины включают, но не ограничены ошибками файловой системы. См. главу 8.

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

REPAIR TABLE возвращает набор результатов со следующими столбцами.

СтолбецЗначение
TableИмя таблицы
OpВсегда repair
Msg_typestatus, error, info, note или warning
Msg_text Соответствующее информационное сообщение

REPAIR TABLE может произвести много строк информации для каждой восстановленной таблицы. У последней строки есть Msg_type = status и Msg_test обычно должен быть OK. Если это не OK для таблицы MyISAM, Вы должны попытаться восстановить ее с myisamchk --safe-recover. REPAIR TABLE не осуществляет все опции myisamchk. С myisamchk --safe-recover Вы можете также использовать опции, которые не поддерживает REPAIR TABLE , например, --max-record-length.

Если Вы используете опцию QUICK, REPAIR TABLE попытается восстановить только индексный файл, а не файл с данными. Этот тип ремонта походит на myisamchk --recover --quick.

Если Вы используете опцию EXTENDED, MySQL создает индекс строку за строкой вместо того, чтобы создать индекс за один раз с сортировкой. Этот тип ремонта походит на myisamchk --safe-recover .

Опция USE_FRM доступна для использования, если индексный файл .MYI отсутствует или если его заголовок поврежден. Эта опция говорит MySQL не доверять информации из заголовка файла .MYI и обновлять это, используя информацию из словаря данных. Этот вид ремонта не может быть сделан с myisamchk.

Используйте USE_FRM только, если Вы не можете использовать обычные режимы REPAIR. Сообщение серверу проигнорировать файл .MYI делает важные табличные метаданные, сохраненные в .MYI, недоступными процессу ремонта, у этого могут быть вредные последствия:

Если USE_FRM не используется, REPAIR TABLE проверяет таблицу, чтобы видеть, требуется ли обновление. Если так, это выполняет обновление по тем же самым правилам, как CHECK TABLE ... FOR UPGRADE. См. раздел 14.7.2.2.

По умолчанию, сервер пишет REPAIR TABLE в двоичный журнал так, чтобы они копировались к ведомым устройствам. Чтобы подавить журналирование, определите дополнительный параметр NO_WRITE_TO_BINLOG или LOCAL.

Когда таблица на ведущем устройстве становится поврежденной, и Вы выполняете REPAIR TABLE, любые получающиеся изменения оригинальной таблицы не размножены ведомым устройствам.

Вы можете быть в состоянии увеличить скорость REPAIR TABLE, устанавливая определенные системные переменные. См. раздел 9.6.3.

14.7.3. Компоненты, плагины и определяемые пользователем функциональные запросы

14.7.3.1. CREATE FUNCTION

CREATE [AGGREGATE] FUNCTION function_name
       RETURNS {STRING|INTEGER|REAL|DECIMAL}
       SONAME shared_library_name
User-defined function (UDF) является способом расширить MySQL с новой функцией, которая работает как родная (встроенная) функция MySQL, например, ABS() или CONCAT().

function_name имя, которое должно использоваться в запросах SQL, чтобы вызвать функцию. RETURNS указывает на тип возвращаемого значения функции. DECIMAL допустимое значение после RETURNS, но в настоящее время DECIMAL возвращают строковые значения и должны быть написаны как STRING.

shared_library_name это базовое имя совместно используемого файла библиотеки, который содержит код, который осуществляет функцию. Файл должен быть расположен в каталоге плагинов. Этот каталог дан значением plugin_dir. См. раздел 26.4.2.5.

Чтобы создать функцию, Вы должны иметь привилегию INSERT для базы данных mysql. Это необходимо потому что CREATE FUNCTION добавляет строку к системной таблице mysql.func, которая делает запись имени функции и имени библиотеки. Если у Вас нет этой таблицы, Вы должны выполнить mysql_upgrade, чтобы создать ее. См. раздел 5.4.5.

Активная функция это та, которая была загружена CREATE FUNCTION и не удалена с DROP FUNCTION. Все активные функции перезагружены каждый раз, когда сервер запускается, если Вы не запускаете mysqld с опцией --skip-grant-tables. В этом случае инициализация UDF пропущена и UDF недоступны.

См. раздел 26.4.2. Для механизма UDF, чтобы работать, функции должны быть написаны на C или C++ (или другом языке, который может использовать соглашение вызова C), Ваша операционная система должна поддерживать динамическую загрузку, и Вы должны собрать mysqld динамически (не статически).

AGGREGATE работает точно как совокупная функция MySQL вроде SUM или COUNT() . Чтобы AGGREGATE работала, Ваша таблица mysql.func должна содержать столбец type. Если это не так, выполните mysql_upgrade (см. раздел 5.4.5.

Чтобы обновить совместно используемую библиотеку UDF, используйте DROP FUNCTION, обновите совместно используемую библиотеку, и затем скомандуйте CREATE FUNCTION. Если Вы обновляете совместно используемую библиотеку сначала и затем используете DROP FUNCTION, сервер может рухнуть.

14.7.3.2. DROP FUNCTION

DROP FUNCTION function_name
Этот запрос удаляет определяемую пользователем функцию (UDF) function_name.

Чтобы удалить функцию, Вы должны иметь привилегию DELETE для базы данных mysql. Это потому, что DROP FUNCTION удаляет строку из системной таблицы mysql.func, которая делает запись имени функции.

DROP FUNCTION также используется, чтобы удалить сохраненные функции (см. раздел 14.1.23).

14.7.3.3. INSTALL COMPONENT

INSTALL COMPONENT component_name [, component_name ] ...
Этот запрос устанавливает один или более серверных компонентов, которые становятся активными немедленно. Компонент оказывает услуги, которые доступны серверу и другим компонентам. INSTALL COMPONENT требует привилегию INSERT для таблицы mysql.component.

Служба загрузчика обрабатывает установку компонентов, а также перечисляет установленные компоненты в mysql.component, которая служит регистрацией. Для последующих перезапусков сервера любые компоненты, перечисленные в mysql.component, установлены службой загрузчика во время запуска. Это происходит, даже если сервер запущен с --skip-grant-tables (это отличается от эффекта той опции в подавлении загрузки mysql.event, mysql.func и mysql.proc).

Если компонент зависит от служб, не существующих в регистрации, и Вы пытаетесь установить компонент, также не устанавливая компонент или компоненты, которые оказывают услуги, от которых это зависит, ошибка происходит:

ERROR 3527 (HY000): Cannot satisfy dependency for service 'component1'
required by component 'component2'.
Чтобы избежать этого, устанавливайте все компоненты в том же самом запросе или устанавливайте зависимый компонент после установки любых компонентов, от которых это зависит.

Если ошибка происходит, запрос не имеет никакого эффекта. Например, это происходит, если название компонента ошибочно, названный компонент не существует или уже установлен или инициализация терпит неудачу.

В настоящее время названия компонента это URN, которые начинаются file:// и для которого следующее значение имени файла не содержит имен каталогов и задано относительно каталога, названного в переменной plugin_dir . Названия компонента не включают зависимого от платформы суффикса имени файла, например, .so или .dll. Эти детали подвержены изменениям, потому что интерпретация названия компонента самостоятельно выполнена службой, и составляющая инфраструктура позволяет заменить выполнение службы по умолчанию альтернативным выполнением.

Например:

INSTALL COMPONENT 'file://component1', 'file://component2';
См. раздел 6.5.

14.7.3.4. INSTALL PLUGIN

INSTALL PLUGIN plugin_name SONAME 'shared_library_name'
Этот запрос устанавливает плагин сервера. Это требует привилегии INSERT для таблицы mysql.plugin.

plugin_name это название плагина как определено в дескрипторной структуре, содержавшейся в файле библиотеки (см. раздел 26.2.4.2). Имена не являются чувствительными к регистру. Для максимальной совместимости имена должны быть ограничены символами ASCII, цифрами и подчеркиванием, потому что они используются в исходных файлах C и SQL.

shared_library_name название совместно используемой библиотеки, которая содержит код плагина. Имя включает расширение имени файла (например, libmyplugin.so, libmyplugin.dll или libmyplugin.dylib).

Совместно используемая библиотека должна быть расположена в каталоге плагинов (указан в plugin_dir ). Библиотека должна быть непосредственно в каталоге, не в подкаталоге. По умолчанию plugin_dir это подкаталог plugin в соответствии с каталогом, названным переменной pkglibdir, но это может быть изменено, устанавливая значение plugin_dir при запуске сервера. Например, установите ее значение в файле my.cnf:

[mysqld]
plugin_dir=/path/to/plugin/directory
Если значение plugin_dir относительный путь, это взято относительно основного каталога MySQL (значение basedir).

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

INSTALL PLUGIN также регистрирует плагин, добавляя строку, которая указывает на имя плагина и имя файла библиотеки в таблицу mysql.plugin. При запуске сервера он загружает и инициализирует любой плагин, который перечислен в mysql.plugin. Это означает, что плагин установлен с INSTALL PLUGIN , только однажды, а не каждый раз, когда сервер запускается. Загрузки плагина при запуске не происходит, если сервер запущен с опцией --skip-grant-tables.

Библиотека может содержать много плагинов. Для каждого из них используйте отдельный запрос INSTALL PLUGIN. Каждый запрос называет различный плагин, но все они определяют то же самое имя библиотеки.

INSTALL PLUGIN заставляет сервер читать файл опций (my.cnf), как во время запуска сервера. Это позволяет плагину поднять любые соответствующие опции от тех файлов. Возможно добавить опции к файлу опции даже прежде, чем загрузить плагин (если использовать префикс loose). Также возможно удалить плагин, отредактировать my.cnf и установить плагин снова. Перезапуск плагина этим путем приводит к новым значениям опции без перезапуска сервера.

Для опций, которые управляют отдельным плагином, загружающимся при запуске сервера, см. раздел 6.6.2. Если Вы должны загрузить плагины для запуска сервера, когда задана опция --skip-grant-tables (которая говорит серверу не читать системные таблицы), используйте опцию --plugin-load, см. раздел 6.1.4.

Чтобы удалить плагин, используйте запрос UNINSTALL PLUGIN.

См. раздел 6.6.2.

Чтобы видеть, какие плагины установлены, используйте SHOW PLUGINS или смотрите таблицу INFORMATION_SCHEMA.PLUGINS.

Если Вы повторно собираете библиотеку и надо повторно установить ее, Вы можете использовать любой из следующих методов:

14.7.3.5. UNINSTALL COMPONENT

UNINSTALL COMPONENT component_name [, component_name ] ...
Этот запрос дезактивирует и удаляет один или более серверных компонентов. Это требует привилегии DELETE для таблицы mysql.component. UNINSTALL COMPONENT дополнение INSTALL COMPONENT .

Служба загрузчика также разрегистрирует удаленные компоненты в A loader service also unregisters uninstalled components from mysql.component. В результате они больше не установлены во время запуска для последующих перезапусков сервера.

Если ошибка происходит, запрос не имеет никакого эффекта. Например, это происходит, если название компонента ошибочно, названный компонент не установлен или не может быть удален, потому что другие установленные компоненты зависят от этого.

См. раздел 14.7.3.3.

Пример:

UNINSTALL COMPONENT 'file://component2';
См. раздел 6.5.

14.7.3.6. UNINSTALL PLUGIN

UNINSTALL PLUGIN plugin_name
Этот запрос удаляет установленный плагин сервера. Это требует привилегию DELETE на системной таблице mysql.plugin. UNINSTALL PLUGIN дополняет INSTALL PLUGIN.

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

Вы не можете удалить плагин, если любая таблица, которая использует это, открыта.

У удаления есть значения для использования связанных таблиц. Например, если полнотекстовый плагин анализатора связан с индексом FULLTEXT таблицы, удаление плагина делает таблицу непригодной. Любая попытка получить доступ к таблице приводит к ошибке. Таблица не может даже быть открыта, таким образом, Вы не можете удалить индекс, для которого используется плагин. Это означает, что удаление плагина является чем-то, что надо делать аккуратно. Если Вы удаляете плагин без намерения повторно установить это позже, и Вы заботитесь о табличном содержании, Вы должны вывести таблицу в дамп с помощью mysqldump и удалить WITH PARSER из CREATE TABLE в дампе, чтобы Вы могли перезагрузить таблицу позже. Если Вы не заботитесь о таблице, DROP TABLE может использоваться, даже если какие-либо плагины, связанные с таблицей, отсутствуют.

См. раздел 6.6.2.

14.7.4. SET

SET имеет несколько форм:

14.7.4.1. SET для назначения переменных

SET variable_assignment [, variable_assignment] ...
variable_assignment:
  user_var_name = expr
| param_name = expr
| local_var_name = expr
| [GLOBAL | SESSION | PERSIST]
system_var_name = expr
| [@@global. | @@session. | @@persist. | @@]
system_var_name = expr
SET для назначения переменных позволяет Вам назначить значения на различные типы переменных, которые затрагивают работу сервера или клиентов:

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

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

Пользовательская переменная записана как @var_name и назначено значение выражения следующим образом:

SET @var_name = expr;
Примеры:
SET @name = 43;
SET @total_tax = (SELECT SUM(tax) FROM taxable_transactions);
Как демонстрирующийся этими запросами, expr может быть простым (буквальное значение) или более сложным (значение, возвращенное скалярным подзапросом).

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

CREATE PROCEDURE p()
BEGIN
  DECLARE counter INT DEFAULT 0;
  WHILE counter < 10 DO
    -- ... do work ...
    SET counter = counter + 1;
  END WHILE;
END;
Много системных переменных являются динамичными и могут быть изменены во время выполнения при использовании SET . Список см. в разделе 6.1.6.2. Чтобы изменить системную переменную с SET, обратитесь к этому по имени, произвольно предваренному модификатором:

Предыдущие модификаторы применяются только к системным переменным. Ошибка происходит для попыток применить их к определяемым пользователем переменным, хранимой процедуре или функциональным параметрам или местным переменным сохраненной программы.

SET может содержать многократные переменные назначения, отделенные запятыми. Этот запрос назначает значения на определяемую пользователем переменную и системную переменную:

SET @x = 1, SESSION sql_mode = '';
Если Вы устанавливаете многократные системные переменные, новый модификатор GLOBAL или SESSION в запросе используется для следующих назначений, у которых нет никакого определенного модификатора.

Примеры многократно-переменного назначения:

SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;
SET @@global.sort_buffer_size = 1000000, @@local.sort_buffer_size = 1000000;
SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;
Если любое переменное назначение в SET терпит неудачу, весь запрос терпит неудачу, никакие переменные не изменены, mysqld-auto.cnf не изменен тоже.

Если Вы меняете системную переменную сеанса, значение остается в силе в пределах Вашего сеанса, пока Вы не меняете переменную к иному значению или завершаете сеанс. Изменение не имеет никакого эффекта на другие сеансы.

Если Вы меняете глобальную системную переменную, значение используется для новых сеансов, пока Вы не меняете переменную к иному значению или не завершите сервер. Изменение видимо любому клиенту, который получает доступ к глобальной переменной. Однако, изменение затрагивает соответствующую переменную сеанса только для клиентов, которые соединяются после изменения. Изменение глобальной переменной не затрагивает переменную сеанса для любых текущих сеансов клиента (даже сеанс, в пределах которого выполнена команда SET GLOBAL).

Чтобы сделать установку глобальной системной переменной постоянной, чтобы это применилось через перезапуски сервера, измените это с помощью SET PERSIST, чтобы сделать запись в файл mysqld-auto.cnf. Также возможно использовать SET GLOBAL и вручную изменить my.cnf, но тут есть вероятность накосячить. SET PERSIST более удобно.

Чтобы установить значение GLOBAL в значение по умолчанию MySQL или соответствующее GLOBAL, установите переменную к значению DEFAULT. Например, следующие два запроса идентичны в установке значения max_join_size к текущему глобальному значению:

SET @@session.max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;
Не все системные переменные могут быть установлены в DEFAULT. В таких случаях назначение DEFAULT приводит к ошибке.

С SET PERSIST (или @@persist.), эффект установки глобальной переменной к ее значению по умолчанию является определенным версией:

Ошибка происходит для попыток назначить DEFAULT определяемым пользователем переменным, хранимой процедуре или функциональным параметрам или местным переменным сохраненной программы.

Чтобы обратиться к значению системной переменной в выражениях, используйте один из модификаторов @@. Например, Вы можете получить значения в SELECT:

SELECT @@global.sql_mode, @@session.sql_mode, @@sql_mode;
Для ссылки на системную переменную в выражении как @@var_name (вместо @@global. или @@session.) MySQL возвращает значение сеанса, если это существует и глобальное значение иначе. Это отличается от SET @@var_name = expr , который всегда обращается к значению сеанса.

@@persist. не разрешен в выражениях.

14.7.4.2. SET CHARACTER SET

SET {CHARACTER SET | CHARSET}
{charset_name | DEFAULT}
Этот запрос отображает все строки, посланные между сервером и текущим клиентом с данным отображением. SET CHARACTER SET устанавливает три системных переменные сеанса: character_set_client и character_set_results установлены в данный набор символов, и character_set_connection к значению character_set_database. См. раздел 11.1.4.

Отображение наборов символов по умолчанию может быть восстановлено при использовании значения DEFAULT. Значение по умолчанию зависит от конфигурации сервера.

ucs2, utf16 и utf32 не может использоваться в качестве набора символов клиента, что означает, что они не работают в SET CHARACTER SET.

14.7.4.3. SET NAMES

SET NAMES {'charset_name'
[COLLATE 'collation_name'] | DEFAULT}
Этот запрос устанавливает три системных переменные сеанса character_set_client , character_set_connection и character_set_results к данному набору символов. Установка character_set_connection в charset_name также установит collation_connection к сопоставлению по умолчанию для charset_name. См. раздел 11.1.4.

Дополнительный параметр COLLATE может использоваться, чтобы определить сопоставление явно. Если дано, сопоставление должно быть одним из разрешенных сопоставлений для charset_name.

Отображение значения по умолчанию может быть восстановлено при использовании значения DEFAULT. Значение по умолчанию зависит от конфигурации сервера.

ucs2, utf16 и utf32 не может использоваться в качестве набора символов клиента, что означает, что они не работают в SET NAMES.

14.7.5. SHOW

SHOW имеет много форм, которые предоставляют информацию о базах данных, таблицах, столбцах или сервере. Этот раздел описывает следующее:

SHOW {BINARY | MASTER} LOGS
SHOW BINLOG EVENTS [IN 'log_name']
     [FROM pos] [LIMIT [offset,]
     row_count]
SHOW CHARACTER SET [like_or_where]
SHOW COLLATION [like_or_where]
SHOW [FULL] COLUMNS FROM tbl_name
     [FROM db_name] [like_or_where]
SHOW CREATE DATABASE db_name
SHOW CREATE EVENT event_name
SHOW CREATE FUNCTION func_name
SHOW CREATE PROCEDURE proc_name
SHOW CREATE TABLE tbl_name
SHOW CREATE TRIGGER trigger_name
SHOW CREATE VIEW view_name
SHOW DATABASES [like_or_where]
SHOW ENGINE engine_name {STATUS | MUTEX}
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW EVENTS
SHOW FUNCTION CODE func_name
SHOW FUNCTION STATUS [like_or_where]
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW MASTER STATUS
SHOW OPEN TABLES [FROM db_name]
     [like_or_where]
SHOW PLUGINS
SHOW PROCEDURE CODE proc_name
SHOW PROCEDURE STATUS [like_or_where]
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW PROFILE [types] [FOR QUERY n]
     [OFFSET n] [LIMIT n]
SHOW PROFILES
SHOW RELAYLOG EVENTS [IN 'log_name']
     [FROM pos] [LIMIT [offset,]
     row_count]
SHOW SLAVE HOSTS
SHOW SLAVE STATUS [NONBLOCKING]
SHOW [GLOBAL | SESSION] STATUS [like_or_where]
SHOW TABLE STATUS [FROM db_name]
     [like_or_where]
SHOW [FULL] TABLES [FROM db_name]
     [like_or_where]
SHOW TRIGGERS [FROM db_name]
     [like_or_where]
SHOW [GLOBAL | SESSION] VARIABLES [like_or_where]
SHOW WARNINGS [LIMIT [offset,] row_count]
     like_or_where:
LIKE 'pattern'
  | WHERE expr
Если синтаксис для данного SHOW включает часть LIKE 'pattern', 'pattern' это строка, которая может содержать SQL-символы % и _. Образец полезен для ограничения вывода запроса соответствием значений.

Несколько SHOW также принимают WHERE, который обеспечивает больше гибкости в определении, которые строки вывести на экран. См. раздел 22.31.

Много MySQL APIs (например, PHP) позволяют обработать результат SHOW как набор результатов из SELECT, см. главу 25. Кроме того, Вы можете работать в SQL с результатами запросов на таблицах в базе данных INFORMATION_SCHEMA, которые Вы не можете легко полцить из SHOW. См. главу 22.

14.7.5.1. SHOW BINARY LOGS

SHOW BINARY LOGS
SHOW MASTER LOGS
Перечисляет двоичные файлы системного журнала на сервере. Это запрос используется как часть процедуры, описанной в разделе 14.4.1.1, которая показывает, как определить, какие журналы могут быть очищены.
mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name      | File_size |
+---------------+-----------+
| binlog.000015 | 724935    |
| binlog.000016 | 733481    |
+---------------+-----------+
SHOW MASTER LOGS эквивалент SHOW BINARY LOGS .

Нужны привилегии SUPER или REPLICATION CLIENT .

14.7.5.2. SHOW BINLOG EVENTS

SHOW BINLOG EVENTS
     [IN 'log_name'] [FROM pos]
     [LIMIT [offset,] row_count]
Показывает события в двоичном журнале. Если Вы не определяете 'log_name', первый двоичный журнал выведен на экран.

LIMIT имеет тот же самый синтаксис, что в SELECT. См. раздел 14.2.9.

SHOW BINLOG EVENTS без LIMIT может занять очень много времени и потреблять ресурс процесса, потому что сервер возвращает клиенту полное содержание двоичного журнала (который включает все запросы, выполненные сервером, которые изменяют данные). Как альтернатива SHOW BINLOG EVENTS, используйте mysqlbinlog, чтобы сохранить двоичной журнал к текстовому файлу для более поздней экспертизы и анализа. См. раздел 5.6.8.

Некоторые события, касающиеся установки пользователя и системных переменных, не включены в вывод SHOW BINLOG EVENTS. Чтобы получить полный обзор событий в пределах двоичного журнала, используйте mysqlbinlog.

SHOW BINLOG EVENTS не работает с файлами системного журнала реле. Вы можете использовать SHOW RELAYLOG EVENTS для этого.

14.7.5.3. SHOW CHARACTER SET

SHOW CHARACTER SET
     [LIKE 'pattern' | WHERE expr]
SHOW CHARACTER SET показывает все доступные наборы символов. LIKE, если дан, указывает, который набор символов соответствует. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31:
mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | cp1252 West European        | latin1_swedish_ci |  1     |
| latin2  | ISO 8859-2 Central European | latin2_general_ci |  1     |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |  1     |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci |  1     |
+---------+-----------------------------+-------------------+--------+
Maxlen показывает максимальное количество байтов, требуемых, чтобы сохранить один символ.

filename набора символов только для внутреннего пользования, SHOW CHARACTER SET не выводит его на экран.

Вы можете также получить информацию о наборах символов из INFORMATION_SCHEMA, которая содержит таблицу CHARACTER_SETS. См. раздел 22.1.

14.7.5.4. SHOW COLLATION

SHOW COLLATION
[LIKE 'pattern' | WHERE expr]
Этот запрос перечисляет сопоставления, поддержанные сервером. По умолчанию вывод SHOW COLLATION включает все доступные сопоставления. LIKE, если есть, указывает, которое сопоставление соответствует. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31:
mysql> SHOW COLLATION WHERE Charset = 'latin1';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         | Yes      |       1 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       1 |
| latin1_danish_ci  | latin1  | 15 |         | Yes      |       1 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       1 |
| latin1_general_ci | latin1  | 48 |         | Yes      |       1 |
| latin1_general_cs | latin1  | 49 |         | Yes      |       1 |
| latin1_spanish_ci | latin1  | 94 |         | Yes      |       1 |
+-------------------+---------+----+---------+----------+---------+
Столбцы Collation и Charset указывают на названия сопоставления и набора символов, с которым оно связано. Id ID сопоставления. Default указывает, является ли сопоставление значением по умолчанию для своего набора символов. Compiled указывает, собран ли набор символов в сервер. Sortlen связан с суммой памяти, требуемой, чтобы сортировать строки, выраженные в наборе символов.

Чтобы видеть сопоставление по умолчанию для каждого набора символов, используйте следующий запрос. Default это зарезервированное слово, чтобы использовать это в качестве идентификатора, это должно быть заключено в кавычки:

mysql> SHOW COLLATION WHERE `Default` = 'Yes';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| big5_chinese_ci   | big5    |  1 | Yes     | Yes      |      1  |
| dec8_swedish_ci   | dec8    |  3 | Yes     | Yes      |      1  |
| cp850_general_ci  | cp850   |  4 | Yes     | Yes      |      1  |
| hp8_english_ci    | hp8     |  6 | Yes     | Yes      |      1  |
| koi8r_general_ci  | koi8r   |  7 | Yes     | Yes      |      1  |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |      1  |
...
Вы можете также получить информацию о сопоставлениях из INFORMATION_SCHEMA, которая содержит таблицу COLLATIONS, см. раздел 22.2.

14.7.5.5. SHOW COLUMNS

SHOW [FULL] COLUMNS {FROM | IN} tbl_name
     [{FROM | IN} db_name]
     [LIKE 'pattern' | WHERE expr]
SHOW COLUMNS показывает сведения о столбцах в данной таблице. Это также работает на представлениях. LIKE, если есть, указывает, которые имена столбцов соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

SHOW COLUMNS покажет сведения только для тех столбцов, для которых у Вас есть некоторая привилегия.

mysql> SHOW COLUMNS FROM City;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
Если типы данных отличаются от того, что Вы ожидаете, что они будут основаны на CREATE TABLE, отметьте, что MySQL иногда изменяет типы данных, когда Вы создаете или изменяете таблицу. Условия, при которых это происходит, описаны в раздел 14.1.15.4.

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

Вы можете использовать db_name.tbl_name как альтернативу tbl_name FROM db_name. Другими словами, эти два запроса эквивалентны:

mysql> SHOW COLUMNS FROM mytable FROM mydb;
mysql> SHOW COLUMNS FROM mydb.mytable;
SHOW COLUMNS покажет следующие значения для каждого столбца таблицы:

Field имя столбца.

Type тип данных столбца.

Collation указывает на сопоставление для недвоичных строковых столбцов или NULL для других столбцов. Это значение выведено на экран, только если Вы используете FULL.

Поле Null содержит YES, если значения NULL могут быть сохранены в столбце, NO если нет.

Поле Key указывает, индексирован ли столбец:

Если больше, чем одно из значений Key относится к данному столбцу таблицы, Key выводит на экран значение с самым высоким приоритетом, в порядке PRI, UNI, MUL.

Индекс UNIQUE может быть выведен на экран как PRI, если это не может содержать NULL и нет PRIMARY KEY в таблице. UNIQUE может вывести на экран как MUL, если несколько столбцов формируют композитный индекс UNIQUE, хотя комбинация столбцов уникальна, каждый столбец все еще может содержать многократные возникновения данного значения.

Поле Default указывает на значение по умолчанию, которое назначено столбцу. Это NULL, если у столбца есть явное значение по умолчанию NULL, или если определение столбца не имеет DEFAULT.

Поле Extra содержит любую дополнительную информацию, которая доступна о данном столбце. Значение не пусто в этих случаях:

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

Comment указывает на любой комментарий, который имеет столбец. Это значение выведено на экран, только если Вы используете FULL.

SHOW FIELDS синоним для SHOW COLUMNS. Вы можете также перечислить столбцы таблицы с помощью mysqlshow db_name tbl_name .

DESCRIBE предоставляет информацию, подобную SHOW COLUMNS. См. раздел 14.8.1.

SHOW CREATE TABLE, SHOW TABLE STATUS и SHOW INDEX также предоставляют информацию о таблицах. См. раздел 14.7.5.

14.7.5.6 SHOW CREATE DATABASE

SHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
Показывает запрос CREATE DATABASE , который создает названную базу данных. Если SHOW включает IF NOT EXISTS, вывод также включает такой пункт. SHOW CREATE SCHEMA синоним для SHOW CREATE DATABASE .
mysql> SHOW CREATE DATABASE test\G
*************************** 1. row ***************************
   Database: test
Create Database: CREATE DATABASE `test`
 /*!40100 DEFAULT CHARACTER SET latin1 */

mysql> SHOW CREATE SCHEMA test\G
*************************** 1. row ***************************
   Database: test
Create Database: CREATE DATABASE `test`
 /*!40100 DEFAULT CHARACTER SET latin1 */
SHOW CREATE DATABASE берет в кавычки имена таблиц и имена столбцов согласно значению опции sql_quote_show_create . См. раздел 6.1.5 .

14.7.5.7. SHOW CREATE EVENT

SHOW CREATE EVENT event_name
Отображает CREATE EVENT, который должен был обновить данное событие. Это требует привилегии requires the EVENT для базы данных, из которой нужно показать событие. Например (используя то же самое событие e_daily, которое использовано в then altered in разделе 14.7.5.18):
mysql> SHOW CREATE EVENT test.e_daily\G
*************************** 1. row ***************************
   Event: e_daily
sql_mode:
   time_zone: SYSTEM
Create Event: CREATE EVENT `e_daily`
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR
ON COMPLETION NOT PRESERVE
ENABLE
COMMENT 'Saves total number of sessions then
clears the table each day'
DO BEGIN
  INSERT INTO site_activity.totals (time, total)
SELECT CURRENT_TIMESTAMP, COUNT(*)
FROM site_activity.sessions;
  DELETE FROM site_activity.sessions;
END
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: latin1_swedish_ci
character_set_client это сессионное значение переменной character_set_client , когда событие создавалось collation_connection сессионное значение переменной collation_connection , когда событие создавалось. Database Collation сопоставление базы данных, с которой связано событие.

Вывод отражает текущий статус события (ENABLE) вместо состояния, с которым это создавалось.

14.7.5.8. SHOW CREATE FUNCTION

SHOW CREATE FUNCTION func_name
Этоь запрос подобен SHOW CREATE PROCEDURE, но для сохраненных функций. См. раздел 14.7.5.9.

14.7.5.9. SHOW CREATE PROCEDURE

SHOW CREATE PROCEDURE proc_name
Этот запрос расширение MySQL. Это возвращает точную строку, которая может использоваться, чтобы обновить названную хранимую процедуру. Подобный запрос, SHOW CREATE FUNCTION, дает информацию о сохраненных функциях (см. раздел 14.7.5.8).

Чтобы использовать любой запрос, Вы должны быть пользователем, названным в подпрограмме DEFINER или иметь доступ SELECT к таблице mysql.proc. Если у Вас нет привилегий для подпрограммы непосредственно, значение для полей Create Procedure или < code>Create Function будет NULL.

mysql> SHOW CREATE PROCEDURE test.simpleproc\G
*************************** 1. row ***************************
   Procedure: simpleproc
sql_mode:
Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)
  BEGIN
  SELECT COUNT(*) INTO param1 FROM t;
  END
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: latin1_swedish_ci

mysql> SHOW CREATE FUNCTION test.hello\G
*************************** 1. row ***************************
Function: hello
sql_mode:
 Create Function: CREATE FUNCTION `hello`(s CHAR(20))
  RETURNS CHAR(50)
  RETURN CONCAT('Hello, ',s,'!')
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: latin1_swedish_ci
character_set_client значение сеанса the character_set_client, когда подпрограмма создавалась. collation_connection значение сеанса collation_connection, когда подпрограмма создавалась. Database Collation сопоставление базы данных, с которой связана подпрограмма.

14.7.5.10. SHOW CREATE TABLE

SHOW CREATE TABLE tbl_name
Показывает CREATE TABLE, который составляет названную таблицу. Чтобы использовать этот запрос, у Вас должна быть некоторая привилегия для таблицы. Этот запрос также работает с представлениями.
mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
   Table: t
Create Table: CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `s` char(60) DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW CREATE TABLE цитирует имена таблиц и столбцов согласно значению опции sql_quote_show_create . См. раздел 6.1.5 .

14.7.5.11. SHOW CREATE TRIGGER

SHOW CREATE TRIGGER trigger_name
Это запрос показывает запрос CREATE TRIGGER, который создает названный триггер. Это запрос требует привилегию TRIGGER для таблицы, связанной с триггером.
mysql> SHOW CREATE TRIGGER ins_sum\G
*************************** 1. row ***************************
   Trigger: ins_sum
  sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
SQL Original Statement: CREATE DEFINER=`me`@`localhost` TRIGGER ins_sum
BEFORE INSERT ON account
FOR EACH ROW SET @sum = @sum + NEW.amount
  character_set_client: utf8
  collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
   Created: 2013-07-09 10:39:34.96
Вывод SHOW CREATE TRIGGER имеет следующие столбцы:

Вы можете также получить информацию из INFORMATION_SCHEMA, которая имеет таблицу TRIGGERS, см. раздел 22.27.

14.7.5.12. SHOW CREATE USER

SHOW CREATE USER user
Этот запрос показывает CREATE USER, которое создает названного пользователя. Ошибка происходит, если пользователь не существует. Запрос требует привилегию SELECT для базы данных mysql, кроме просмотра привилегий для текущего пользователя.

Чтобы назвать учетную запись, используйте формат, описанный в разделе 7.2.3. Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'. Также возможно определить CURRENT_USER или CURRENT_USER(), чтобы ссылаться на учетную запись, связанную с текущим сеансом.

mysql> SHOW CREATE USER 'root'@'localhost'\G
*************************** 1. row ***************************
CREATE USER for root@localhost: CREATE USER 'root'@'localhost'
       IDENTIFIED WITH 'mysql_native_password'
       AS '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
       REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
Выходной формат затронут установкой log_builtin_as_identified_by_password.

Чтобы вывести на экран привилегии, предоставленные учетной записи, используйте SHOW GRANTS, см. раздел 14.7.5.21.

14.7.5.13. SHOW CREATE VIEW

SHOW CREATE VIEW view_name
Этот запрос показывает CREATE VIEW , который создает названное представление.
mysql> SHOW CREATE VIEW v\G
*************************** 1. row ***************************
View: v
 Create View: CREATE ALGORITHM=UNDEFINED
  DEFINER=`bob`@`localhost`
  SQL SECURITY DEFINER VIEW `v` AS select 1 AS `a`,2 AS `b`
character_set_client: latin1
collation_connection: latin1_swedish_ci
character_set_client значение сеанса character_set_client , когда представление создавалось. collation_connection значение сеанса collation_connection , когда представление создавалось.

Использование SHOW CREATE VIEW требует привилегии SHOW VIEW и SELECT для рассматриваемого представления.

Вы можете также получить информацию об объектах представления из базы данных INFORMATION_SCHEMA, таблица VIEWS, см. раздел 22.29.

MySQL позволяет Вам использовать отличающийся sql_mode, чтобы сказать серверу тип синтаксиса SQL. Например, Вы могли бы использовать режим SQL ANSI, чтобы гарантировать, что MySQL правильно интерпретирует стандартный оператор связи SQL, двойную черту (||), в Ваших запросах. Если Вы тогда создаете представление, которое связывает элементы, Вы могли бы поменять sql_mode на значение, отличающееся от ANSI , а это может заставить представление становиться недопустимым. Но дело обстоит не так. Независимо от того, как Вы описываете определение представления, MySQL всегда хранит это одинаково, в канонической форме. Вот пример, который показывает, как сервер изменяет оператор связи на функцию CONCAT():

mysql> SET sql_mode = 'ANSI';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE VIEW test.v AS SELECT 'a' || 'b' as col1;
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW CREATE VIEW test.v\G
*************************** 1. row ***************************
View: v
 Create View: CREATE VIEW "v" AS select concat('a','b') AS "col1"
...
1 row in set (0.00 sec)
Преимущество хранения определения представления в канонической форме состоит в том что изменения, произведенные позже в значении sql_mode не будут затрагивать работу представления. Однако дополнительное последствие то, что комментарии до SELECT исключены из определения сервером.

14.7.5.14. SHOW DATABASES

SHOW {DATABASES | SCHEMAS}
[LIKE 'pattern' | WHERE expr]
SHOW DATABASES перечисляет базы данных по узлу сервера MySQL. SHOW SCHEMAS синоним для SHOW DATABASES. LIKE, если есть, указывает, которые имена базы данных должны соответствовать. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

Вы видите только те базы данных, для которых у Вас есть некоторая привилегия, если у Вас нет глобальной привилегии SHOW DATABASES. Вы можете также получить этот список, используя mysqlshow.

Если сервер был запущен с опцией --skip-show-database, Вы не можете использовать это запрос вообще, если Вы не имеете привилегии SHOW DATABASES.

MySQL осуществляет базы данных как подкаталоги в каталоге данных, таким образом, этот запрос просто перечисляет каталоги. Однако, вывод может включать названия каталогов, которые не соответствуют фактическим базам данных.

14.7.5.15. SHOW ENGINE

SHOW ENGINE engine_name {STATUS | MUTEX}
SHOW ENGINE выводит на экран операционную информацию о механизме хранения. Это требует привилегии PROCESS. У запроса есть эти разновидности:
SHOW ENGINE INNODB STATUS
SHOW ENGINE INNODB MUTEX
SHOW ENGINE PERFORMANCE_SCHEMA STATUS
SHOW ENGINE INNODB STATUS выводит на экран обширную информацию от стандартного InnoDB Monitor о статусе механизма хранения InnoDB. См. раздел 16.16.

SHOW ENGINE INNODB MUTEX отображает статистику InnoDB mutex и rw-lock.

InnoDB mutexes и rwlocks можно также отследить по таблицам в Performance Schema, см. раздел 16.15.2.

Набор статистики Mutex сконфигурирован динамически, используя следующие опции:

Сбор mutex статистики для SHOW ENGINE INNODB MUTEX может также быть включен, устанавливая innodb_monitor_enable='all' или выключен, устанавливая innodb_monitor_disable='all'.

Вывод SHOW ENGINE INNODB MUTEX включает следующие столбцы:

SHOW ENGINE INNODB MUTEX пропускает mutexes и rw-locks блоков буферного пула, поскольку количество вывода может быть подавляющим на системах с большим буферным пулом. Есть один mutex и одна rw-блокировка в каждом 16K буферном блоке пула и 65536 блоков на каждый гигабайт. SHOW ENGINE INNODB MUTEX также не перечисляет mutex или rw-блокировки, которые никогда не ждали (os_waits=0). Таким образом, SHOW ENGINE INNODB MUTEX покажет только информацию о mutex и rw-locks за пределами буферного пула, которые вызвали по крайней мере одно ожидание на уровне OS.

Использовать SHOW ENGINE PERFORMANCE_SCHEMA STATUS, чтобы смотреть внутренние операции кода Performance Schema:

mysql> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\G
...
*************************** 3. row ***************************
  Type: performance_schema
  Name: events_waits_history.size
Status: 76
*************************** 4. row ***************************
  Type: performance_schema
  Name: events_waits_history.count
Status: 10000
*************************** 5. row ***************************
  Type: performance_schema
  Name: events_waits_history.memory
Status: 760000
...
*************************** 57. row ***************************
  Type: performance_schema
  Name: performance_schema.memory
Status: 26459600
...
Этот запрос предназначен, чтобы помочь DBA понять эффекты, которые различные опции Performance Schema имеют на требования к памяти.

Name состоят из двух частей, которые называют внутренний буфер и буферный признак, соответственно. Интерпретируйте буферные имена следующим образом:

У буферных признаков есть эти значения:

В некоторых случаях есть непосредственная связь между параметром конфигурации Performance Schema и SHOW ENGINE. Например, events_waits_history_long.count соответствует performance_schema_events_waits_history_long_size. В других случаях отношения более сложны. Например, events_waits_history.count соответствует performance_schema_events_waits_history_size (число строк на поток) умноженный на performance_schema_max_thread_instances (число потоков).

14.7.5.16. SHOW ENGINES

SHOW [STORAGE] ENGINES
SHOW ENGINES показывает информацию о статусе механизмов хранения сервера. Это особенно полезно для проверки, поддержан ли механизм хранения, или чтобы увидеть, каков механизм по умолчанию. Эта информация может также быть получена из INFORMATION_SCHEMA (таблица ENGINES), см. раздел 22.6.
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
  Engine: InnoDB
 Support: DEFAULT
 Comment: Supports transactions, row-level locking и foreign keys
Transactions: YES
  XA: YES
  Savepoints: YES
*************************** 2. row ***************************
  Engine: MRG_MYISAM
 Support: YES
 Comment: Collection of identical MyISAM tables
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 3. row ***************************
  Engine: MEMORY
 Support: YES
 Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 4. row ***************************
  Engine: BLACKHOLE
 Support: YES
 Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 5. row ***************************
  Engine: MyISAM
 Support: YES
 Comment: MyISAM storage engine
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 6. row ***************************
  Engine: CSV
 Support: YES
 Comment: CSV storage engine
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 7. row ***************************
  Engine: ARCHIVE
 Support: YES
 Comment: Archive storage engine
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 8. row ***************************
  Engine: PERFORMANCE_SCHEMA
 Support: YES
 Comment: Performance Schema
Transactions: NO
  XA: NO
  Savepoints: NO
*************************** 9. row ***************************
  Engine: FEDERATED
 Support: YES
 Comment: Federated MySQL storage engine
Transactions: NO
  XA: NO
  Savepoints: NO
Вывод SHOW ENGINES может измениться, согласно версии MySQL и другим факторам. Значения, показанные в столбце Support, указывают на уровень поддержки сервером механизма хранения, как показано в следующей таблице.

ЗначениеСмысл
YES Механизм поддержан и активный.
DEFAULT Like YES, но это механизм по умолчанию.
NOМеханизм не поддержан.
DISABLED Механизм поддержан, но был отключен.

NO значит, что сервер был собран без поддержки механизма, таким образом, это не может быть включено во время выполнения.

DISABLED происходит потому, что сервер был запущен с опциями, которые отключает механизм, или потому что не все опции, необходимые, чтобы включить это, были даны. В последнем случае файл журнала ошибок должен содержать причину, указывающую, почему опция отключена. См. раздел 6.4.2.

Вы могли бы также видеть DISABLED для механизма хранения, если сервер был собран, чтобы поддержать это, но был запущен с опцией --skip-engine_name.

Все MySQL поддерживают MyISAM. Невозможно отключить MyISAM.

Столбцы Transactions, XA и Savepoints указывают, поддерживает ли механизм хранения транзакции, транзакции XA и точки сохранения, соответственно.

14.7.5.17. SHOW ERRORS

SHOW ERRORS [LIMIT [offset,] row_count]
SHOW COUNT(*) ERRORS
SHOW ERRORS это диагностический запрос, который подобен SHOW WARNINGS, за исключением того, что это выводит на экран информацию только для ошибок, а не для ошибок, предупреждений и примечаний.

LIMIT аналогичен соответствующему параметру в SELECT. См. раздел 14.2.9.

SHOW COUNT(*) ERRORS выводит на экран число ошибок. Вы можете также получить это число из переменной error_count :

SHOW COUNT(*) ERRORS;
SELECT @@error_count;
SHOW ERRORS и error_count относятся только к ошибкам, не предупреждениям или примечаниям. В других отношениях они подобны SHOW WARNINGS и warning_count . В частности, SHOW ERRORS не может вывести на экран информацию больше, чем max_error_count сообщений, и error_count может превысить значение max_error_count, если число ошибок превышает max_error_count.

См. раздел 14.7.5.40.

14.7.5.18. SHOW EVENTS

SHOW EVENTS [{FROM | IN} schema_name]
[LIKE 'pattern' | WHERE expr]
Этот запрос выводит на экран информацию о событиях Event Manager. Нужна привилегия EVENT для базы данных, из которой нужно показать события.

В его самой простой форме SHOW EVENTS перечисляет все события в текущей схеме:

mysql> SELECT CURRENT_USER(), SCHEMA();
+----------------+----------+
| CURRENT_USER() | SCHEMA() |
+----------------+----------+
| jon@ghidora    | myschema |
+----------------+----------+
1 row in set (0.00 sec)

mysql> SHOW EVENTS\G
*************************** 1. row ***************************
  Db: myschema
Name: e_daily
 Definer: jon@ghidora
   Time zone: SYSTEM
Type: RECURRING
  Execute at: NULL
  Interval value: 10
  Interval field: SECOND
  Starts: 2006-02-09 10:41:23
Ends: NULL
  Status: ENABLED
  Originator: 0
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: latin1_swedish_ci
Чтобы видеть события для определенной схемы, используйте FROM. Например, чтобы видеть события для схемы test, используйте следующий запрос:
SHOW EVENTS FROM test;
LIKE, если есть, указывает, которые события соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

Вывод SHOW EVENTS имеет следующие столбцы:

См. раздел 19.4.1.12 .

Запрос действия событий не показывают в выводе SHOW EVENTS. Используйте SHOW CREATE EVENT или таблицу INFORMATION_SCHEMA.EVENTS .

Времена, выведенные на экран SHOW EVENTS, даны в часовом поясе, как обсуждено в разделе 21.4.4.

Столбцы в выводе SHOW EVENTS подобны, но не идентичны столбцам в таблице INFORMATION_SCHEMA.EVENTS. См. раздел 22.7.

14.7.5.19. SHOW FUNCTION CODE

SHOW FUNCTION CODE func_name
Этот запрос подобен SHOW PROCEDURE CODE, но для сохраненных функций. См. раздел 14.7.5.27.

14.7.5.20. SHOW FUNCTION STATUS

SHOW FUNCTION STATUS
     [LIKE 'pattern'
     | WHERE expr]
Этот запрос подобен SHOW PROCEDURE STATUS, но для сохраненных функций. См. раздел 14.7.5.28.

14.7.5.21. SHOW GRANTS

SHOW GRANTS [FOR user
     [USING user
     [, user] ...]]
Этот запрос выводит на экран запрос или запросы GRANT, которые должны быть сделаны, чтобы дублировать привилегии, которые предоставляют учетной записи пользователя MySQL. SHOW GRANTS требует привилегии SELECT для базы данных mysql, кроме просмотра привилегии для текущего пользователя.

Чтобы назвать учетную запись, используйте тот же самый формат, что в GRANT, например, 'jeffrey'@'localhost'. Если Вы определяете только часть имени пользователя имени учетной записи, часть имени хоста '%'. См. раздел 14.7.1.6.

mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
Чтобы вывести на экран привилегии, предоставленные учетной записи, которую Вы используете, чтобы соединиться с сервером, Вы можете использовать любой из следующих запросов:
SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();
Если SHOW GRANTS FOR CURRENT_USER (или любой из эквивалентных синтаксисов), используется в DEFINER, например, в пределах хранимой процедуры, которая определена с SQL SECURITY DEFINER), выведенные на экран привилегии являются таковыми из definer, а не invoker.

С USING SHOW GRANTS позволяет Вам исследовать привилегии, связанные с ролями для пользователя. Каждую роль, названную в пункте, нужно предоставить пользователю.

Если Вы не выводите на экран информацию для своей собственной учетной записи, USING требует привилегию SUPER.

Предположите, что пользователю u1 назначены роли r1 и r2:

CREATE ROLE 'r1', 'r2';
GRANT SELECT ON db1.* TO 'r1';
GRANT INSERT, UPDATE, DELETE ON db1.* TO 'r2';
CREATE USER 'u1'@'localhost' IDENTIFIED BY 'u1pass';
GRANT 'r1', 'r2' TO 'u1'@'localhost';
SHOW GRANTS без USING показывает предоставленные роли:
mysql> SHOW GRANTS FOR 'u1'@'localhost';
+---------------------------------------------+
| Grants for u1@localhost                     |
+---------------------------------------------+
| GRANT USAGE ON *.* TO `u1`@`localhost`      |
| GRANT `r1`@`%`,`r2`@`%` TO `u1`@`localhost` |
+---------------------------------------------+
Добавление USING заставляет запрос также выводить на экран привилегии, связанные с каждой названной ролью:
mysql> SHOW GRANTS FOR 'u1'@'localhost' USING 'r1';
+---------------------------------------------+
| Grants for u1@localhost                     |
+---------------------------------------------+
| GRANT USAGE ON *.* TO `u1`@`localhost`      |
| GRANT SELECT ON `db1`.* TO `u1`@`localhost` |
| GRANT `r1`@`%`,`r2`@`%` TO `u1`@`localhost` |
+---------------------------------------------+
mysql> SHOW GRANTS FOR 'u1'@'localhost' USING 'r2';
+-------------------------------------------------------------+
| Grants for u1@localhost                                     |
+-------------------------------------------------------------+
| GRANT USAGE ON *.* TO `u1`@`localhost`                      |
| GRANT INSERT, UPDATE, DELETE ON `db1`.* TO `u1`@`localhost` |
| GRANT `r1`@`%`,`r2`@`%` TO `u1`@`localhost`                 |
+-------------------------------------------------------------+
mysql> SHOW GRANTS FOR 'u1'@'localhost' USING 'r1', 'r2';
+---------------------------------------------------------------------+
| Grants for u1@localhost                                             |
+---------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `u1`@`localhost`                              |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `db1`.* TO `u1`@`localhost` |
| GRANT `r1`@`%`,`r2`@`%` TO `u1`@`localhost`                         |
+---------------------------------------------------------------------+
SHOW GRANTS покажет только привилегии, предоставленные явно названной учетной записи. Другие привилегии, которые могли бы быть доступными учетной записи, не выведены на экран. Например, если анонимная учетная запись существует, названная учетная запись могла бы быть в состоянии использовать свои привилегии, но SHOW GRANTS не будет их показывать.

Чтобы вывести на экран информацию не о привилегиях для учетных записей MySQL, используйте SHOW CREATE USER , см. раздел 14.7.5.12.

14.7.5.22. SHOW INDEX

SHOW {INDEX | INDEXES | KEYS}
{FROM | IN} tbl_name
[{FROM | IN} db_name]
[WHERE expr]
SHOW INDEX возвращает индексную информацию. Формат напоминает формат SQLStatistics в ODBC. Это запрос требует некоторой привилегии для любого столбца в таблице.

SHOW INDEX возвращает следующие поля:

Вы можете использовать db_name.tbl_name как альтернативу tbl_name FROM db_name. Эти два запросы эквивалентны:

SHOW INDEX FROM mytable FROM mydb;
SHOW INDEX FROM mydb.mytable;
WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в раздел 22.31.

Вы можете также перечислить индексы таблицы с mysqlshow -k db_name tbl_name.

14.7.5.23. SHOW MASTER STATUS

SHOW MASTER STATUS
Этот запрос обеспечивает информацию о статусе двоичных файлов системного журнала ведущего устройства. Это требует любой привилегии SUPER или REPLICATION CLIENT .

Пример:

mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
 File: master-bin.000002
 Position: 1307
 Binlog_Do_DB: test
 Binlog_Ignore_DB: manual, mysql
Executed_Gtid_Set: 3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
1 row in set (0.00 sec)
Когда глобальные операционные ID используются, Executed_Gtid_Set показывает набор GTID для транзакций, которые были выполнены на ведущем устройстве. Это то же самое, как значение gtid_executed на этом сервере, так же как значение Executed_Gtid_Set в выводе SHOW SLAVE STATUS на этом сервере.

14.7.5.24. SHOW OPEN TABLES

SHOW OPEN TABLES [{FROM | IN} db_name]
[LIKE 'pattern' | WHERE expr]
SHOW OPEN TABLES перечисляет не-TEMPORARY таблицы, которые в настоящее время открыты в табличном кэше. См. раздел 9.4.3.1. FROM, если есть, ограничивает таблицы существующими в db_name. LIKE, если есть, указывает, которые имена таблиц соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

SHOW OPEN TABLES имеет следующие столбцы:

Если у Вас нет никаких привилегий для таблицы, она не показана в выводе SHOW OPEN TABLES.

14.7.5.25. SHOW PLUGINS

SHOW PLUGINS
SHOW PLUGINS показывает информацию о плагинах сервера. Эта информация также доступна в таблице INFORMATION_SCHEMA.PLUGINS, см. раздел 22.15.

Пример вывода SHOW PLUGINS :

mysql> SHOW PLUGINS\G
*************************** 1. row ***************************
   Name: binlog
 Status: ACTIVE
   Type: STORAGE ENGINE
Library: NULL
License: GPL
*************************** 2. row ***************************
   Name: CSV
 Status: ACTIVE
   Type: STORAGE ENGINE
Library: NULL
License: GPL
*************************** 3. row ***************************
   Name: MEMORY
 Status: ACTIVE
   Type: STORAGE ENGINE
Library: NULL
License: GPL
*************************** 4. row ***************************
   Name: MyISAM
 Status: ACTIVE
   Type: STORAGE ENGINE
Library: NULL
License: GPL
...
Столбцы вывода SHOW PLUGINS:

Для плагинов, установленных с INSTALL PLUGIN, Name и Library также зарегистрированы в таблице mysql.plugin.

Для информации о структурах данных, которые формируют информацию, выведенную на экран SHOW PLUGINS , см. раздел 26.2.

14.7.5.26. SHOW PRIVILEGES

SHOW PRIVILEGES
SHOW PRIVILEGES показывает список системных привилегий, которые сервер MySQL поддерживает. Точный список привилегий зависит от версии Вашего сервера.
mysql> SHOW PRIVILEGES\G
*************************** 1. row ***************************
Privilege: Alter
  Context: Tables
  Comment: To alter the table
*************************** 2. row ***************************
Privilege: Alter routine
  Context: Functions,Procedures
  Comment: To alter or drop stored functions/procedures
*************************** 3. row ***************************
Privilege: Create
  Context: Databases,Tables,Indexes
  Comment: To create new databases and tables
*************************** 4. row ***************************
Privilege: Create routine
  Context: Databases
  Comment: To use CREATE FUNCTION/PROCEDURE
*************************** 5. row ***************************
Privilege: Create temporary tables
  Context: Databases
  Comment: To use CREATE TEMPORARY TABLE
...
Привилегии, принадлежащие определенному пользователю, выведены на экран SHOW GRANTS, см. раздел 14.7.5.21.

14.7.5.27. SHOW PROCEDURE CODE

SHOW PROCEDURE CODE proc_name
Этот запрос расширение MySQL, которое доступно только для серверов, которые были созданы с поддержкой отладки. Это выводит на экран представление внутреннего выполнения названной хранимой процедуры. Подобный запрос SHOW FUNCTION CODE, показывает информацию о сохраненных функциях (см. раздел 14.7.5.19).

Чтобы использовать запрос, Вы должны быть владельцем подпрограммы или иметь привилегию SELECT на таблице mysql.proc.

Если названная подпрограмма доступна, запрос производит набор результатов. Каждая строка в наборе результатов соответствует одной инструкции в подпрограмме. Первый столбец Pos, который является порядковым числом, начинающимся с 0. Второй столбец Instruction содержит запрос SQL (обычно измененный от первоисточника) или директиву, у которой есть значение только в обработчике сохраненной подпрограммы.

mysql> DELIMITER //
mysql> CREATE PROCEDURE p1 ()
    -> BEGIN
    ->   DECLARE fanta INT DEFAULT 55;
    ->   DROP TABLE t2;
    ->   LOOP
    ->     INSERT INTO t3 VALUES (fanta);
    ->   END LOOP;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW PROCEDURE CODE p1//
+-----+----------------------------------------+
| Pos | Instruction                            |
+-----+----------------------------------------+
|   0 | set fanta@0 55                         |
|   1 | stmt 9 "DROP TABLE t2"                 |
|   2 | stmt 5 "INSERT INTO t3 VALUES (fanta)" |
|   3 | jump 2                                 |
+-----+----------------------------------------+
4 rows in set (0.00 sec)
В этом примере невыполняемые запросы BEGIN и END исчезли, и для DECLARE variable_name появляется только выполнимая часть (часть, где значение по умолчанию назначено). Для каждого запроса, который взят из источника, есть кодовое слово stmt сопровождаемое типом (9 DROP, 5 INSERT). Заключительная строка содержит инструкцию jump 2 со значением GOTO instruction #2.

14.7.5.28. SHOW PROCEDURE STATUS

SHOW PROCEDURE STATUS
     [LIKE 'pattern' | WHERE expr]
Этот запрос расширение MySQL. Это возвращает характеристики хранимой процедуры, такие как база данных, имя, тип, создатель, даты создания и модификации и информация о наборе символов. Подобный запрос, SHOW FUNCTION STATUS, покажет информацию о сохраненных функциях (см. раздел 14.7.5.20).

LIKE, если есть, указывает, которые имена процедур или функций соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

mysql> SHOW PROCEDURE STATUS LIKE 'sp1'\G
*************************** 1. row ***************************
  Db: test
Name: sp1
Type: PROCEDURE
 Definer: testuser@localhost
Modified: 2004-08-03 15:29:37
 Created: 2004-08-03 15:29:37
   Security_type: DEFINER
 Comment:
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: latin1_swedish_ci
character_set_client сессионное значение переменной character_set_client , когда подпрограмма создавалась. collation_connection сессионное значение переменной collation_connection, когда подпрограмма создавалась. Database Collation сопоставление базы данных, с которой связана подпрограмма.

Вы можете также получить информацию о сохраненных подпрограммах из таблицы ROUTINES в INFORMATION_SCHEMA. См. раздел 22.19.

14.7.5.29. SHOW PROCESSLIST

SHOW [FULL] PROCESSLIST
SHOW PROCESSLIST показывает, которые потоки выполняются. Вы можете также получить эту информацию из таблицы PROCESSLIST базы данных INFORMATION_SCHEMA или из команды mysqladmin processlist. Если Вы имеете привилегию PROCESS, Вы можете видеть все потоки. Иначе Вы можете видеть только свои собственные потоки (то есть, потоки, связанные с учетной записью MySQL, которую Вы используете). Если Вы не используете FULL, только первые 100 символов каждого запроса показываются в поле Info.

Информация о процессе также доступна из таблицы performance_schema.threads . Однако, доступ к threads не требует mutex и оказывает минимальное влияние на работу сервера. INFORMATION_SCHEMA.PROCESSLIST и SHOW PROCESSLIST имеют отрицательные исполнительные последствия, потому что они требуют mutex. threads также показывает информацию о фоновых потоках, которую INFORMATION_SCHEMA.PROCESSLIST и SHOW PROCESSLIST не выводят. Это означает, что threads может использоваться, чтобы контролировать деятельность, которую другие источники информации потока не могут.

SHOW PROCESSLIST очень полезен, если Вы получаете сообщение too many connections и хотите узнать, что происходит. MySQL резервирует одно дополнительное соединение, которое будет использоваться учетными записями, которые имеют привилегию SUPER, чтобы гарантировать, что администраторы должны всегда быть в состоянии соединиться и проверить систему (предполагая, что Вы не даете эту привилегию всем своим пользователям).

Потоки могут быть уничтожены с помощью KILL, см. раздел 14.7.6.4.

Пример вывода SHOW PROCESSLIST :

mysql> SHOW FULL PROCESSLIST\G
*************************** 1. row ***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 1030455
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 2
User: system user
Host:
db: NULL
Command: Connect
Time: 1004
State: Has read all relay log; waiting for the slave
   I/O thread to update it
Info: NULL
*************************** 3. row ***************************
Id: 3112
User: replikator
Host: artemis:2204
db: NULL
Command: Binlog Dump
Time: 2144
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
*************************** 4. row ***************************
Id: 3113
User: replikator
Host: iconnect2:45781
db: NULL
Command: Binlog Dump
Time: 2086
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
*************************** 5. row ***************************
Id: 3123
User: stefan
Host: localhost
db: apollon
Command: Query
Time: 0
State: NULL
Info: SHOW FULL PROCESSLIST
5 rows in set (0.00 sec)
Столбцы, произведенные SHOW PROCESSLIST имеют следующие значения:

14.7.5.30. SHOW PROFILE

SHOW PROFILE [type [, type] ... ]
     [FOR QUERY n]
     [LIMIT row_count [OFFSET offset]]

type:
ALL
  | BLOCK IO
  | CONTEXT SWITCHES
  | CPU
  | IPC
  | MEMORY
  | PAGE FAULTS
  | SOURCE
  | SWAPS
SHOW PROFILE и SHOW PROFILES выводят на экран информацию о профилировании, которая указывает на использование ресурсов для запросов, выполненных в течение текущего сеанса.

Эти запросы устарели и будут удалены в будущем выпуске MySQL. Используйте Performance Schema, см. раздел 23.16.1.

Профилированием управляет сессионная переменная profiling, у которой есть значение по умолчанию 0 (OFF). Профилирование включено, устанавливая profiling в 1 или ON:

mysql> SET profiling = 1;
SHOW PROFILES выводит на экран список новых запросов, посланных в сервер. Размером списка управляет profiling_history_size, у которой есть значение по умолчанию 15. Максимальное значение 100. Установка значения к 0 имеет эффект отключения профилирования.

Все запросы профилируются, кроме SHOW PROFILE и SHOW PROFILES, таким образом, Вы не найдете ни один из этих запросов в списке профиля. Например, SHOW PROFILING незаконный запрос, и синтаксическая ошибка происходит, если Вы пытаетесь выполнить ее, но она обнаружится в списке профилирования.

SHOW PROFILE покажет подробную информацию о единственном запросе. Без FOR QUERY n вывод принадлежит последний раз выполненному запросу. Если FOR QUERY n включен, SHOW PROFILE покажет информацию для запроса n. Значение n соответствует значению Query_ID, выведенному SHOW PROFILES.

LIMIT row_count может быть дан, чтобы ограничить вывод row_count строками. Если LIMIT задан, OFFSET offset может быть добавлен, чтобы начать вывод со строки offset в полном наборе строк.

По умолчанию SHOW PROFILE отобразит столбцы Status и Duration Значения Status походят на значения State из SHOW PROCESSLIST, хотя могли бы быть некоторые незначительные различия в интерпретации этих двух запросов для некоторых значений состояния (см. раздел 9.14).

type могут быть определены, чтобы вывести на экран определенные дополнительные типы информации:

Профилирование включено для сеанса. Когда сеанс заканчивается, его информация о профилировании потеряна.

mysql> SELECT @@profiling;
+-------------+
| @@profiling |
+-------------+
|   0         |
+-------------+
1 row in set (0.00 sec)

mysql> SET profiling = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE IF EXISTS t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE T1 (id INT);
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW PROFILES;
+----------+----------+--------------------------+
| Query_ID | Duration | Query                    |
+----------+----------+--------------------------+
| 0        | 0.000088 | SET PROFILING = 1        |
| 1        | 0.000136 | DROP TABLE IF EXISTS t1  |
| 2        | 0.011947 | CREATE TABLE t1 (id INT) |
+----------+----------+--------------------------+
3 rows in set (0.00 sec)

mysql> SHOW PROFILE;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| checking permissions | 0.000040 |
| creating table       | 0.000056 |
| After create         | 0.011363 |
| query end            | 0.000375 |
| freeing items        | 0.000089 |
| logging slow query   | 0.000019 |
| cleaning up          | 0.000005 |
+----------------------+----------+
7 rows in set (0.00 sec)

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| query end          | 0.000107 |
| freeing items      | 0.000008 |
| logging slow query | 0.000015 |
| cleaning up        | 0.000006 |
+--------------------+----------+
4 rows in set (0.00 sec)

mysql> SHOW PROFILE CPU FOR QUERY 2;
+----------------------+----------+----------+------------+
| Status               | Duration | CPU_user | CPU_system |
+----------------------+----------+----------+------------+
| checking permissions | 0.000040 | 0.000038 |   0.000002 |
| creating table       | 0.000056 | 0.000028 |   0.000028 |
| After create         | 0.011363 | 0.000217 |   0.001571 |
| query end            | 0.000375 | 0.000013 |   0.000028 |
| freeing items        | 0.000089 | 0.000010 |   0.000014 |
| logging slow query   | 0.000019 | 0.000009 |   0.000010 |
| cleaning up          | 0.000005 | 0.000003 |   0.000002 |
+----------------------+----------+----------+------------+
7 rows in set (0.00 sec)

Профилирование только частично функционально на небольшом количестве архитектуры. Для значений, которые зависят от системного вызова getrusage(), NULL возвращен на таких системах, как Windows, которые не поддерживают требование. Кроме того, профилирование для процесса, а не потока. Это означает, что деятельность по потокам в пределах сервера, кроме Вашего собственного, может затронуть информацию о синхронизации, которую Вы видите.

Вы можете также получить информацию профилирования из таблицы PROFILING базы данных INFORMATION_SCHEMA. См. раздел 22.17. Например, следующие запросы приводят к тому же самому результату:

SHOW PROFILE FOR QUERY 2;
SELECT STATE, FORMAT(DURATION, 6) AS DURATION
       FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = 2 ORDER BY SEQ;

14.7.5.31. SHOW PROFILES

SHOW PROFILES
SHOW PROFILES вместе с SHOW PROFILE показывают профилирующие информацию, которая указывает на использование ресурсов для запросов, выполненных в течение текущего сеанса. См. раздел 14.7.5.30.

14.7.5.32. SHOW RELAYLOG EVENTS

SHOW RELAYLOG EVENTS
     [IN 'log_name'] [FROM pos]
     [LIMIT [offset,] row_count]
Показывает события в журнале реле ведомого устройства. Если Вы не определяете 'log_name', первый журнал реле выведен на экран. Этот запрос не имеет никакого эффекта на ведущее устройство.

LIMIT имеет тот же самый синтаксис, что касается SELECT, см. раздел 14.2.9.

SHOW RELAYLOG EVENTS без LIMIT может занять много времени и ресурсов, потому что сервер возвращает клиенту полное содержание журнала реле (включая все запросы, изменяющие данные, которые были получены ведомым устройством).

Некоторые события, касающиеся установки пользовательских и системных переменных, не включены в вывод SHOW RELAYLOG EVENTS. Чтобы получить полный обзор событий в пределах журнала реле, используйте mysqlbinlog.

14.7.5.33. SHOW SLAVE HOSTS

SHOW SLAVE HOSTS
Выводит на экран список ведомых устройств, в настоящее время зарегистрированных в ведущем устройстве.

SHOW SLAVE HOSTS должен быть выполнен на сервере, который действует как ведущее устройство. Запрос выводит на экран информацию о серверах, которые являются или были соединены как ведомые устройства, с каждой строкой результата, соответствующей одному ведомому серверу, как показано здесь:

mysql> SHOW SLAVE HOSTS;
+------------+-----------+------+-----------+--------------------------------------+
| Server_id  | Host      | Port | Master_id | Slave_UUID                           |
+------------+-----------+------+-----------+--------------------------------------+
|  192168010 | iconnect2 | 3306 | 192168011 | 14cb6624-7f93-11e0-b2c0-c80aa9429562 |
| 1921680101 | athena    | 3306 | 192168011 | 07af4990-f41f-11df-a566-7ac56fdaf645 |
+------------+-----------+------+-----------+--------------------------------------+

14.7.5.34. SHOW SLAVE STATUS

SHOW SLAVE STATUS [FOR CHANNEL channel]
Этот запрос обеспечивает информацию о статусе и существенных параметрах ведомых потоков. Это требует любой привилегии SUPER или REPLICATION CLIENT .

SHOW SLAVE STATUS не блокирует. Когда выполнен одновременно с STOP SLAVE, SHOW SLAVE STATUS возвращается, не ожидая, пока STOP SLAVE закончить закрывать ведомый поток SQL или ведомый поток ввода/вывода (или обоих). Это разрешает использование в контроле и других приложениях где, получение непосредственного ответа от SHOW SLAVE STATUS более важно, чем обеспечение, чтобы это возвратило последние данные.

Если Вы делаете этот запрос, используя mysql, Вы можете использовать \G, а не точку с запятой, чтобы получить более читаемое вертикальное расположение:

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
   Slave_IO_State: Waiting for master to send event
  Master_Host: localhost
  Master_User: root
  Master_Port: 13000
Connect_Retry: 60
  Master_Log_File: master-bin.000002
  Read_Master_Log_Pos: 1307
   Relay_Log_File: slave-relay-bin.000003
Relay_Log_Pos: 1508
Relay_Master_Log_File: master-bin.000002
 Slave_IO_Running: Yes
Slave_SQL_Running: Yes
  Replicate_Do_DB:
  Replicate_Ignore_DB:
   Replicate_Do_Table:
   Replicate_Ignore_Table:
  Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
   Last_Errno: 0
   Last_Error:
 Skip_Counter: 0
  Exec_Master_Log_Pos: 1307
  Relay_Log_Space: 1858
  Until_Condition: None
   Until_Log_File:
Until_Log_Pos: 0
   Master_SSL_Allowed: No
   Master_SSL_CA_File:
   Master_SSL_CA_Path:
  Master_SSL_Cert:
Master_SSL_Cipher:
   Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
   Last_SQL_Errno: 0
   Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
 Master_Server_Id: 1
  Master_UUID: 3e11fa47-71ca-11e1-9e33-c80aa9429562
 Master_Info_File: /var/mysqld.2/data/master.info
SQL_Delay: 0
  SQL_Remaining_Delay: NULL
  Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Master_Retry_Count: 10
  Master_Bind:
  Last_IO_Error_Timestamp:
 Last_SQL_Error_Timestamp:
   Master_SSL_Crl:
   Master_SSL_Crlpath:
   Retrieved_Gtid_Set: 3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Executed_Gtid_Set: 3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Auto_Position: 1
 Replicate_Rewrite_DB:
 Channel_name:
1 row in set (0.00 sec)
Performance Schema обеспечивает таблицы, которые выставляют информацию о репликации. Это подобно информации, доступной из SHOW SLAVE STATUS, но представленной в табличной форме. Для деталей см. раздел 23.9.11 .

Следующий список описывает области, возвращенные SHOW SLAVE STATUS. См. раздел 19.1.7.1 .

14.7.5.35. SHOW STATUS

SHOW [GLOBAL | SESSION] STATUS
[LIKE 'pattern' | WHERE expr]

Значение show_compatibility_56 затрагивает информацию и привилегии, требуемые для запроса, описанного здесь. Для деталей см. раздел 6.1.5.

SHOW STATUS обеспечивает информацию о статусе сервера (см. раздел 6.1.7). Этот запрос не требует никакой привилегии. Это требует только способности соединиться с сервером.

Информация о переменной состояния также доступна из этих источников:

Для SHOW STATUS LIKE, если есть, указывает, которые имена переменных соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

SHOW STATUS принимает дополнительный параметр GLOBAL или SESSION:

Контекст для каждой переменной состояния перечислен в разделе 6.1.7.

Каждый вызов SHOW STATUS использует внутреннюю временную таблицу и постепенно увеличивает глобальное значение Created_tmp_tables.

Частичный вывод показан здесь. Список имен и значений может отличаться для Вашего сервера. Значение каждой переменной дано в разделе 6.1.7.

mysql> SHOW STATUS;
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| Aborted_clients         | 0          |
| Aborted_connects        | 0          |
| Bytes_received          | 155372598  |
| Bytes_sent              | 1176560426 |
| Connections             | 30023      |
| Created_tmp_disk_tables | 0          |
| Created_tmp_tables      | 8340       |
| Created_tmp_files       | 60         |
...
| Open_tables             | 1          |
| Open_files              | 2          |
| Open_streams            | 0          |
| Opened_tables           | 44600      |
| Questions               | 2026873    |
...
| Table_locks_immediate   | 1920382    |
| Table_locks_waited      | 0          |
| Threads_cached          | 0          |
| Threads_created         | 30022      |
| Threads_connected       | 1          |
| Threads_running         | 1          |
| Uptime                  | 80380      |
+-------------------------+------------+
С LIKE запрос выводит на экран только строки для переменных с именами, которые соответствуют образцу:
mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| Key_blocks_used    | 14955    |
| Key_read_requests  | 96854827 |
| Key_reads          | 162040   |
| Key_write_requests | 7589728  |
| Key_writes         | 3813196  |
+--------------------+----------+

14.7.5.36. SHOW TABLE STATUS

SHOW TABLE STATUS [{FROM | IN} db_name]
     [LIKE 'pattern' | WHERE expr]
SHOW TABLE STATUS работает аналогично SHOW TABLES , но предоставляет большую информацию о каждой не-TEMPORARY таблице. Вы можете также получить этот список, используя команду mysqlshow --status db_name. LIKE, если есть, указывает, которые имена таблиц соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в раздел 22.31.

Этот запрос также выводит на экран информацию о представлениях.

Вывод SHOW TABLE STATUS имеет такие столбцы:

Примечания:

14.7.5.37. SHOW TABLES

SHOW [FULL] TABLES [{FROM | IN} db_name]
     [LIKE 'pattern' | WHERE expr]
SHOW TABLES перечисляет не-TEMPORARY таблицы в данной базе данных. Вы можете также получить этот список, используя mysqlshow db_name. LIKE, если есть, указывает, которые имена таблиц соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в раздел 22.31.

Соответствие LIKE зависит от установки переменной lower_case_table_names.

Этот запрос также перечисляет любые представления в базе данных. FULL поддержан таким образом, что SHOW FULL TABLES выводит на экран второй столбец. Значения для второго столбца BASE TABLE для таблицы и VIEW для представления.

Если у Вас нет никаких привилегий для базовой таблицы или представления, объект не показан в выводе SHOW TABLES или mysqlshow db_name.

14.7.5.38. SHOW TRIGGERS

SHOW TRIGGERS [{FROM | IN} db_name]
     [LIKE 'pattern' | WHERE expr]
SHOW TRIGGERS перечисляет триггеры, в настоящее время определенные для таблиц в базе данных (базе данных по умолчанию, если нет FROM). Этот запрос возвращает результаты только для баз данных и таблиц, для которых Вы имеете привилегию TRIGGER . LIKE, если есть, указывает, какие имена таблиц (не триггеров!) соответствуют, и заставляет запрос выводить на экран триггеры для тех таблиц. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

Для триггера ins_sum, определенного в разделе 21.3, вывод этого запроса показан здесь:

mysql> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1. row ***************************
 Trigger: ins_sum
   Event: INSERT
   Table: account
   Statement: SET @sum = @sum + NEW.amount
  Timing: BEFORE
 Created: 2013-07-09 10:39:34.96
sql_mode: NO_ENGINE_SUBSTITUTION
 Definer: me@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: latin1_swedish_ci
Столбцы вывода SHOW TRIGGERS :

Вы можете также получить информацию о триггерах из таблицы TRIGGERS в базе данных INFORMATION_SCHEMA. См. раздел 22.27.

14.7.5.39. SHOW VARIABLES

SHOW [GLOBAL | SESSION] VARIABLES
     [LIKE 'pattern' | WHERE expr]

Значение show_compatibility_56 затрагивает доступную информацию и привилегии, требуемые для запроса, описанного здесь. Для деталей см. описание этой переменной в разделе 6.1.5 .

SHOW VARIABLES показывает значения системных переменных MySQL (см. раздел 6.1.5). Этот запрос не требует никакой привилегии. Это требует только способности соединиться с сервером.

Системная информация о переменной также доступна из этих источников:

Для SHOW VARIABLES LIKE, если есть, указывает, которые имена переменной соответствуют. WHERE может быть дан, чтобы выбрать строки, используя более общие условия, как обсуждено в разделе 22.31.

SHOW VARIABLES принимает дополнительный модификатор контекста GLOBAL или SESSION:

Контекст для каждой системной переменной перечислен в разделе 6.1.5.

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

SELECT @@GLOBAL.innodb_data_file_path;
Большинство системных переменных может быть установлено при запуске сервера (переменные только для чтения, например, version_comment это исключения). Многие могут быть изменены во время выполнения с помощью SET. См. разделы 6.1.6 и 14.7.4.1.

Частичный вывод показывают здесь. Список имен и значений может отличаться для Вашего сервера. Раздел 6.1.5 описывает значение каждой переменной, а раздел 6.1.1 предоставляет информацию об их настройке.

mysql> SHOW VARIABLES;
+-----------------------------------------+---------------------------+
| Variable_name                           | Value                     |
+-----------------------------------------+---------------------------+
| auto_increment_increment                | 1                         |
| auto_increment_offset                   | 1                         |
| autocommit                              | ON                        |
| automatic_sp_privileges                 | ON                        |
| back_log                                | 50                        |
| basedir                                 | /home/jon/bin/mysql-5.5   |
| big_tables                              | OFF                       |
| binlog_cache_size                       | 32768                     |
| binlog_direct_non_transactional_updates | OFF                       |
| binlog_format                           | STATEMENT                 |
| binlog_stmt_cache_size                  | 32768                     |
| bulk_insert_buffer_size                 | 8388608                   |
...
| max_allowed_packet                      | 4194304                   |
| max_binlog_cache_size                   | 18446744073709547520      |
| max_binlog_size                         | 1073741824                |
| max_binlog_stmt_cache_size              | 18446744073709547520      |
| max_connect_errors                      | 100                       |
| max_connections                         | 151                       |
| max_delayed_threads                     | 20                        |
| max_error_count                         | 64                        |
| max_heap_table_size                     | 16777216                  |
| max_insert_delayed_threads              | 20                        |
| max_join_size                           | 18446744073709551615      |
...
| thread_handling                         | one-thread-per-connection |
| thread_stack                            | 262144                    |
| time_format                             | %H:%i:%s                  |
| time_zone                               | SYSTEM                    |
| timestamp                               | 1316689732                |
| tmp_table_size                          | 16777216                  |
| tmpdir                                  | /tmp                      |
| transaction_alloc_block_size            | 8192                      |
| transaction_prealloc_size               | 4096                      |
| tx_isolation                            | REPEATABLE-READ           |
| unique_checks                           | ON                        |
| updatable_views_with_limit              | YES                       |
| version                                 | 5.5.17-log                |
| version_comment                         | Source distribution       |
| version_compile_machine                 | x86_64                    |
| version_compile_os                      | Linux                     |
| wait_timeout                            | 28800                     |
| warning_count                           | 0                         |
+-----------------------------------------+---------------------------+
С LIKE запрос выводит на экран строки только для тех переменных, имена которых соответствуют образцу. Чтобы получить строку для определенной переменной, используйте LIKE:
SHOW VARIABLES LIKE 'max_join_size';
SHOW SESSION VARIABLES LIKE 'max_join_size';
Чтобы получить список переменных чьи имена соответствуют образцу, используйте подстановочный символ % в LIKE:
SHOW VARIABLES LIKE '%size%';
SHOW GLOBAL VARIABLES LIKE '%size%';
Подстановочные символы могут использоваться в любой позиции в пределах образца, который будет соответствующим. Строго говоря, потому что _ это подстановочный знак, который соответствует любому единственному символу, Вы должны экранировать его как \_, чтобы соответствовать этому буквально. Практически это редко необходимо.

14.7.5.40. SHOW WARNINGS

SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW COUNT(*) WARNINGS
SHOW WARNINGS это диагностический запрос, отображающий информацию об условиях (ошибки, предупреждения и примечания), следующих из выполнения запросов в текущем сеансе. Предупреждения произведены для таких запросов DML, как INSERT, UPDATE и LOAD DATA INFILE, а также для запросов DDL CREATE TABLE и ALTER TABLE.

LIMIT имеет тот же самый синтаксис, что касается SELECT, см. раздел 14.2.9.

SHOW WARNINGS также используется после EXPLAIN EXTENDED, чтобы вывести на экран дополнительную информацию, произведенную EXPLAIN, когда используется EXTENDED, см. раздел 9.8.3.

SHOW WARNINGS показывает информацию об условиях, следующих из выполнения нового недиагностического запроса в текущем сеансе. Если новый запрос привел к ошибке во время парсинга, SHOW WARNINGS показывает получающиеся условия, независимо от типа запроса (диагностический или недиагностический).

SHOW COUNT(*) WARNINGS выводит на экран общее количество ошибок, предупреждений и примечаний. Вы можете также получить это число из переменной warning_count:

SHOW COUNT(*) WARNINGS;
SELECT @@warning_count;
Различие в этих запросах: первый является диагностическим запросом, который не очищает список сообщений. Второй считают недиагностическим и очищает список сообщений, потому что это использует SELECT.

Связанный диагностический запрос SHOW ERRORS показывает только состояния ошибки (это исключает предупреждения и примечания), а SHOW COUNT(*) ERRORS показывает общее количество ошибок. См. раздел 14.7.5.17. GET DIAGNOSTICS может использоваться, чтобы исследовать информацию на отдельные условия. См. раздел 14.6.7.3.

Вот простой пример, который показывает предупреждения преобразования данных для INSERT:

mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4));
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO t1 VALUES(10,'mysql'), (NULL,'test'), (300,'xyz');
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 3

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1265
Message: Data truncated for column 'b' at row 1
*************************** 2. row ***************************
  Level: Warning
   Code: 1048
Message: Column 'a' cannot be null
*************************** 3. row ***************************
  Level: Warning
   Code: 1264
Message: Out of range value for column 'a' at row 3
3 rows in set (0.00 sec)
max_error_count управляет максимальным количеством ошибок, предупреждений и сообщений примечания, для которых сервер хранит информацию, и таким образом число сообщений, которые покажет SHOW WARNINGS. Чтобы изменить число сообщений, которое сервер может сохранить, измените значение max_error_count. По умолчанию 64.

max_error_count контролирует сколько сообщений хранится, а не сколько посчитано. Значение warning_count не ограничено max_error_count, даже если число произведенных сообщений превышает max_error_count. Следующий пример демонстрирует это. ALTER TABLE производит три предупреждающих сообщения (строгий режим SQL отключен для примера, чтобы препятствовать ошибке после проблемы однократного преобразования). Только одно сообщение хранится и выведено на экран потому, что max_error_count была установлена в 1, но все три посчитаны (как показано значением warning_count):

mysql> SHOW VARIABLES LIKE 'max_error_count';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_error_count | 64    |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> SET max_error_count=1, sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t1 MODIFY b CHAR;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 3

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT @@warning_count;
+-----------------+
| @@warning_count |
+-----------------+
|   3             |
+-----------------+
1 row in set (0.01 sec)
Чтобы отключить хранение сообщений, установите max_error_count в 0. В этом случае warning_count все еще указывает, сколько предупреждений произошло, но сообщения не хранятся и не могут быть выведены на экран.

sql_notes управляет, увеличивается ли счетчик сообщений warning_count и хранит ли их сервер. По умолчанию sql_notes = 1, но если установлено в 0, примечания не увеличивают warning_count и сервер не хранит их:

mysql> SET sql_notes = 1;
mysql> DROP TABLE IF EXISTS test.no_such_table;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------------+
| Level | Code | Message                            |
+-------+------+------------------------------------+
| Note  | 1051 | Unknown table 'test.no_such_table' |
+-------+------+------------------------------------+
1 row in set (0.00 sec)

mysql> SET sql_notes = 0;
mysql> DROP TABLE IF EXISTS test.no_such_table;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW WARNINGS;
Empty set (0.00 sec)
Сервер MySQL посылает каждому клиенту количество, указывающее на общее количество ошибок, предупреждений и примечаний, следующих из нового запроса, выполненного клиентом. Из C API это значение может быть получено вызовом mysql_warning_count() . См. раздел 25.8.7.77.

В mysql Вы можете включить и отключить автоматическое отображение предупреждений, используя соответственно команды warnings и nowarning или их сокращения \W и \w (см. раздел 5.5.1.2):

mysql> \W
Show warnings enabled.
mysql> SELECT 1/0;
+------+
| 1/0  |
+------+
| NULL |
+------+
1 row in set, 1 warning (0.03 sec)

Warning (Code 1365): Division by 0
mysql> \w
Show warnings disabled.

14.7.6. Другие административные запросы

14.7.6.1. BINLOG

BINLOG 'str'
BINLOG запрос внутреннего пользования. Это произведено mysqlbinlog как пригодное для печатания представление определенных событий в двоичных файлах системного журнала. См. раздел 5.6.8. Значение 'str' это строка в base64, которую сервер расшифровывает, чтобы определить изменение данных, обозначенное соответствующим событием. Этот запрос требует привилегию SUPER.

Это запрос может выполнить только события описания формата и события строки.

14.7.6.2. CACHE INDEX

CACHE INDEX tbl_index_list [,
      tbl_index_list] ...
      [PARTITION (partition_list | ALL)]
      IN key_cache_name

tbl_index_list:
  tbl_name [[INDEX|KEY] (index_name[,
  index_name] ...)]

partition_list:
  partition_name[, partition_name][, ...]
CACHE INDEX назначает табличные индексы к определенному ключевому кэшу. Это используется только для MyISAM. После назначения индексов, они могут быть предварительно загружены в кэш при желании с LOAD INDEX INTO CACHE.

Следующий запрос назначает индекс таблиц t1, t2 и t3 к ключевому кэшу hot_cache:

mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+
CACHE INDEX позволяет Вам определить, что только особый индекс таблицы должен быть назначен на кэш. Текущее выполнение назначает все индексы таблицы к кэшу, таким образом нет никакой причины определить что-либо, кроме имени таблицы.

Ключевой кэш, упомянутый в CACHE INDEX, может быть создан, устанавливая его размер с запросом установки параметра или в установках параметров сервера. Например:

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
К ключевым параметрам кэша можно получить доступ как к членам структурированной системной переменной. См. раздел 6.1.6.1.

Ключевой кэш должен существовать прежде, чем Вы сможете назначить индекс к нему:

mysql> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'
По умолчанию индексы таблицы назначены на основной (значение по умолчанию) ключевой кэш, создаваемый при запуске сервера. Когда ключевой кэш разрушен, все индексы, назначенные на него, становятся назначенными на ключевой кэш значения по умолчанию снова.

Назначения действуют на сервер глобально: если один клиент назначает индексирование на данный кэш, этот кэш используется для всех запросов, вовлекающих индексирование, независимо от того, какой клиент их запускает.

В MySQL 8.0 этот запрос также поддержан для разделенных таблиц MyISAM. Вы можете назначить один или больше индексов для одного, нескольких или всех разделов к данному ключевому кэшу. Например, Вы можете сделать следующее:

CREATE TABLE pt (c1 INT, c2 VARCHAR(50), INDEX i(c1)) ENGINE=MyISAM
       PARTITION BY HASH(c1) PARTITIONS 4;
SET GLOBAL kc_fast.key_buffer_size = 128 * 1024;
SET GLOBAL kc_slow.key_buffer_size = 128 * 1024;
CACHE INDEX pt PARTITION (p0) IN kc_fast;
CACHE INDEX pt PARTITION (p1, p3) IN kc_slow;
Предыдущий набор запросов выполняет следующие действия:

Если Вы хотите вместо этого назначить индекс для всех разделов в таблице pt к единственному ключевому кэшу kc_all, Вы можете использовать любой из следующих 2 запросов:

CACHE INDEX pt PARTITION (ALL) IN kc_all;
CACHE INDEX pt IN kc_all;
Эти два запроса эквивалентны. Другими словами, если Вы хотите назначить индекс для всех разделов таблицы к тому же самому ключевому кэшу, тогда PARTITION (ALL) опционально.

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

В MySQL 8.0 индекс предварительно загружен для разделенных таблиц MyISAM. См. раздел 14.7.6.5.

14.7.6.3. FLUSH

FLUSH [NO_WRITE_TO_BINLOG | LOCAL]
      flush_option [, flush_option] ...
FLUSH имеет несколько различных форм, которые перезагружают различные внутренние кэши, таблицы потока или блокировки. Чтобы выполнить FLUSH, Вы должны иметь привилегию RELOAD . Определенные опции потока могли бы потребовать дополнительных привилегий, как описано позже.

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

FLUSH LOGS, FLUSH TABLES WITH READ LOCK и FLUSH TABLES tbl_name ... FOR EXPORT не записаны в двоичный журнал в любом случае, потому что они вызвали бы проблемы, если копируются к ведомому устройству.

Сигнал SIGHUP серверу вызывает несколько операций, которые подобны различным формам FLUSH, см. раздел 6.1.11.

FLUSH неявно закрывает транзакции. См. раздел 14.3.3.

RESET аналогичен FLUSH, см. раздел 14.7.6.6.

flush_option может быть любым из следующих элементов.

mysqladmin обеспечивает интерфейс командной строки к некоторым операциям потока, используя такие команды, как flush-hosts, flush-logs , flush-privileges, flush-status и flush-tables. См. раздел 5.5.2.

Невозможно запустить FLUSH в пределах сохраненных функций или триггеров. Однако, Вы можете использовать statements within stored FLUSH в хранимых процедурах, пока их не вызывают из сохраненных функций или триггеров. См. раздел C.1 .

FLUSH TABLES

FLUSH TABLES имеет несколько форм, описанных после. Если любая разновидность опции TABLES используется в FLUSH , это должна быть единственная используемая опция. FLUSH TABLE синоним для FLUSH TABLES.

14.7.6.4. KILL

KILL [CONNECTION | QUERY] processlist_id
Каждое соединение с mysqld работает в отдельном потоке. Вы можете уничтожить поток с помощью KILL processlist_id.

Идентификаторы потока могут быть определены из столбца ID таблицы INFORMATION_SCHEMA.PROCESSLIST, столбца Id вывода SHOW PROCESSLIST и столбца PROCESSLIST_ID таблицы Performance Schema threads. Значение для текущего потока возвращено функцией CONNECTION_ID().

KILL разрешает дополнительный модификатор CONNECTION или QUERY:

Если Вы имеете привилегию PROCESS, Вы можете видеть все потоки. Если Вы имеете привилегию SUPER, Вы можете уничтожить все потоки и запросы. Иначе Вы можете видеть и уничтожить только свои собственные потоки и запросы.

Вы можете также использовать команды mysqladmin processlist и mysqladmin kill, чтобы исследовать и уничтожить потоки.

Вы не можете использовать KILL с библиотекой Embedded MySQL Server потому, что встроенный сервер просто работает в потоках приложения. Это не создает собственных потоков соединения.

Когда Вы используете KILL, определенный для потока флаг уничтожения установлен. В большинстве случаев это может занять время для потока, потому что флаг уничтожения проверен только в определенных интервалах:

Уничтожение REPAIR TABLE или OPTIMIZE TABLE на MyISAM приводит к таблице, которая повреждена и непригодна. Любые чтения или записи такой таблицы терпят неудачу, пока Вы не оптимизируете или не восстанавливаете ее снова (без прерывания).

14.7.6.5. LOAD INDEX INTO CACHE

LOAD INDEX INTO CACHE
  tbl_index_list [, tbl_index_list] ...
tbl_index_list:
  tbl_name
  [PARTITION (partition_list | ALL)]
  [[INDEX|KEY] (index_name[, index_name] ...)]
  [IGNORE LEAVES]
partition_list:
partition_name[, partition_name][, ...]
LOAD INDEX INTO CACHE предварительные загружает табличный индекс в ключевой кэш, на который она была назначена явным CACHE INDEX или в ключевой кэш по умолчанию иначе.

LOAD INDEX INTO CACHE используется только для MyISAM. В MySQL 8.0 это также поддержано для разделенных таблиц MyISAM, кроме того, индекс на разделенных таблицах, может быть предварительно загружен для одного, нескольких или всех разделов.

IGNORE LEAVES заставляет только блоки для узлов нелиста индекса быть предварительно загруженными.

IGNORE LEAVES также поддержан для разделенных таблиц MyISAM.

Следующий запрос предварительно загружает узлы (индексные блоки) индекса для таблиц t1 и t2:

mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table   | Op           | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status   | OK       |
| test.t2 | preload_keys | status   | OK       |
+---------+--------------+----------+----------+
Этот запрос предварительно загружает все индексные блоки из t1. Это предварительно загружает только блоки для узлов нелиста t2.

LOAD INDEX INTO CACHE позволяет Вам определить, что только особый индекс таблицы должен быть предварительно загружен. Текущие выполнение грузит все индексы таблицы в кэш, таким образом, нет никакой причины определить что-либо, кроме имени таблицы.

Возможно предварительно загрузить индекс на определенном разделе таблицы MyISAM. Например, следующие 2 запроса предварительно загружают индекс: первый запрос для раздела p0 таблицы pt, второй запрос для разделов p1 и p3:

LOAD INDEX INTO CACHE pt PARTITION (p0);
LOAD INDEX INTO CACHE pt PARTITION (p1, p3);
Предварительно загрузить индексирование для всего разделения в таблице pt можно любым из следующих 2 запросов:
LOAD INDEX INTO CACHE pt PARTITION (ALL);
LOAD INDEX INTO CACHE pt;
Эти два запроса эквивалентны. Другими словами, если Вы хотите предварительно загрузить индексы для всего разделения разделенной таблицы, то PARTITION (ALL) опционально.

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

LOAD INDEX INTO CACHE ... IGNORE LEAVES терпит неудачу, если не все индексы в таблице имеют тот же самый размер блока. Вы можете определить размеры блока для таблицы при использовании myisamchk -dv и проверке столбца Blocksize.

14.7.6.6. RESET

RESET reset_option [, reset_option] ...
RESET используется, чтобы очистить состояние различных операций сервера. Вы должны иметь привилегию RELOAD .

RESET действует как более сильная версия FLUSH, см. раздел 14.7.6.3.

RESET неявно закрывает транзакции. См. раздел 14.3.3.

reset_option может быть таким:

14.7.6.7. SHUTDOWN

SHUTDOWN
Этот запрос останавливает сервер MySQL. Это требует привилегии SHUTDOWN.

SHUTDOWN обеспечивает SQL-интерфейс с той же самой функциональностью, как использование команды mysqladmin shutdown .

14.8. Служебные запросы

14.8.1. DESCRIBE

DESCRIBE и EXPLAIN синонимы, используемые чтобы получить информацию о структуре таблицы или планах выполнения запроса. Для получения дополнительной информации см. разделы 14.7.5.5 и 14.8.2.

14.8.2. EXPLAIN

{EXPLAIN | DESCRIBE | DESC}
tbl_name [col_name |
wild]

{EXPLAIN | DESCRIBE | DESC}
[explain_type]
{explainable_stmt | FOR CONNECTION
     connection_id}
explain_type: {EXTENDED | PARTITIONS
  | FORMAT = format_name}
format_name: {TRADITIONAL | JSON}
explainable_stmt: {
SELECT statement
  | DELETE statement
  | INSERT statement
  | REPLACE statement
  | UPDATE statement}
Практически DESCRIBE чаще используется, чтобы получить информацию о структуре таблицы, тогда как EXPLAIN используется, чтобы получить план выполнения запроса (то есть, объяснение того, как MySQL выполнил бы запрос). Следующее обсуждение использует DESCRIBE и EXPLAIN в соответствии с этим использованием, но анализатор MySQL обрабатывает их как абсолютные синонимы.

Получение информации о структуре таблицы

DESCRIBE предоставляет информацию о столбцах в таблице:

mysql> DESCRIBE City;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
DESCRIBE сокразение для SHOW COLUMNS. Эти запросытакже выводят на экран информацию для представлений. Описание для SHOW COLUMNS предоставляет больше информации о столбцах вывода. См. раздел 14.7.5.5.

По умолчанию DESCRIBE отображает информацию обо всех столбцах в таблице. col_name, если есть, задает название столбца в таблице. В этом случае запрос выводит на экран информацию только для названного столбца. wild, если задана, строка образца. Это может содержать подстановочные символы SQL % и _. В этом случае запрос выводит на экран вывод только для столбцов с именами, соответствующими строке. Нет никакой потребности помещать строку в пределах кавычек, если она не содержит пробелы или другие специальные символы.

DESCRIBE обеспечен для совместимости с СУБД Oracle.

SHOW CREATE TABLE, SHOW TABLE STATUS и SHOW INDEX также предоставляют информацию о таблицах. См. раздел 14.7.5.

Получение информации о плане выполнения

EXPLAIN предоставляет информацию о том, как MySQL выполняет запросы:

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

Оптимизатор может иногда предоставлять информацию, дополнительную к EXPLAIN. Однако, формат следа оптимизатора и контент подвержены изменениям между версиями. Для деталей см. MySQL Internals: Tracing the Optimizer.

Если у Вас есть проблема с тем, что индекс не используется, когда Вы полагаете, что он должен быть задействован, выполните ANALYZE TABLE, чтобы обновить табличную статистику, такую как количество элементов ключей, которые могут затронуть выбор, который делает оптимизатор. См. раздел 14.7.2.1.

14.8.3. HELP

HELP 'search_string'
HELP возвращает информацию из MySQL Reference manual. Его правильное функционирование требует что таблицы справки в базе данных mysql были инициализированы с информацией о теме справки (см. раздел 6.1.10).

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

Строка поиска может содержать подстановочные символы % и _. У них есть то же самое значение, что касается соответствующих операций, выполненных с оператором LIKE. Например, HELP 'rep%' возвращает список тем, которые начинаются с rep.

Запрос HELP понимает несколько типов строк поиска:

Другими словами, строка поиска соответствует категории, темам или единственной теме. Вы не можете обязательно сказать заранее, возвратит ли данная строка поиска список элементов или справочную информацию для единственной темы справки. Однако, Вы можете сказать, какой ответ HELP возвращен, исследуя число строк и столбцов в наборе результатов.

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

14.8.4. USE

USE db_name
USE db_name запрос говорит MySQL использовать базу данных db_name как значение по умолчанию (текущую) базу данных для последующих запросов. База данных остается значением по умолчанию до конца сеанса или другого вызова оператора USE:
USE db1;
SELECT COUNT(*) FROM mytable;   # selects from db1.mytable
USE db2;
SELECT COUNT(*) FROM mytable;   # selects from db2.mytable
Создание особой базы данных по умолчанию посредством USE не устраняет Вас от доступа к таблицам в других базах данных. Следующий пример получает доступ к таблице author базы данных db1 и таблице editor базы данных db2:
USE db1;
SELECT author_name,editor_name FROM author,db2.editor
       WHERE author.editor_id = db2.editor.editor_id;