Функция CAST() соответствует синтаксису ANSI SQL99, а функция CONVERT() - синтаксису ODBC.
Данная функция приведения типов используется главным образом для создания столбца конкретного типа с помощью команды CREATE ... SELECT:
Выражение CAST string AS BINARY эквивалентно BINARY string. CAST(expr AS CHAR считает что данное выражение есть строка в кодировке по умолчанию.
Для преобразования строки в числовую величину обычно не нужно ничего делать: просто используйте строку так, как будто это число:
Если вы указываете номер в строковом контексте, номер будет автоматически преобразован к строке типа BINARY.
MySQL поддерживает арифметические операции с 64-битовыми величинами - как со знаковыми, так и с беззнаковыми. Если используются числовые операции (такие как +) и один из операндов представлен в виде unsigned integer, то результат будет беззнаковым. Его можно переопределить, используя операторы приведения SIGNED и UNSIGNED, чтобы получить 64-битовое целое число со знаком или без знака соответственно.
Следует учитывать, что если один из операндов представлен величиной с плавающей точкой (в данном контексте DECIMAL() рассматривается как величина с плавающей точкой), результат также является величиной с плавающей точкой и не подчиняется вышеприведенному правилу приведения.
Если в арифметической операции используется строка, то результат преобразуется в число с плавающей точкой.
MySQL использует для двоичных операций 64-битовые величины BIGINT, следовательно, для двоичных операторов максимальный диапазон составляет 64 бита.
Результат является беззнаковым 64-битовым целым числом.
Результат является беззнаковым 64-битовым целым числом.
Результат - беззнаковое 64-битное целое число.
XOR был реализован в MySQL 4.0.2.
Результат является беззнаковым 64-битовым целым числом.
Результат является беззнаковым 64-битовым целым числом.
Результат является беззнаковым 64-битовым целым числом.
возвращает пустую строку.
В версии MySQL 3.22.11 или более поздней данная функция включает в себя имя хоста клиента, а также имя пользователя. Можно извлечь часть, касающуюся только имени пользователя, приведенным ниже способом (проверяется, включает ли данная величина имя хоста):
Возвращает текущее имя пользователя, под которым пользователь аутентифицировался в текущей сессии:
mysql> SELECT USER(); -> 'davida@localhost' mysql> SELECT * FROM mysql.user; -> ERROR 1044: Access denied for user: '@localhost' to database 'mysql' mysql> SELECT CURRENT_USER(); -> '@localhost'
Создает строку "пароля" из простого текста в аргументе str. Именно эта функция используется в целях шифрования паролей MySQL для хранения в столбце Password в таблице привилегий user:
Шифрование, которое выполняет функция PASSWORD(), необратимо. Способ шифрования пароля, который используется функцией PASSWORD(), отличается от применяемого для шифрования паролей в Unix.
Функция PASSWORD() используется в системе аутентификации в сервер MySQL, вам не следует использовать ее для ваших собственных приложений. С этой целью, лучше используйте функции MD5() и SHA1().
Шифрует аргумент str, используя вызов системной функции кодирования crypt() из Unix. Аргумент salt должен быть строкой из двух символов (в версии MySQL 3.22.16 аргумент salt может содержать более двух символов):
Если функция crypt() в данной операционной системе недоступна, функция ENCRYPT() всегда возвращает NULL. Функция ENCRYPT() игнорирует все символы в аргументе str, за исключением первых восьми, по крайней мере в некоторых операционных системах - это определяется тем, как реализован системный вызов базовой функции crypt().
Аргумент | Описание |
Только один аргумент | Используется первый ключ из des-key-file |
Номер ключа | Используется заданный ключ (0-9) из des-key-file |
Строка | Для шифрования string_to_encrypt может использоваться ключ, заданный в key_string |
Функция возвращает двоичную строку, в которой первый символ будет CHAR(128 | key_number). Число 128 добавлено для упрощения распознавания зашифрованного ключа. При использовании строкового ключа key_number будет равен 127. При ошибке эта функция возвращает NULL. Длина строки в результате будет равна new_length=org_length + (8-(org_length % 8))+1. Выражение des-key-file имеет следующий форматt:
key_number des_key_string key_number des_key_string
Каждый элемент key_number должен быть числом от 0 до 9. Строки в данном файле могут располагаться в произвольном порядке. Выражение des_key_string
представляет собой строку, которая будет использована при шифровании сообщения. Между числом и ключом должен быть по крайней мере один пробел. Первый ключ используется по умолчанию, если не задан какой-либо аргумент ключа в функции DES_ENCRYPT(). Существует возможность послать MySQL запрос на чтение новых значений ключей из файла ключей при помощи команды FLUSH DES_KEY_FILE. Эта операция требует наличия привилегии Reload_priv. Одно из преимуществ наличия набора ключей по умолчанию состоит в том, что приложения могут проверять существование зашифрованных величин в столбцах без предоставления конечному пользователю права расшифровки этих величин.
mysql> SELECT customer_address FROM customer_table WHERE crypted_credit_card = DES_ENCRYPT("credit_card_number");
DES_DECRYPT(string_to_decrypt [, key_string])
Дешифрует строку, зашифрованную с помощью функции DES_ENCRYPT(). Следует учитывать, что эта функция работает только тогда, когда конфигурация MySQL поддерживает SSL. See section 4.3.9 Использование безопасных соединений. Если аргумент key_string не задан, то функция DES_DECRYPT() проверяет первый байт зашифрованной строки для определения номера ключа алгоритма DES, использованного для шифрования исходной строки, Затем читает ключ из des-key-file для расшифровки сообщения. Чтобы выполнить это, пользователь должен обладать привилегией SUPER. При указании значения аргумента в key_string эта строка используется как ключ для дешифровки сообщения. Если строка string_to_decrypt не выглядит как зашифрованная, то MySQL вернет заданную строку string_to_decrypt. При ошибке эта функция возвращает NULL.
LAST_INSERT_ID([expr])
Возвращает последнюю автоматически сгенерированную величину, которая была внесена в столбец AUTO_INCREMENT. See section 8.4.3.31 mysql_insert_id().
mysql> SELECT LAST_INSERT_ID(); -> 195
Значение последнего сгенерированного ID сохраняется на сервере для данного конкретного соединения и не будет изменено другим клиентом. Оно не будет изменено даже при обновлении другого столбца AUTO_INCREMENT конкретной величиной (то есть, которая не равна NULL и не равна 0). При внесении большого количества строк с помощью одной команды INSERT функция LAST_INSERT_ID() возвращает значение для первой внесенной строки. Причина этого заключается в том, что можно легко воспроизвести точно такую же команду INSERT на другом сервере.
Если задано значение аргумента expr в функции LAST_INSERT_ID(), то величина аргумента возвращается функцией и устанавливается в качестве следующего значения, которое будет возвращено функцией LAST_INSERT_ID(). Это можно использовать для моделирования последовательностей:
Вначале создается таблица:
mysql> CREATE TABLE sequence (id INT NOT NULL); mysql> INSERT INTO sequence VALUES (0);
Затем данную таблицу можно использовать для генерации чисел последовательности как показано ниже:
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
Можно генерировать последовательности без вызова LAST_INSERT_ID(): полезность применения данной функции состоит в том, что данное значение ID
поддерживается на сервере как последняя автоматически сгенерированная величина (защищенная от других пользователей), и вы можете извлекать новый ID так же, как и любое другое нормальное значение AUTO_INCREMENT в MySQL. Например, функция LAST_INSERT_ID() (без аргумента) возвратит новое значение ID. Функцию C API mysql_insert_id() также можно использовать для получения этой величины. Следует учитывать, что, поскольку функция mysql_insert_id() обновляется только после команд INSERT и UPDATE, то нельзя использовать эту функцию C API для извлечения значения ID для LAST_INSERT_ID(expr) после выполнения других команд SQL, таких как SELECT
или SET.
FORMAT(X,D)
Форматирует число X в формат вида '#,###,###.##' с округлением до D
десятичных знаков. Если D равно 0, результат будет представлен без десятичной точки или дробной части:
mysql> SELECT FORMAT(12332.123456, 4); -> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4); -> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0); -> '12,332'
VERSION()
Возвращает строку с номером версии сервера MySQL:
mysql> SELECT VERSION(); -> '3.23.13-log'
Следует учитывать, что если данная версия заканчивается с -log, то это означает, что включено ведение журналов.
CONNECTION_ID()
Возвращает идентификатор (thread_id) для данного соединения. Каждое соединение имеет свой собственный уникальный идентификатор:
mysql> SELECT CONNECTION_ID(); -> 1
GET_LOCK(str,timeout)
Пытается осуществить блокировку по имени, которое заданно в строке str, с временем ожидания в секундах, указанном в аргументе timeout. Возвращает 1, если блокировка осуществлена успешно, 0 - если закончилось время ожидания для данной попытки, или NULL, если возникла ошибка (такая как отсутствие свободной памяти или уничтожение потока командой mysqladmin kill).
Блокировка снимается при выполнении команды RELEASE_LOCK(), запуске новой команды GET_LOCK() или при завершении данного потока. Эту функцию можно использовать для осуществления блокировок уровня приложения или для моделирования блокировки записи. Функция блокирует запросы других клиентов на блокировку с тем же именем; клиенты, которые используют согласованные имена блокировок, могут применять эту функцию для выполнения совместного упредительного блокирования:
mysql> SELECT GET_LOCK("lock1",10); -> 1 mysql> SELECT IS_FREE_LOCK("lock2"); -> 1 mysql> SELECT GET_LOCK("lock2",10); -> 1 mysql> SELECT RELEASE_LOCK("lock2"); -> 1 mysql> SELECT RELEASE_LOCK("lock1"); -> NULL
Обратите внимание: повторный вызов функции RELEASE_LOCK() возвращает NULL, поскольку блокировка lock1 была автоматически выполнена вторым вызовом функции GET_LOCK().
RELEASE_LOCK(str)
Снимает блокировку, указанную в строке str, полученной от функции GET_LOCK(). Возвращает 1 если блокировка была снята, 0 - если такая блокировка уже поставлена в другом соединении (в этом случае блокировка не снимается) и NULL, если блокировки с указанным именем не существует. Последнее может произойти в случае, когда вызов функции GET_LOCK() не привел к успешному результату или данная блокировка уже снята. Функцию RELEASE_LOCK() удобно использовать совместно с командой DO. See section 6.4.10 Синтаксис оператора DO.
IS_FREE_LOCK(str)
Проверяет, свободна ли блокировка по имени str (т.е. не установлена). Возвращает 1 если блокировка свободна (никто не поставил таковую). Возвращает 0 если блокировка установлена и NULL в случае ошибки (например, при неправильных аргументах).
BENCHMARK(count,expr)
Функция BENCHMARK() повторяет выполнение выражения expr заданное количество раз, указанное в аргументе count. Она может использоваться для определения того, насколько быстро MySQL обрабатывает данное выражение. Значение результата всегда равно 0. Функция предназначена для использования в клиенте mysql, который сообщает о времени выполнения запроса:
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye")); +----------------------------------------------+ | BENCHMARK(1000000,ENCODE("hello","goodbye")) | +----------------------------------------------+ | 0 | +----------------------------------------------+ 1 row in set (4.74 sec)
Указанное в отчете время представляет собой время, подсчитанное на стороне клиента, а не время, затраченное центральным процессором (CPU time) на сервере. Может оказаться целесообразным выполнить BENCHMARK() несколько раз, чтобы выяснить, насколько интенсивно загружен серверный компьютер.
INET_NTOA(expr)
По заданному числовому адресу сети (4 или 8 байтов) возвращает представление указанного адреса в виде разделенных точками четырех октетов в виде строки:
mysql> SELECT INET_NTOA(3520061480); -> "209.207.224.40"
INET_ATON(expr)
По заданному представлению сетевого адреса в виде строки, содержащей разделенные точками четыре октета, функция возвращает целое число, представляющее собой числовое значение данного адреса. Адреса могут быть длиной 4 или 8 байтов:
mysql> SELECT INET_ATON("209.207.224.40"); -> 3520061480
Результирующее число всегда генерируется в соответствии с порядком расположения октетов в сетевом адресе, например вышеприведенное число вычисляется как 209*256^3 + 207*256^2 + 224*256 +40.
MASTER_POS_WAIT(log_name, log_pos)
Блокируется, пока подчиненный сервер не достигнет определенной точки положения в журнале репликации головного сервера (т.е. не прочитает и не выполнит все операции до указанной позиции).
Если информация головного сервера не инициализирована, или аргументы неправильны, то функция возвращает NULL. Если подчиненный сервер не работает, то функция блокируется и ожидает, пока сервер запустится и дойдет до указанной позиции или пройдет через нее. Если подчиненный сервер уже прошел указанную точку, то функция немедленно возвращает результат.
Если timeout (новшество в 4.0.10) указан, то ожидание прекратится по прошествии timeout секунд. Таймаут должен быть больше 0. 0 или негативный таймаут означает тоже самое что и отсутствие таймаута.
Возвращаемая величина представляет собой число событий в журнале, которые функция должна была ``переждать'', пока сервер дойдет до указанной точки, NULL в случае ошибки или -1 в случае, если истек таймаут.
FOUND_ROWS()
Возвращает количество строк, которые возвратила бы последняя команда SELECT SQL_CALC_FOUND_ROWS ... при отсутствии ограничения оператором LIMIT.
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS();
Второй вызов команды SELECT возвратит количество строк, которые возвратила бы первая команда SELECT, если бы она была написана без выражения LIMIT. Отметим, что, хотя при использовании команды SELECT SQL_CALC_FOUND_ROWS ..., MySQL должен пересчитать все строки в наборе результатов, этот способ все равно быстрее, чем без LIMIT, так как не требуется посылать результат клиенту.
Функция SQL_CALC_FOUND_ROWS появилась в MySQL 4.0.0.
Функции, используемые в операторах GROUP BY
Вызов групповых функций для SQL-команд, не содержащих GROUP BY, эквивалентен выполнению этих функций над всем набором возвращаемых данных.
COUNT(expr)
Возвращает количество величин со значением, не равным NULL, в строках, полученных при помощи команды SELECT:
mysql> SELECT student.student_name,COUNT(*) FROM student,course WHERE student.student_id=course.student_id GROUP BY student_name;
Функция COUNT(*) несколько отличается от описанной выше: она возвращает количество извлеченных строк, содержащих величины со значением NULL. COUNT(*) оптимизирована для очень быстрого возврата результата при условии, что команда SELECT извлекает данные из одной таблицы, никакие другие столбцы не обрабатываются и функция не содержит выражения WHERE. Например:
mysql> SELECT COUNT(*) FROM student;
COUNT(DISTINCT expr,[expr...])
Возвращает количество различающихся величин со значением, не равным NULL:
mysql> SELECT COUNT(DISTINCT results) FROM student;
В MySQL для того, чтобы получить количество различающихся комбинаций выражений, не содержащих NULL, нужно просто задать список этих выражений. В ANSI SQL необходимо провести конкатенацию всех выражений внутри COUNT(DISTINCT ...).
AVG(expr)
Возвращает среднее значение аргумента expr:
mysql> SELECT student_name, AVG(test_score) FROM student GROUP BY student_name;
MIN(expr)
MAX(expr)
Возвращает минимальную или максимальную величину аргумента expr. Функции MIN() и MAX() могут принимать строковый аргумент; в таких случаях они возвращают минимальную или максимальную строковую величину. See section 5.4.3 Использование индексов в MySQL.
mysql> SELECT student_name, MIN(test_score), MAX(test_score) FROM student GROUP BY student_name;
В MIN(), MAX() и других групповых фунциях MySQL сейчас сравнивает ENUM и SET-столбцы по ихнему строковому представлению а не по относительной позиции строки в множестве. Это будет исправлено.
SUM(expr)
Возвращает сумму величин в аргументе expr. Обратите внимание: если возвращаемый набор данных не содержит ни одной строки, то функция возвращает NULL!
VARIANCE(expr)
Возвращает вариант стандарта, которому соответствует expr. Это - расширение по сравнению с ANSI SQL, доступное только в 4.1 или более поздних версиях.
STD(expr)
STDDEV(expr)
Возвращает среднеквадратичное отклонение значения в аргументе expr. Эта функция является расширением ANSI SQL. Форма STDDEV() обеспечивает совместимость с Oracle.
BIT_OR(expr)
Возвращает побитовое ИЛИ для всех битов в expr. Вычисление производится с 64-битовой (BIGINT) точностью.
BIT_AND(expr)
Возвращает побитовое И для всех битов в expr. Вычисление производится с 64-битовой (BIGINT) точностью.
В MySQL расширены возможности использования оператора GROUP BY. Теперь в выражениях SELECT можно использовать столбцы или вычисления, которые не присутствуют в части GROUP BY. Это справедливо для любой возможной величины для этой группы. Данная возможность позволяет повысить производительность за счет исключения сортировки и группирования ненужных величин. Например, в следующем запросе нет необходимости в группировке customer.name:
mysql> SELECT order.custid,customer.name,MAX(payments) FROM order,customer WHERE order.custid = customer.custid GROUP BY order.custid;
В ANSI SQL к предложению GROUP BY необходимо добавлять customer.name. В MySQL, если работа происходит не в режиме ANSI, это имя избыточно.
Не используйте данное свойство, если столбцы, пропущенные в части GROUP BY, не являются уникальными в данной группе! Возможны непредсказуемые результаты.
В некоторых случаях можно применять функции MIN() и MAX() для получения указанной величины столбца, даже если он не является уникальным. В следующем примере выдается значение столбца column из строки, содержащей наименьшую величину в столбце sort:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
See section 3.5.4 Строка, содержащая максимальное значение некоторого столбца.
Следует отметить, что в версии MySQL 3.22 (или более ранней) либо при попытке работы в рамках ANSI SQL применение выражений в предложениях GROUP BY или ORDER BY невозможно. Это ограничение можно обойти, используя для выражения псевдоним:
mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name GROUP BY id,val ORDER BY val;
В версии MySQL 3.23 можно также выполнить следующее:
mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
Функции, используемые в операторах SELECT и WHERE
В команде SQL выражение SELECT или определение WHERE могут включать в себя любое выражение, в котором используются описанные ниже функции.
Выражение, содержащее NULL, всегда будет давать в результате величину NULL, если иное не оговорено в документации для операторов и функций, задействованных в данном выражении.
Примечание: между именем функции и следующими за ним скобками не должно быть пробелов. Это поможет синтаксическому анализатору MySQL отличать вызовы функций от ссылок на таблицы или столбцы, имена которых случайно окажутся теми же, что и у функций. Однако допускаются пробелы до или после аргументов.
Если нужно, чтобы в MySQL допускались пробелы после имени функции, следует запустить mysqld с параметром --ansi или использовать CLIENT_IGNORE_SPACE
в mysql_connect(), но в этом случае все имена функций станут зарезервированными словами. See section 1.9.2 Запуск MySQL в режиме ANSI.
В целях упрощения в данной документации результат выполнения программы mysql в примерах представлен в сокращенной форме. Таким образом вывод:
mysql> SELECT MOD(29,9); 1 rows in set (0.00 sec)
+-----------+ | mod(29,9) | +-----------+ | 2 | +-----------+
будет представлен следующим образом:
mysql> SELECT MOD(29,9); -> 2
Синтаксис оператора JOIN
MySQL поддерживает следующий синтаксис оператора JOIN при использовании в командах SELECT:
table_reference, table_reference table_reference [CROSS] JOIN table_reference table_reference INNER JOIN table_reference join_condition table_reference STRAIGHT_JOIN table_reference table_reference LEFT [OUTER] JOIN table_reference join_condition table_reference LEFT [OUTER] JOIN table_reference table_reference NATURAL [LEFT [OUTER]] JOIN table_reference { OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr } table_reference RIGHT [OUTER] JOIN table_reference join_condition table_reference RIGHT [OUTER] JOIN table_reference table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference
где table_reference определено, как:
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]
и join_condition определено, как:
ON conditional_expr | USING (column_list)
В большинстве случаев не следует указывать в части ON какие бы то ни было условия, накладывающие ограничения на строки в наборе результатов (из этого правила есть исключения). Если необходимо указать, какие строки должны присутствовать в результате, следует сделать это в выражении WHERE.
Необходимо учитывать, что в версиях до 3.23.17 оператор INNER JOIN не принимает параметр join_condition!
Наличие последней из приведенных выше конструкций выражения LEFT OUTER JOIN обусловлено только требованиями совместимости с ODBC:
Вместо ссылки на таблицу может использоваться псевдоним, который присваивается при помощи выражений tbl_name AS alias_name или tbl_name alias_name:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name;
Условный оператор ON представляет собой условие в любой форме из числа тех, которые можно использовать в выражении WHERE.
Если запись для правой таблицы в частях ON или USING в LEFT JOIN не найдена, то для данной таблицы используется строка, в которой все столбцы установлены в NULL. Эту возможность можно применять для нахождения результатов в таблице, не имеющей эквивалента в другой таблице:
mysql> SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
Этот пример находит все строки в таблице table1 с величиной id, которая не присутствует в таблице table2 (т.е. все строки в table1, для которых нет соответствующих строк в table2). Конечно, это предполагает, что table2.id объявлен как NOT NULL. See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.
USING (column_list) служит для указания списка столбцов, которые должны существовать в обеих таблицах. Такое выражение USING, как:
A LEFT JOIN B USING (C1,C2,C3,...)
семантически идентично выражению ON, например:
A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
Выражение NATURAL [LEFT] JOIN для двух таблиц определяется так, чтобы оно являлось семантическим эквивалентом INNER JOIN или LEFT JOIN с выражением USING, в котором указаны все столбцы, имеющиеся в обеих таблицах.
INNER JOIN и , (запятая) являются семантическими эквивалентами. Оба осуществляют полное объединение используемых таблиц. Способ связывания таблиц обычно задается в условии WHERE.
RIGHT JOIN работает аналогично LEFT JOIN. Для сохранения переносимости кода между различными базами данных рекомендуется вместо RIGHT JOIN использовать LEFT JOIN.
STRAIGHT_JOIN идентично JOIN, за исключением того, что левая таблица всегда читается раньше правой. Это выражение может использоваться для тех (немногих) случаев, когда оптимизатор объединения располагает таблицы в неправильном порядке.
Начиная с версии MySQL 3.23.12, можно давать MySQL указания о том, какой индекс должен использоваться при извлечении информации из таблицы. Эта возможность полезна, если оператор EXPLAIN показывает, что MySQL из всех возможных индексов использует ошибочный. Задавая значение индекса в USE INDEX (key_list), можно заставить MySQL применять для поиска записи только один из возможных индексов. Альтернативное выражение IGNORE INDEX (key_list) запрещает использование в MySQL данного конкретного индекса. Выражения USE/IGNORE KEY являются синонимами для USE/IGNORE INDEX.
В MySQL 4.0. 9 можно также указывать FORCE INDEX. Это работает также, как и USE INDEX (key_list) но в дополнение дает понять серверу что полное сканирование таблицы будет ОЧЕНЬ дорогостоящей операцией. Другими словами, в этом случае сканирование таблицы будет использовано только тогда, когда не будет найдено другого способа использовать один из данных индексов для поиска записей в таблице.
Несколько примеров:
mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id); mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id; mysql> SELECT * FROM table1 USE INDEX (key1,key2) WHERE key1=1 AND key2=2 AND key3=3; mysql> SELECT * FROM table1 IGNORE INDEX (key3) WHERE key1=1 AND key2=2 AND key3=3;
See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.
Синтаксис оператора UNION
SELECT ... UNION [ALL] SELECT ... [UNION SELECT ...]
Оператор UNION реализован в MySQL 4.0.0.
UNION используется для объединения результатов работы нескольких команд SELECT в один набор результатов.
Столбцы, перечисленные в части select_expression должны быть одинакового типа. Имена столбцов, указанные в первом SELECT будут использованы как имена столбцов для всего результата.
Эти команды SELECT являются обычными командами выборки данных, но со следующим ограничением:
Только последняя команда SELECT может включать оператор INTO OUTFILE.
Если не используется ключевое слово ALL для UNION, все возвращенные строки будут уникальными, так как по умолчанию подразумевается DISTINCT для всего результирующего набора данных. Если указать ключевое слово ALL, то результат будет содержать все найденные строки из всех примененных команд SELECT.
Если для всего результата UNION необходимо применить оператор ORDER BY, следует использовать круглые скобки:
(SELECT a FROM table_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM table_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10) ORDER BY a;
Синтаксис оператора SELECT
Оператор SELECT имеет следующую структуру:
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY] [DISTINCT | DISTINCTROW | ALL] select_expression,... [INTO {OUTFILE | DUMPFILE} 'file_name' export_options] [FROM table_references [WHERE where_definition] [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...] [HAVING where_definition] [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC], ...] [LIMIT [offset,] rows | rows OFFSET offset] [PROCEDURE procedure_name(argument_list)] [FOR UPDATE | LOCK IN SHARE MODE]]
SELECT применяется для извлечения строк, выбранных из одной или нескольких таблиц. Выражение select_expression задает столбцы, в которых необходимо проводить выборку. Кроме того, оператор SELECT можно использовать для извлечения строк, вычисленных без ссылки на какую-либо таблицу. Например:
mysql> SELECT 1 + 1; -> 2
При указании ключевых слов следует точно соблюдать порядок, указанный выше. Например, выражение HAVING должно располагаться после всех выражений GROUP BY и перед всеми выражениями ORDER BY.
Используя ключевое слово AS, выражению в SELECT можно присвоить псевдоним. Псевдоним используется в качестве имени столбца в данном выражении и может применяться в ORDER BY или HAVING. Например:
mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
Псевдонимы столбцов нельзя использовать в выражении WHERE, поскольку находящиеся в столбцах величины на момент выполнения WHERE могут быть еще не определены. See section A.5.4 Проблемы с alias.
Выражение FROM table_references задает таблицы, из которых надлежит извлекать строки. Если указано имя более чем одной таблицы, следует выполнить объединение. Информацию о синтаксисе объединения можно найти в разделе section 6.4.1.1 Синтаксис оператора JOIN. Для каждой заданной таблицы по желанию можно указать псевдоним.
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]
В версии MySQL 3.23. 12 можно указывать, какие именно индексы (ключи) MySQL должен применять для извлечения информации из таблицы. Это полезно, если оператор EXPLAIN (выводящий информацию о структуре и порядке выполнения запроса SELECT), показывает, что MySQL из списка возможных индексов выбрал неправильный. Если нужно. чтобы для поиска записи в таблице применялся только один из возможных индексов, следует задать значение этого индекса в USE INDEX
(key_list). Альтернативное выражение IGNORE INDEX (key_list) запрещает использование в MySQL данного конкретного индекса.
В MySQL 4.0.9 можно также указывать FORCE INDEX. Это работает также, как и USE INDEX (key_list) но в дополнение дает понять серверу что полное сканирование таблицы будет ОЧЕНЬ дорогостоящей операцией. Другими словами, в этом случае сканирование таблицы будет использовано только тогда, когда не будет найдено другого способа использовать один из данных индексов для поиска записей в таблице.
Выражения USE/IGNORE KEY являются синонимами для USE/IGNORE INDEX.
Ссылки на таблицы могут даваться как tbl_name (в рамках текущей базы данных), или как dbname.tbl_name с тем, чтобы четко указать базу данных.
Ссылки на столбцы могут задаваться в виде col_name, tbl_name.col_name
или db_name.tbl_name.col_name. В выражениях tbl_name или db_name.tbl_name нет необходимости указывать префикс для ссылок на столбцы в команде SELECT, если эти ссылки нельзя истолковать неоднозначно. See section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы, где приведены примеры неоднозначных случаев, для которых требуются более четкие определения ссылок на столбцы.
Ссылку на таблицу можно заменить псевдонимом, используя tbl_name [AS] alias_name:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name;
mysql> SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
В выражениях ORDER BY и GROUP BY для ссылок на столбцы, выбранные для вывода информации, можно использовать либо имена столбцов, либо их псевдонимы, либо их позиции (местоположения). Нумерация позиций столбцов начинается с 1:
mysql> SELECT college, region, seed FROM tournament ORDER BY region, seed;
mysql> SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s;
mysql> SELECT college, region, seed FROM tournament ORDER BY 2, 3;
Для того чтобы сортировка производилась в обратном порядке, в утверждении ORDER BY к имени заданного столбца, в котором производится сортировка, следует добавить ключевое слово DESC (убывающий). По умолчанию принята сортировка в возрастающем порядке, который можно задать явно при помощи ключевого слова ASC.
В выражении WHERE можно использовать любую из функций, которая поддерживается в MySQL. See section 6.3 Функции, используемые в операторах SELECT и WHERE.
Выражение HAVING может ссылаться на любой столбец или псевдоним, упомянутый в выражении select_expression. HAVING отрабатывается последним, непосредственно перед отсылкой данных клиенту, и без какой бы то ни было оптимизации. Не используйте это выражение для определения того, что должно быть определено в WHERE. Например, нельзя задать следующий оператор:
mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
Вместо этого следует задавать:
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
В версии MySQL 3.22.5 или более поздней можно также писать запросы, как показано ниже:
mysql> SELECT user,MAX(salary) FROM users GROUP BY user HAVING MAX(salary)>10;
В более старых версиях MySQL вместо этого можно указывать:
mysql> SELECT user,MAX(salary) AS sum FROM users GROUP BY user HAVING sum>10;
Параметры (опции) DISTINCT, DISTINCTROW и ALL указывают, должны ли возвращаться дублирующиеся записи. По умолчанию установлен параметр (ALL), т.е. возвращаются все встречающиеся строки. DISTINCT и DISTINCTROW являются синонимами и указывают, что дублирующиеся строки в результирующем наборе данных должны быть удалены.
Все параметры, начинающиеся с SQL_, STRAIGHT_JOIN и HIGH_PRIORITY, представляют собой расширение MySQL для ANSI SQL.
При указании параметра HIGH_PRIORITY содержащий его оператор SELECT
будет иметь более высокий приоритет, чем команда обновления таблицы. Нужно только использовать этот параметр с запросами, которые должны выполняться очень быстро и сразу. Если таблица заблокирована для чтения, то запрос SELECT HIGH_PRIORITY будет выполняться даже при наличии команды обновления, ожидающей, пока таблица освободится.
Параметр SQL_BIG_RESULT можно использовать с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что результат будет содержать большое количество строк. Если указан этот параметр, MySQL при необходимости будет непосредственно использовать временные таблицы на диске, однако предпочтение будет отдаваться не созданию временной таблицы с ключом по элементам GROUP BY, а сортировке данных.
При указании параметра SQL_BUFFER_RESULT MySQL будет заносить результат во временную таблицу. Таким образом MySQL получает возможность раньше снять блокировку таблицы; это полезно также для случаев, когда для посылки результата клиенту требуется значительное время.
Параметр SQL_SMALL_RESULT является опцией, специфической для MySQL. Данный параметр можно использовать с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что результирующий набор данных будет небольшим. В этом случае MySQL для хранения результирующей таблицы вместо сортировки будет использовать быстрые временные таблицы. В версии MySQL 3.23 указывать данный параметр обычно нет необходимости.
Параметр SQL_CALC_FOUND_ROWS (MySQL 4.0.0 и более новый) возвращает количество строк, которые вернул бы оператор SELECT, если бы не был указан LIMIT. Искомое количество строк можно получить при помощи SELECT FOUND_ROWS(). See section 6.3.6.2 Разные функции.
Заметьте, что в версиях MySQL до 4.1.0 это не работает с LIMIT 0, который оптимизирован для того, чтобы немедленно вернуть нулевой результат. See section 5.2.8 Как MySQL оптимизирует LIMIT.
Параметр SQL_CACHE предписывает MySQL сохранять результат запроса в кэше запросов при использовании QUERY_CACHE_TYPE=2 (DEMAND). See section 6.9 Кэш запросов в MySQL.
Параметр SQL_NO_CACHE запрещает MySQL хранить результат запроса в кэше запросов. See section 6.9 Кэш запросов в MySQL.
При использовании выражения GROUP BY строки вывода будут сортироваться в соответствии с порядком, заданным в GROUP BY, - так, как если бы применялось выражение ORDER BY для всех полей, указанных в GROUP BY. В MySQL выражение GROUP BY расширено таким образом, что для него можно также указывать параметры ASC и DESC:
SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
Расширенный оператор GROUP BY в MySQL обеспечивает, в частности, возможность выбора полей, не упомянутых в выражении GROUP BY. Если ваш запрос не приносит ожидаемых результатов, прочтите, пожалуйста, описание GROUP BY. See section 6.3.7 Функции, используемые в операторах GROUP BY.
При указании параметра STRAIGHT_JOIN оптимизатор будет объединять таблицы в том порядке, в котором они перечислены в выражении FROM. Применение данного параметра позволяет увеличить скорость выполнения запроса, если оптимизатор производит объединение таблиц неоптимальным образом. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).
Выражение LIMIT может использоваться для ограничения количества строк, возвращенных командой SELECT. LIMIT принимает один или два числовых аргумента. Эти аргументы должны быть целочисленными константами. Если заданы два аргумента, то первый указывает на начало первой возвращаемой строки, а второй задает максимальное количество возвращаемых строк. При этом смещение начальной строки равно 0 (не 1):
Для совместимости с PostgreSQL MySQL также поддерживает синтаксис LIMIT # OFFSET #.
mysql> SELECT * FROM table LIMIT 5,10; # возвращает строки 6-15
Для того, чтобы выбрать все строки с определенного смещения и до конца результата, вы можете использовать значение -1 в качестве второго параметра:
mysql> SELECT * FROM table LIMIT 95,-1; # Retrieve rows 96-last.
Если задан один аргумент, то он показывает максимальное количество возвращаемых строк:
mysql> SELECT * FROM table LIMIT 5; # возвращает первых 5 строк
Другими словами, LIMIT n эквивалентно LIMIT 0,n.
Оператор SELECT может быть представлен в форме SELECT ... INTO OUTFILE 'file_name'. Эта разновидность команды осуществляет запись выбранных строк в файл, указанный в file_name. Данный файл создается на сервере и до этого не должен существовать (таким образом, помимо прочего, предотвращается разрушение таблиц и файлов, таких как `/etc/passwd'). Для использования этой формы команды SELECT необходимы привилегии FILE. Форма SELECT ... INTO OUTFILE главным образом предназначена для выполнения очень быстрого дампа таблицы на серверном компьютере. Команду SELECT ... INTO OUTFILE нельзя применять, если необходимо создать результирующий файл на ином хосте, отличном от серверного. В таком случае для генерации нужного файла вместо этой команды следует использовать некоторую клиентскую программу наподобие mysqldump --tab или mysql -e "SELECT ..." > outfile. Команда SELECT ... INTO OUTFILE является дополнительной по отношению к LOAD DATA INFILE; синтаксис части export_options этой команды содержит те же выражения FIELDS и LINES, которые используются в команде LOAD DATA INFILE. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE. Следует учитывать, что в результирующем текстовом файле оператор ESCAPED BY экранирует только следующие символы:
Символ оператора ESCAPED BY
Первый символ оператора FIELDS TERMINATED BY
Первый символ оператора LINES TERMINATED BY
Помимо этого ASCII-символ 0 конвертируется в ESCAPED BY, за которым следует символ `0' (ASCII 48). Это делается потому, что необходимо экранировать любые символы операторов FIELDS TERMINATED BY, ESCAPED BY
или LINES TERMINATED BY, чтобы иметь надежную возможность повторить чтение этого файла. ASCII 0 экранируется, чтобы облегчить просмотр файла с помощью программ вывода типа pager. Поскольку результирующий файл не должен удовлетворять синтаксису SQL, нет необходимости экранировать что-либо еще. Ниже приведен пример того, как получить файл в формате, который используется многими старыми программами.
SELECT a,b,a+b INTO OUTFILE "/tmp/result.text" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\n" FROM test_table;
Если вместо INTO OUTFILE использовать INTO DUMPFILE, то MySQL запишет в файл только одну строку без символов завершения столбцов или строк и без какого бы то ни было экранирования. Это полезно для хранения данных типа BLOB в файле.
Следует учитывать, что любой файл, созданный с помощью INTO OUTFILE и INTO DUMPFILE, будет доступен для записи всем пользователям! Причина этого заключается в следующем: сервер MySQL не может создавать файл, принадлежащий только какому-либо текущему пользователю (вы никогда не можете запустить mysqld от пользователя root), соответственно, файл должен быть доступен для записи всем пользователям.
При использовании FOR UPDATE с обработчиком таблиц, поддерживающим блокировку страниц/строк, выбранные строки будут заблокированы для записи.
Синтаксис оператора HANDLER
HANDLER tbl_name OPEN [ AS alias ] HANDLER tbl_name READ index_name { = | >= |
Оператор HANDLER обеспечивает прямой доступ к интерфейсу обработчика таблиц MyISAM.
Первая форма оператора HANDLER открывает таблицу, делая ее доступной для последовательности команд HANDLER ... READ. Этот объект недоступен другим потокам и не будет закрыт, пока данный поток не вызовет HANDLER tbl_name CLOSE или сам поток не будет уничтожен.
Вторая форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), для которой(ых) указанный индекс соответствует заданному условию и условие в выражении WHERE также выполняется. Если индекс состоит из нескольких частей (охватывает несколько столбцов), то составляющие его величины указываются в виде разделенного запятыми списка. Обеспечиваются величины только для нескольких первых столбцов.
Третья форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), из таблицы; в порядке указания индексов в соответствии с условием WHERE.
Четвертая форма (без указания индексов) выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), из таблицы, используя естественный порядок строк (как они хранятся в файле данных), в соответствии с условием WHERE. Эта форма работает быстрее, чем HANDLER tbl_name READ index_name, в тех случаях, когда желателен просмотр всей таблицы.
Оператор HANDLER ... CLOSE закрывает таблицу, открытую оператором HANDLER ... OPEN.
Оператор HANDLER представляет собой что-то наподобие низкоуровневой команды. Например, он не обеспечивает целостности таблицы. Т.е. HANDLER ... OPEN НЕ делает моментального снимка таблицы и НЕ блокирует ее. Отсюда следует, что после вызова команды HANDLER ... OPEN данные таблицы могут быть модифицированы (этим или любым другим потоком), а сами модификации в просмотрах таблицы при помощи HANDLER ... NEXT или HANDLER ... PREV могут появляться только частично.
Вот причины, по которым вы можете предпочесть HANDLER вместо обычного SQL:
Он быстрее чем SELECT, потому что:
Выделенный код обработчика таблиц создается в потоке по вызову HANDLER open.
Меньше синтаксического анализа.
Нет нагрузки на оптимизацию и проверку.
Таблицу не нужно блокировать между запросами.
Этот интерфейс не обязан предоставлять целостный вид данных (скажем, грязное чтение допускается), что позволяет обработчику таблиц делать оптимизации которые SQL обычно не допускает.
Гораздо легче переносить на MySQL приложения, которые используют интерфейс, подобный ISAM.
Такой интерфейс позволяет просматривать базу данных способом, который не так легко (или в некоторых случаях и вовсе невозможно) реализовать с помощью SQL. Интерфейс HANDLER является более естественным способом получить данные, когда приходится иметь дело с интерактивными пользовательскими приложениями.
Синтаксис оператора INSERT ... SELECT
INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column list)] SELECT ...
Команда INSERT ... SELECT обеспечивает возможность быстрого внесения большого количества строк в таблицу из одной или более таблиц.
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;
Для команды INSERT ... SELECT необходимо соблюдение следующих условий:
Целевая таблица команды INSERT не должна появляться в утверждении FROM
части SELECT данного запроса, поскольку в ANSI SQL запрещено производить выборку из той же таблицы, в которую производится вставка. (Проблема заключается в том, что операция SELECT, возможно, найдет записи, которые были внесены ранее в течение того же самого прогона команды. При использовании команд, внутри которых содержатся многоступенчатые выборки, можно легко попасть в очень запутанную ситуацию!)
Столбцы AUTO_INCREMENT работают, как обычно.
Для получения информации о данном запросе можно использовать функцию C API mysql_info(). See section 6.4.3 Синтаксис оператора INSERT.
Чтобы гарантировать возможность использования журнала обновлений/двоичного журнала для восстановления исходного состояния таблиц, в MySQL во время выполнения команды INSERT ... SELECT параллельные вставки не разрешаются.
Разумеется, для перезаписи старых строк можно вместо INSERT использовать REPLACE.
Синтаксис оператора INSERT
INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] VALUES (expression,...),(...),... [ ON DUPLICATE KEY UPDATE col_name=expression, ... ] или INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ... или INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=(expression | DEFAULT), ... [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]
Оператор INSERT вставляет новые строки в существующую таблицу. Форма данной команды INSERT ... VALUES вставляет строки в соответствии с точно указанными в команде значениями. Форма INSERT ... SELECT вставляет строки, выбранные из другой таблицы или таблиц. Форма INSERT ... VALUES со списком из нескольких значений поддерживается в версии MySQL 3.22.5 и более поздних. Синтаксис выражения col_name=expression поддерживается в версии MySQL 3.22.10 и более поздних.
tbl_name задает таблицу, в которую должны быть внесены строки. Столбцы, для которых заданы величины в команде, указываются в списке имен столбцов или в части SET:
Если не указан список столбцов для INSERT ... VALUES или INSERT ... SELECT, то величины для всех столбцов должны быть определены в списке VALUES() или в результате работы SELECT. Если порядок столбцов в таблице неизвестен, для его получения можно использовать DESCRIBE tbl_name.
Любой столбец, для которого явно не указано значение, будет установлен в свое значение по умолчанию. Например, если в заданном списке столбцов не указаны все столбцы в данной таблице, то не упомянутые столбцы устанавливаются в свои значения по умолчанию. Установка значений по умолчанию описывается в разделе section 6.5.3 Синтаксис оператора CREATE TABLE.
Вы также можете использовать ключевое слово DEFAULT для того, чтобы установить столбец в его значение по умолчанию (новшество в MySQL 4.0.3). Это облегчает написание INSERT, присвающим значения всем, за исключением одного-двух, столбцам, т.к. такой ситнаксис позволяет вам обойтись без указания списка столбцов, которые оператор INSERT должен обновить.
В MySQL всегда предусмотрено значение по умолчанию для каждого поля. Это требование ``навязано'' MySQL, чтобы обеспечить возможность работы как с таблицами, поддерживающими транзакции, так и с таблицами, не поддерживающими их.
Наша точка зрения (разработчиков) состоит в том, что проверка содержимого полей должна производиться приложением, а не сервером баз данных.
Выражение expression может относится к любому столбцу, который ранее был внесен в список значений. Например, можно указать следующее:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
Но нельзя указать:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды INSERT будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы. В этом случае данный клиент должен ожидать, пока данная команда вставки не будет завершена, что в случае интенсивного использования таблицы может потребовать значительного времени. В противоположность этому команда INSERT DELAYED позволяет данному клиенту продолжать операцию сразу же. See section 6.4.4 Синтаксис оператора INSERT DELAYED. Следует отметить, что указатель LOW_PRIORITY обычно не используется с таблицами MyISAM, поскольку при его указании становятся невозможными параллельные вставки. See section 7.1 Таблицы MyISAM.
Если в команде INSERT со строками, имеющими много значений, указывается ключевое слово IGNORE, то все строки, имеющие дублирующиеся ключи PRIMARY или UNIQUE в этой таблице, будут проигнорированы и не будут внесены. Если не указывать IGNORE, то данная операция вставки прекращается при обнаружении строки, имеющей дублирующееся значение существующего ключа. Количество строк, внесенных в данную таблицу, можно определить при помощи функции C API mysql_info().
Если вы указываете ON DUPLICATE KEY UPDATE (новшество в MySQL 4.1.0), и производится вставка строки, которая вызывает ошибку дублирующегося первичного (PRIMARY) или уникального (UNIQUE) ключа, то вполняется UPDATE старой строки.
Например:
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3) --> ON DUPLICATE KEY UPDATE c=c+1;
Если a определяется как UNIQUE и уже содержит 1, то тогда вышеуказанная команда будет аналогична следующей:
mysql> UPDATE table SET c=c+1 WHERE a=1;
Внимание: если столбец b также является уникальным ключем, то UPDATE переписывается как:
mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
и если несколько записей соответствуют a=1 OR b=2 только одна запись будет обновлена! В общем случае, следует избегать использования ON DUPLICATE KEY на таблицах со множеством уникальных (UNIQUE) ключей.
Когда используется ON DUPLICATE KEY UPDATE, опция DELAYED будет проигнорирована.
Если MySQL был сконфигурирован с использованием опции DONT_USE_DEFAULT_FIELDS, то команда INSERT будет генерировать ошибку, если явно не указать величины для всех столбцов, которые требуют значений не-NULL. See section 2.3.3 Типичные опции configure.
С помощью функции mysql_insert_id можно найти величину, использованную для столбца AUTO_INCREMENT. See section 8.4.3.31 mysql_insert_id().
Если задается команда INSERT ... SELECT или INSERT ... VALUES со списками из нескольких значений, то для получения информации о данном запросе можно использовать функцию C API mysql_info(). Формат этой информационной строки приведен ниже:
Records: 100 Duplicates: 0 Warnings: 0
Duplicates показывает число строк, которые не могли быть внесены, поскольку они дублировали бы значения некоторых существующих уникальных индексов. Указатель Warnings показывает число попыток внести величину в столбец, который по какой-либо причине оказался проблематичным. Предупреждения возникают при выполнении любого из следующих условий:
Внесение NULL в столбец, который был объявлен, как NOT NULL. Данный столбец устанавливается в значение, заданное по умолчанию.
Установка числового столбца в значение, лежащее за пределами его допустимого диапазона. Данная величина усекается до соответствующей конечной точки этого диапазона.
Занесение в числовой столбец такой величины, как '10.34 a'. Конечные данные удаляются и вносится только оставшаяся числовая часть. Если величина вовсе не имеет смысла как число, то столбец устанавливается в 0.
Внесение в столбцы типа CHAR, VARCHAR, TEXT или BLOB строки, превосходящей максимальную длину столбца. Данная величина усекается до максимальной длины столбца.
Внесение в столбец даты или времени строки, недопустимой для данного типа столбца. Этот столбец устанавливается в нулевую величину, соответствующую данному типу.
Синтаксис оператора INSERT DELAYED
INSERT DELAYED ...
Опция DELAYED для команды INSERT является специфической для MySQL возможностью, которая очень полезна, если клиент не может ждать завершения команды INSERT. Такая проблема встречается часто - она возникает, когда MySQL используется для ведения журналов (проще говоря, для логгинга) и при этом периодически запускаются команды SELECT и UPDATE, для выполнения которых требуется много времени. Оператор DELAYED был введен в версию MySQL 3.22.15. Он является расширением MySQL к ANSI SQL92.
INSERT DELAYED работает только с таблицами типа ISAM и MyISAM. Следует учитывать, что таблицы MyISAM поддерживают одновременное выполнение SELECT
и INSERT, поэтому если нет свободных блоков в середине файла данных, то необходимость в применении INSERT DELAYED возникает очень редко. See section 7.1 Таблицы MyISAM.
При использовании оператора INSERT DELAYED клиент сразу же получает успешный ответ от сервера, а запись будет добавлена в таблицу сразу же после того, как эту таблицу перестанет использовать другой поток.
Еще одно существенное преимущество применения оператора INSERT DELAYED
заключается в том, что данные от многих клиентов собираются вместе и записываются одним блоком. Это намного быстрее, чем несколько отдельных операций вставки.
Обратите внимание: в настоящее время все записи, поставленные в очередь на добавление, хранятся только в памяти до тех пор, пока они не будут записаны на диск. Отсюда следует, что если выполнение mysqld будет завершено принудительно (kill -9) или программа умрет, то все находящиеся в очереди данные, которые не записаны на диск, будут потеряны!.
Ниже детально описано, что происходит при использовании опции DELAYED в командах INSERT или REPLACE. В этом описании ``поток'' понимается как поток, принимающий команду INSERT DELAYED, а ``обработчик'' - это поток, который обрабатывает все команды INSERT DELAYED в конкретной таблице.
При выполнении потоком команды DELAYED для таблицы создается поток-обработчик для обработки всех команд DELAYED в данной таблице, если подобный обработчик уже не существует.
Данный поток проверяет, выполнил ли уже обработчик блокировку DELAYED; если нет, то он предписывает обработчику сделать это. Блокировка DELAYED может быть осуществлена даже в случае, если блокировки READ
или WRITE на данной таблице уже выполнены другими потоками. Однако обработчик будет ожидать всех блокировок ALTER TABLE и завершения всех команд FLUSH TABLES, чтобы убедиться в том, что структура таблицы соответствует последнему обновлению.
Поток выполняет команду INSERT, но вместо записи строки в таблицу он ставит финальную копию этой строки в очередь, управляемую потоком-обработчиком. Поток отмечает все синтаксические ошибки и сообщает о них клиентской программе.
Клиент не может уведомить о количестве дубликатов или значении AUTO_INCREMENT для данной результирующей строки; он также не может получить эти данные с сервера, поскольку команда INSERT возвращает результат до полного завершения операции вставки. По той же причине ничего существенного не даст и использование функции C API mysql_info().
Обновление журнала обновлений производится потоком-обработчиком после вставки строки в таблицу. В случае многострочной вставки обновление журнала обновлений производится при записи первой строки.
После записи каждых delayed_insert_limit строк, обработчик проверяет, не находятся ли в ожидании выполнения какие-либо команды SELECT. Если да, то обработчик перед продолжением своей работы ``пропускает их вперед'' на выполнение.
Если очередь обработчика больше не содержит строк, то с данной таблицы будет снята блокировка. Если в течение delayed_insert_timeout секунд не поступят никакие новые команды INSERT DELAYED, то обработчик завершит свою работу.
Если более, чем delayed_queue_size строк уже ожидают в очереди обработчика, то поток, запрашивающий INSERT DELAYED, будет ждать, пока не освободится место в очереди. Таким образом можно иметь уверенность в том, что mysqld не займет всю память сервера для хранения запросов данной очереди.
Поток-обработчик будет наблюдаться в списке процессов MySQL со значением delayed_insert в столбце Command. Поток-обработчик можно уничтожить запуском команды FLUSH TABLES или командой KILL номер_потока. Однако перед своим завершением он вначале сохранит в таблице все поставленные в очередь строки. В процессе сохранения он не будет принимать никаких новых команд INSERT от иного потока. При выполнении после этого команды INSERT DELAYED будет создан новый поток-обработчик. Обратите внимание: отсюда следует, что команды INSERT DELAYED имеют более высокий приоритет, чем обычные команды INSERT, если уже существует запущенный обработчик INSERT DELAYED! Другие команды обновления должны ожидать, пока не опустеет очередь INSERT DELAYED или же пока кто-либо не прекратит выполнение потока-обработчика (с помощью KILL номер_потока) или не выполнит FLUSH TABLES.
Представленные в таблице переменные обеспечивают информацию об INSERT DELAYED:
Переменная | Значение |
Delayed_insert_threads | Количество потоков-обработчиков |
Delayed_writes | Количество строк, записанных INSERT DELAYED |
Not_flushed_delayed_rows | Количество строк, ожидающих записи |
Чтобы увидеть эти переменные, следует вызвать команду SHOW STATUS или выполнить команду mysqladmin extended-status.
Обратите внимание: если данная таблица не используется, то команда INSERT DELAYED работает медленнее, чем обычная команда INSERT. Кроме того, возникает дополнительная нагрузка на сервер, поскольку требуется управлять отдельным потоком для каждой таблицы, для которой используется INSERT DELAYED. Это означает, что команду INSERT DELAYED следует применять только тогда, когда в ней есть реальная необходимость!
Синтаксис оператора UPDATE
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition] [ORDER BY ...] [LIMIT rows]
или
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...] SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]
Оператор UPDATE обновляет столбцы в соответствии с их новыми значениями в строках существующей таблицы. В выражении SET указывается, какие именно столбцы следует модифицировать и какие величины должны быть в них установлены. В выражении WHERE, если оно присутствует, задается, какие строки подлежат обновлению. В остальных случаях обновляются все строки. Если задано выражение ORDER BY, то строки будут обновляться в указанном в нем порядке.
Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды UPDATE задерживается до тех пор, пока другие клиенты не завершат чтение этой таблицы.
Если указывается ключевое слово IGNORE, то команда обновления не будет прервана, даже если при обновлении возникнет ошибка дублирования ключей. Строки, из-за которых возникают конфликтные ситуации, обновлены не будут.
Если доступ к столбцу из указанного выражения осуществляется по аргументу tbl_name, то команда UPDATE использует для этого столбца его текущее значение. Например, следующая команда устанавливает столбец age в значение, на единицу большее его текущей величины:
mysql> UPDATE persondata SET age=age+1;
Значения команда UPDATE присваивает слева направо. Например, следующая команда дублирует столбец age, затем инкрементирует его:
mysql> UPDATE persondata SET age=age*2, age=age+1;
Если столбец устанавливается в его текущее значение, то MySQL замечает это и не обновляет его.
Команда UPDATE возвращает количество фактически измененных строк. В версии MySQL 3.22 и более поздних функция C API mysql_info() возвращает количество строк, которые были найдены и обновлены, и количество предупреждений, имевших место при выполнении UPDATE.
В версии MySQL 3.23 можно использовать LIMIT #, чтобы убедиться, что было изменено только заданное количество строк.
Начиная с версии MySQL 4.0.4 вы также можете выполнять UPDATE, охватывающий множество таблиц:
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
Обратите внимание: вы не можете использовать ORDER BY или LIMIT для многотабличных обновлений.
Синтаксис оператора DELETE
DELETE [LOW_PRIORITY] [QUICK] FROM table_name [WHERE where_definition] [ORDER BY ...] [LIMIT rows]
или
DELETE [LOW_PRIORITY] [QUICK] table_name[.*] [, table_name[.*] ...] FROM table-references [WHERE where_definition]
или
DELETE [LOW_PRIORITY] [QUICK] FROM table_name[.*] [, table_name[.*] ...] USING table-references [WHERE where_definition]
Оператор DELETE удаляет из таблицы table_name строки, удовлетворяющие заданным в where_definition условиям, и возвращает число удаленных записей.
Если оператор DELETE запускается без определения WHERE, то удаляются все строки. При работе в режиме AUTOCOMMIT это будет аналогично использованию оператора TRUNCATE. See section 6.4.7 Синтаксис оператора TRUNCATE. В MySQL 3.23 оператор DELETE без определения WHERE возвратит ноль как число удаленных записей.
Если действительно необходимо знать число удаленных записей при удалении всех строк, и если допустимы потери в скорости, то можно использовать команду DELETE в следующей форме:
mysql> DELETE FROM table_name WHERE 1>0;
Следует учитывать, что эта форма работает намного медленнее, чем DELETE FROM table_name без выражения WHERE, поскольку строки удаляются поочередно по одной.
Если указано ключевое слово LOW_PRIORITY, выполнение данной команды DELETE
будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы.
Если задан параметр QUICK, то обработчик таблицы при выполнении удаления не будет объединять индексы - в некоторых случаях это может ускорить данную операцию.
В таблицах MyISAM удаленные записи сохраняются в связанном списке, а последующие операции INSERT повторно используют места, где располагались удаленные записи. Чтобы возвратить неиспользуемое пространство и уменьшить размер файлов, можно применить команду OPTIMIZE TABLE или утилиту myisamchk для реорганизации таблиц. Команда OPTIMIZE TABLE проще, но утилита myisamchk работает быстрее. See section 4.5.1 Синтаксис команды OPTIMIZE TABLE. See section 4.4.6.10 Оптимизация таблиц.
Первый из числа приведенных в начале данного раздела многотабличный формат команды DELETE поддерживается, начиная с MySQL 4.0.0. Второй многотабличный формат поддерживается, начиная с MySQL 4.0.2.
Идея заключается в том, что удаляются только совпадающие строки из таблиц, перечисленных перед выражениями FROM или USING. Это позволяет удалять единовременно строки из нескольких таблиц, а также использовать для поиска дополнительные таблицы.
Символы .* после имен таблиц требуются только для совместимости с Access:
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
или
DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
В предыдущем случае просто удалены совпадающие строки из таблиц t1 и t2.
Если применяется выражение ORDER BY (доступно с версии MySQL 4.0), то строки будут удалены в указанном порядке. В действительности это выражение полезно только в сочетании с LIMIT. Например:
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp LIMIT 1
Данный оператор удалит самую старую запись (по timestamp), в которой строка соответствует указанной в выражении WHERE.
Специфическая для MySQL опция LIMIT для команды DELETE указывает серверу максимальное количество строк, которые следует удалить до возврата управления клиенту. Эта опция может использоваться для гарантии того, что данная команда DELETE не потребует слишком много времени для выполнения. Можно просто повторять команду DELETE до тех пор, пока количество удаленных строк меньше, чем величина LIMIT.
С MySQL 4.0 вы можете указать множество таблиц в DELETE чтобы удалить записи из одной таблицы, основываясь на условии по множеству таблиц. Однако, с такой формой оператора DELETE нельзя использовать ORDER BY или LIMIT.
Синтаксис оператора TRUNCATE
TRUNCATE TABLE table_name
В версии 3.23 TRUNCATE TABLE выполняет последовательность "COMMIT ; DELETE FROM table_name". See section 6.4.6 Синтаксис оператора DELETE.
TRUNCATE TABLE имеет следующие отличия от DELETE FROM ...:
Эта операция удаляет и воссоздает таблицу, что намного быстрее, чем поочередное удаление строк.
Операция является нетранзакционной; если одновременно выполняется транзакция или активная блокировка таблицы, то можно получить ошибку.
Не возвращает количество удаленных строк.
Пока существует корректный файл `table_name.frm', таблицу можно воссоздать с его с помощью, даже если файлы данных или индексов повреждены.
TRUNCATE является расширением Oracle SQL.
Синтаксис оператора REPLACE
REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] VALUES (expression,...),(...),... или REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] SELECT ... или REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name SET col_name=expression, col_name=expression,...
Оператор REPLACE работает точно так же, как INSERT, за исключением того, что если старая запись в данной таблице имеет то же значение индекса UNIQUE или PRIMARY KEY, что и новая, то старая запись перед занесением новой будет удалена. See section 6.4.3 Синтаксис оператора INSERT.
Другими словами, команда REPLACE не предоставляет доступа к замещаемой записи. В некоторых старых версиях MySQL такой доступ иногда оказывался возможным, но это был дефект, который уже исправлен.
Для использования REPLACE у вас должны быть привилегии INSERT и DELETE для таблицы.
При использовании команды REPLACE функция mysql_affected_rows() вернет значение, равное 2, если старая строка была заменена новой. Объясняется это тем, что в таблицу вставляется строка после того, как удаляется дубликат.
Это позволяет легко определять, какое действие произвела команда REPLACE - добавление или замещение строки. Достаточно просто проверить, какое число вернула функция mysql_affected_rows() - 1 (строка добавлена) или 2
(замещена).
Следует учитывать, что, если не используются индексы UNIQUE или PRIMARY KEY, то применение команды REPLACE не имеет смысла, так как она работает просто как INSERT.
Синтаксис оператора LOAD DATA INFILE
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE tbl_name [FIELDS [TERMINATED BY '\t'] [[OPTIONALLY] ENCLOSED BY ''] [ESCAPED BY '\\' ] ] [LINES TERMINATED BY '\n'] [IGNORE number LINES] [(col_name,...)]
Команда LOAD DATA INFILE читает строки из текстового файла и вставляет их в таблицу с очень высокой скоростью. Если задано ключевое слово LOCAL, то файл читается с клиентского хоста. Если же LOCAL не указывается, то файл должен находиться на сервере. (Опция LOCAL доступна в версии MySQL 3.22.6 и более поздних.)
Если текстовые файлы, которые нужно прочитать, находятся на сервере, то из соображений безопасности эти файлы должны либо размещаться в директории базы данных, либо быть доступными для чтения всем пользователям. Кроме того, для применения команды LOAD DATA INFILE к серверным файлам необходимо обладать привилегиями FILE для серверного хоста. See section 4.2.7 Привилегии, предоставляемые MySQL.
В версиях MySQL 3.23.49 и MySQL 4.0.2 команда LOCAL не будет работать в случаях, если демон mysqld запущен с параметром --local-infile=0 или если для клиента не включена возможность поддержки LOCAL. See section 4.2.4 Вопросы безопасности, относящиеся к команде LOAD DATA LOCAL.
Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды LOAD DATA будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы.
Если указывается ключевое слово CONCURRENT при работе с таблицами MyISAM, то другие потоки могут извлекать данные из таблицы во время выполнения команды LOAD DATA. Использование этой возможности, конечно, будет немного влиять на производительность выполнения LOAD DATA, даже если никакой другой поток не использует данную таблицу в это же время.
При применении опции LOCAL выполнение может происходить несколько медленнее в сравнении с предоставлением серверу доступа к файлам напрямую, поскольку содержимое файла должно переместиться с клиентского хоста на сервер. С другой стороны, в этом случае нет необходимости в привилегиях FILE для загрузки локальных файлов.
При использовании версий MySQL до 3.23.24 при помощи команды LOAD DATA INFILE нельзя выполнять чтение из FIFO. Если необходимо читать из FIFO
(например, стандартный вывод gunzip), следует использовать LOAD DATA LOCAL INFILE.
Можно также загружать файлы данных, используя утилиту mysqlimport. Эта утилита выполняет загрузку файлов путем посылки на сервер команд LOAD DATA INFILE. Опция --local заставляет mysqlimport читать файлы данных с клиентского хоста. Можно указать параметр --compress, чтобы получить лучшую производительность при работе через медленные сети, если и клиент, и сервер поддерживают протокол сжатия данных.
В случаях, когда файлы находятся на сервере, последний действует по следующим правилам:
Если задан абсолютный (полный) путь к файлу, то сервер использует этот путь без изменений.
Если задан относительный путь к файлу с указанием одного или более начальных каталогов, то поиск файла будет осуществляться относительно указанных каталогов в каталоге данных сервера (datadir).
Если дается путь к файлу без указания начальных каталогов, то сервер ищет этот файл в директории используемой базы данных.
Отсюда следует, что файл, заданный как `./myfile.txt', читается из серверного каталога данных, в то время как файл, заданный как `myfile.txt', читается из каталога используемой базы данных. Например, следующая команда LOAD DATA читает файл data.txt в каталоге базы данных для db1, поскольку db1 является текущей базой данных, даже если эта команда явно содержит указание загрузить файл в таблицу базы данных db2:
mysql> USE db1; mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;
Ключевые слова REPLACE и IGNORE управляют обработкой входных записей, которые дублируют существующие записи с теми же величинами уникальных ключей. Если указать REPLACE, то новые строки заменят существующие с таким же уникальным ключом. Если указать IGNORE, то входные строки, имеющие тот же уникальный ключ, что и существующие, будут пропускаться. Если не указан ни один из параметров, то при обнаружении дублирующегося значения ключа возникает ошибка и оставшаяся часть текстового файла игнорируется.
Если данные загружаются из локального файла с использованием ключевого слова LOCAL, то сервер не сможет прервать передачу данных посреди этой операции, поэтому по умолчанию выполнение команды происходит так же, как и в случае, когда указывается IGNORE.
При использовании LOAD DATA INFILE на пустых таблицах MyISAM все неуникальные индексы создаются в отдельном пакете (как в REPAIR). Обычно это значительно ускоряет работу LOAD DATA INFILE в случае большого количества индексов.
Команда LOAD DATA INFILE является дополнительной к SELECT ... INTO OUTFILE. See section 6.4.1 Синтаксис оператора SELECT. Чтобы записать данные из базы данных в файл, используется SELECT ... INTO OUTFILE. Чтобы прочитать данные обратно в базу данных, используется LOAD DATA INFILE. Синтаксис FIELDS и LINES одинаков в обеих командах. Обе части являются необязательными, но если указаны оба, то FIELDS должно предшествовать LINES.
Если указывается FIELDS, то каждое из его подвыражений (TERMINATED BY, [OPTIONALLY] ENCLOSED BY, и ESCAPED BY) также является необязательным, однако необходимо указать по меньшей мере одно из них.
Если утверждение FIELDS не определено, то по умолчанию его параметры будут принимать следующие значения:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
Если утверждение LINES не определено, то по умолчанию оно имеет следующую структуру:
LINES TERMINATED BY '\n'
Иными словами, при установках по умолчанию команда LOAD DATA INFILE при чтении входных данных будет работать следующим образом:
Искать концы строк в виде символов `\n'
Разбивать строки на поля по символам табуляции.
Не ожидать, что поля могут быть заключены в символы цитирования.
Интерпретировать встречающиеся символы табуляции, новой строки или `\', предваренные `\', как литералы, являющиеся частью значения поля.
И, наоборот, если действуют установки по умолчанию при записи выходных данных, команда SELECT ... INTO OUTFILE будет работать следующим образом:
Вставлять символы табуляции между полями.
Не заключать поля в символы цитирования.
Использовать символы `\' для экранирования экземпляров символов табуляции, новой строки или `\', которые появляются среди величин поля.
Вставлять символы новой строки в конце каждой записи.
Следует учитывать, что в записи FIELDS ESCAPED BY `\' необходимо указывать два обратных слеша для величины, которая должна читаться как один обратный слеш.
Опцию IGNORE number LINES можно применять для игнорирования заголовка имен столбцов в начале файла:
mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;
При использовании SELECT ... INTO OUTFILE совместно с LOAD DATA INFILE
для того, чтобы данные из базы данных прочитать в файл, а затем - обратно из файла в базу данных, опции, обрабатывающие поля и строки, для обеих команд должны совпадать. В противном случае LOAD DATA INFILE не сможет интерпретировать содержимое данного файла правильно. Предположим, что команда SELECT ... INTO OUTFILE используется для записи в файл с полями, разделенными запятыми:
mysql> SELECT * INTO OUTFILE 'data.txt' FIELDS TERMINATED BY ',' FROM ...;
Чтобы прочитать этот разделенный запятыми файл обратно в базу данных, корректная команда должна иметь вид:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY ',';
Если вместо этого попытаться прочитать этот файл с помощью команды, представленной ниже, то она не будет работать, поскольку предписывает команде LOAD DATA INFILE искать символы табуляции между полями:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY '\t';
Похожий результат получился бы, если бы каждая входная строка интерпретировалась как отдельное поле.
Команду LOAD DATA INFILE можно также использовать для чтения файлов, полученных из внешних источников. Например, поля в файле формата базе данных dBASE будут разделены запятыми и заключены в двойные кавычки. Если строки в данном файле заканчиваются символами новой строки, то для записи файла можно использовать приведенную ниже команду, в которой проиллюстрировано задание опций, обрабатывающих поля и строки:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
Любая из опций, обрабатывающих поля и строки, может задавать пустую строку (''). Если строка не пустая, то величины опций FIELDS [OPTIONALLY] ENCLOSED BY и FIELDS ESCAPED BY должны содержать один символ. Величины опций FIELDS TERMINATED BY и LINES TERMINATED BY могут содержать более чем один символ. Например, чтобы записать строки, заканчивающиеся парами ``возврат каретки - перевод строки'' (как в текстовых файлах MS DOS или Windows), необходимо задать следующее выражение: LINES TERMINATED BY '\r\n'.
Например, чтобы прочитать файл `jokes', в котором строки разделены символами %%, в таблицу SQL, необходимо сделать следующее:
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 служит для управления полями, заключенными в заданные символы. Если параметр OPTIONALLY опущен, то в выводе (SELECT ... INTO OUTFILE) все поля будут заключены в символы, заданные в 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 и VARCHAR:
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
не сможет правильно прочитать. Например, если символ экранирования является пустой строкой, то вывод, представленный выше, окажется таким, как показано ниже. Обратите внимание: второе поле в четвертой строке содержит запятую, следующую за кавычкой, которая (ошибочно) появляется, чтобы ограничить данное поле:
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, встречающиеся внутри поля, интерпретируются как одиночные символы 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 служит для управления записью или чтением специальных символов. Если символ FIELDS ESCAPED BY не пустой, он используется в качестве префикса для следующих символов в выводе:
Символ FIELDS ESCAPED BY
Символ FIELDS [OPTIONALLY] ENCLOSED BY
Первый символ величин FIELDS TERMINATED BY и LINES TERMINATED BY
Символ ASCII 0 (в действительности после экранирующего символа пишется ASCII `0', а не байт с нулевой величиной)
Если символ FIELDS ESCAPED BY пустой, то никакие символы не экранируются. На самом деле указывать пустой экранирующий символ нет смысла, особенно если величины полей в обрабатываемых данных содержат какие-либо из символов, указанных в приведенном выше списке.
Если символ FIELDS ESCAPED BY не пуст, то в случае входных данных вхождения такого символа удаляются и следующий за таким вхождением символ принимается буквально как часть величины поля. Исключениями являются экранированные `0' или `N' (например, \0 или \N, если экранирующим символом является `\'). Эти последовательности интерпретируются как ASCII 0 (байт с нулевой величиной) и NULL. См. ниже правила обработки величины NULL.
Чтобы получить более полную информацию о синтаксисе экранирующего символа `\' см. раздел section 6.1.1 Литералы: представление строк и чисел.
В ряде случаев опции обработки полей и строк взаимодействуют:
Если LINES TERMINATED BY является пустой строкой и FIELDS TERMINATED BY является не пустой строкой, то строки также заканчиваются символами FIELDS TERMINATED BY.
Если обе величины FIELDS TERMINATED BY и FIELDS ENCLOSED BY
являются пустыми (''), то применяется формат с фиксированной строкой (без разделителей). В формате с фиксированной строкой не предусмотрены никакие разделители между полями. Вместо этого при чтении и записи величин столбцов используется ширина ``вывода'' столбцов. Например, если столбец объявлен как INT(7), значения для этого столбца записываются с использованием полей шириной 7 символов. Входные значения для этого столбца получаются чтением 7 символов. Формат с фиксированной строкой влияет также на обработку величин NULL (см. ниже). Отметим, что формат с фиксированными размерами не будет работать при использовании мультибайтного набора символов.
Значения NULL в зависимости от используемых опций FIELDS и LINES будут обрабатываться по-разному:
Для установленных по умолчанию величин FIELDS и LINES NULL
записывается как \N для вывода и \N читается как NULL для ввода (исходя из предположения, что символ ESCAPED BY равен `\').
Если FIELDS ENCLOSED BY не является пустым, то поле, значение которого представляет собой слово из букв NULL, читается как величина NULL (в отличие от слова NULL, заключенного между символами FIELDS ENCLOSED BY, которое читается как строка 'NULL').
Если FIELDS ESCAPED BY является пустым, NULL записывается как слово NULL.
В формате с фиксированной строкой (который имеет место, если оба спецификатора - FIELDS TERMINATED BY и FIELDS ENCLOSED BY - являются пустыми), NULL записывается как пустая строка. Отметим, что вследствие этого величина NULL и пустая строка в данной таблице будут неразличимы при записи в файл, поскольку они обе записываются как пустые строки. Если необходимо, чтобы эти величины были различными при обратном чтении файла, то не следует использовать формат с фиксированной строкой.
Некоторые случаи, не поддерживаемые оператором LOAD DATA INFILE:
Строки с фиксированным размером (обе опции FIELDS TERMINATED BY и FIELDS ENCLOSED BY пустые) и столбцы типа BLOB или TEXT.
Если указывается разделитель, совпадающий с другим или являющийся префиксом другого, то LOAD DATA INFILE не сможет интерпретировать ввод правильно. Например, следующее утверждение FIELDS вызовет проблемы:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
Если опция FIELDS ESCAPED BY пустая, то содержащееся в значении поля вхождение символа FIELDS ENCLOSED BY или LINES TERMINATED BY, за которым следует символ FIELDS TERMINATED BY, приведет к преждевременному завершению чтения поля или строки командой LOAD DATA INFILE. Это происходит вследствие того, что LOAD DATA INFILE не может правильно определить, где заканчивается поле или строка.
Следующий пример загружает все столбцы таблицы persondata:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
Список полей не указывается, следовательно, команда LOAD DATA INFILE
ожидает входные строки для заполнения каждого столбца таблицы. При этом используются значения FIELDS и LINES по умолчанию.
Если требуется загрузить только некоторые из столбцов таблицы, необходимо задать список столбцов:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
Список полей необходимо задавать и в случаях, если порядок следования полей во входном файле отличается от порядка столбцов в данной таблице. В противном случае MySQL не сможет установить соответствие вводимых полей и столбцов таблицы.
Если строка имеет слишком мало полей, то столбцы, для которых отсутствуют поля во входном файле, устанавливаются в свои значения по умолчанию. Назначение величин по умолчанию описывается в разделе section 6.5.3 Синтаксис оператора CREATE TABLE.
Значение пустого поля интерпретируется иначе, чем отсутствие значения:
Для строковых типов столбец устанавливается в пустую строку.
Для числовых типов столбец устанавливается в 0.
Для типов даты и времени столбец устанавливается в соответствующее этому типу значение ``ноль''. See section 6.2.2 Типы данных даты и времени.
Отметим, что это те же самые величины, которые окажутся в столбце в результате явного назначения пустой строки столбцам строкового, числового типов, либо типов даты или времени в команде INSERT или UPDATE.
Столбцы типа TIMESTAMP устанавливаются только в текущую дату или время в случаях, если для столбца назначено значение NULL или (только для первого столбца TIMESTAMP) если столбец TIMESTAMP находится вне списка полей, если такой список задан.
Если входная строка имеет слишком много полей, то лишние поля игнорируются и количество предупреждений увеличится.
Команда LOAD DATA INFILE интерпретирует все входные данные как строки, поэтому нельзя указывать числовые величины для столбцов ENUM или SET так же, как для команд INSERT. Все величины ENUM и SET должны быть заданы как строки!
При использовании C API можно получить информацию о запросе, вызвав функцию API mysql_info() по окончании запроса LOAD DATA INFILE. Ниже показан формат строки информации для этого случая:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
Предостережения выдаются при тех же обстоятельствах, что и при записи величин командой INSERT (see section 6.4.3 Синтаксис оператора INSERT), за исключением того, что команда LOAD DATA INFILE дополнительно генерирует предупреждения, когда во входной строке слишком мало или слишком много полей. Предостережения нигде не хранятся; количество предупреждений может использоваться только для того, чтобы проверить, нормально ли выполнились указанные действия. Если необходимо точно знать причины предупреждений, то следует выполнить команду SELECT ... INTO OUTFILE в другой файл и сравнить результат с первоначальным входным файлом - это единственный способ получить такую информацию.
Если необходимо выполнить LOAD DATA для чтения из канала, можно применить следующий трюк:
mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x
При использовании версии MySQL старше, чем 3.23.25, вышеприведенное можно сделать только с LOAD DATA LOCAL INFILE.
Чтобы получить более подробную информацию об эффективности INSERT в сравнении с LOAD DATA INFILE и увеличении скорости LOAD DATA INFILE, см. раздел section 5.2.9 Скорость выполнения запросов INSERT.
Синтаксис оператора DO
DO expression, [expression, ...]
Выполняет данное выражение, но не возвращает какой-либо результат. Является сокращенной формой оператора SELECT expression, expression, но преимущество его заключается в том, что он работает немного быстрее, если нет необходимости в возвращении результата.
Оператор главным образом полезен при использовании с функциями, имеющими побочные эффекты, такими как RELEASE_LOCK.
Синтаксис оператора CREATE DATABASE
CREATE DATABASE [IF NOT EXISTS] db_name
Оператор CREATE DATABASE создает базу данных с указанным именем. Правила для допустимых имен базы данных приведены в разделе section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы. Если база данных уже существует и не указан ключевой параметр IF NOT EXISTS, то возникает ошибка выполнения команды.
Базы данных в MySQL реализуются как директории, содержащие файлы, которые соответствуют таблицам в базе данных. Поскольку при первоначальном создании база данных не содержит таблиц, то команда CREATE DATABASE
создает только соответствующую поддиректорию в директории данных MySQL.
Базы данных можно также создавать с помощью утилиты mysqladmin. See section 4.8 Клиентские сценарии и утилиты MySQL.
Синтаксис оператора DROP DATABASE
DROP DATABASE [IF EXISTS] db_name
Оператор DROP DATABASE удаляет все таблицы в указанной базе данных и саму базу. Если вы выполняете DROP DATABASE на базе данных, символически связанной с другой, то удаляется как ссылка, так и оригинальная база данных. Будьте ОЧЕНЬ внимательны при работе с этой командой!
Оператор DROP DATABASE возвращает количество файлов, которые были удалены из директории базы данных. Как правило, это число равно количеству таблиц, умноженному на три, поскольку обычно каждая таблица представлена тремя файлами - `.MYD'-файлом, `MYI'-файлом и `.frm'-файлом.
Команда DROP DATABASE удаляет из директории указанной базы данных все файлы со следующими расширениями:
Расширение | Расширение | Расширение | Расширение |
.BAK | .DAT | .HSH | .ISD |
.ISM | .ISM | .MRG | .MYD |
.MYI | .db | .frm | |
Все поддиректории, имена которых состоят из двух цифр (RAID-директории), также удаляются.
В версии MySQL 3.22 и более поздних можно использовать ключевые слова IF EXISTS для предупреждения ошибки, если указанная база данных не существует.
Можно также удалять базы данных с помощью утилиты mysqladmin. See section 4.8 Клиентские сценарии и утилиты MySQL.
Молчаливые изменения определений столбцов
В некоторых случаях MySQL без уведомления изменяет определение столбца, заданное командой CREATE TABLE (Это может осуществляться также для команды ALTER TABLE):
Столбец VARCHAR с длиной меньше, чем четыре, преобразуется в столбец CHAR.
Если некоторый столбец в таблице имеет переменную длину, то и вся строка в результате будет переменной длины. Следовательно, если таблица содержит любые столбцы переменной длины (VARCHAR, TEXT или BLOB), то все столбцы CHAR с длиной, превышающей три символа, преобразуются в столбцы VARCHAR. Это в любом случае не влияет на использование столбцов; в MySQL столбец VARCHAR представляет собой просто иной способ хранения символов. MySQL выполняет данное преобразование, поскольку оно позволяет сэкономить память и сделать табличные операции более быстрыми. See section 7 Типы таблиц MySQL.
Количество выводящихся символов столбца TIMESTAMP должно быть четным и находиться в диапазоне от 2 до 14. При задании размера вывода, равного 0 или превышающего 14, указанный размер приводится к 14. Нечетные величины размера вывода в пределах от 1 до 13 приводятся к следующему четному числу.
В столбце TIMESTAMP не может храниться литерал NULL; установка данного столбца в NULL устанавливает его в текущее значение даты и времени. Поскольку столбцы TIMESTAMP ведут себя подобным образом, то атрибуты NULL и NOT NULL неприменимы в обычном режиме и игнорируются при их задании. DESCRIBE tbl_name всегда сообщает, что столбцу TIMESTAMP могут быть присвоены величины NULL.
MySQL приводит в соответствие определенные типы столбцов, используемые другими производителями баз данных SQL, к типам, принятым в MySQL. See section 6.2.5 Использование типов столбцов из других баз данных.
Если необходимо увидеть, использует ли MySQL иной тип столбца, чем был первоначально задан, следует запустить команду DESCRIBE tbl_name после создания или изменения данной таблицы.
Некоторые другие изменения типов столбцов могут происходить при сжатии таблицы с использованием утилиты myisampack. See section 7.1.2.3 Характеристики сжатых таблиц.
Синтаксис оператора CREATE TABLE
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement]
или
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name LIKE old_table_name;
create_definition: col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY KEY] [reference_definition] или PRIMARY KEY (index_col_name,...) или KEY [index_name] (index_col_name,...) или INDEX [index_name] (index_col_name,...) или UNIQUE [INDEX] [index_name] (index_col_name,...) или FULLTEXT [INDEX] [index_name] (index_col_name,...) или [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition] или CHECK (expr)
type: 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] или CHAR(length) [BINARY] или VARCHAR(length) [BINARY] или DATE или TIME или TIMESTAMP или DATETIME или TINYBLOB или BLOB или MEDIUMBLOB или LONGBLOB или TINYTEXT или TEXT или MEDIUMTEXT или LONGTEXT или ENUM(value1,value2,value3,...) или SET(value1,value2,value3,...)
index_col_name: col_name [(length)]
reference_definition: REFERENCES tbl_name [(index_col_name,...)] [MATCH FULL | MATCH PARTIAL] [ON DELETE reference_option] [ON UPDATE reference_option]
reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
table_options: TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM } или AUTO_INCREMENT = # или AVG_ROW_LENGTH = # или CHECKSUM = {0 | 1} или COMMENT = "string" или MAX_ROWS = # или MIN_ROWS = # или PACK_KEYS = {0 | 1 | DEFAULT} или PASSWORD = "string" или DELAY_KEY_WRITE = {0 | 1} или ROW_FORMAT= { default | dynamic | fixed | compressed } или RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=# RAID_CHUNKSIZE=# или UNION = (table_name,[table_name...]) или INSERT_METHOD= {NO | FIRST | LAST } или DATA DIRECTORY="абсолютный путь к каталогу" или INDEX DIRECTORY="абсолютный путь к каталогу"
select_statement: [IGNORE | REPLACE] SELECT ... (любое корректное выражение SELECT)
Оператор CREATE TABLE создает таблицу с заданным именем в текущей базе данных. Правила для допустимых имен таблицы приведены в разделе section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы. Если нет активной текущей базы данных или указанная таблица уже существует, то возникает ошибка выполнения команды.
В версии MySQL 3.22 и более поздних имя таблицы может быть указано как db_name.tbl_name. Эта форма записи работает независимо от того, является ли указанная база данных текущей.
Начиная с MySQL 3.23 при создании таблицы можно использовать ключевое слово TEMPORARY. Временная таблица автоматически удаляется по завершении соединения, а ее имя действительно только в течение данного соединения. Это означает, что в двух разных соединениях могут использоваться временные таблицы с одинаковыми именами без конфликта друг с другом или с существующей таблицей с тем же именем (существующая таблица скрыта, пока не удалена временная таблица). С версии MySQL 4.0.2 для создания временных таблиц необходимо иметь привилегии CREATE TEMPORARY TABLES.
В версии MySQL 3.23 и более поздних можно использовать ключевые слова IF NOT EXISTS для того, чтобы не возникала ошибка, если указанная таблица уже существует. Следует учитывать, что при этом не проверяется идентичность структур этих таблиц.
В MySQL 4.1 вы можете указать LIKE чтобы создавать таблицу, основываясь на определении другой, уже существующей, таблицы. В MySQL 4.1 также можете определять тип автоматически создаваемого столбца:
CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;
Каждая таблица tbl_name представлена определенными файлами в директории базы данных. В случае таблиц типа MyISAM это следующие файлы:
Файл | Назначение |
tbl_name.frm | Файл определения таблицы |
tbl_name.MYD | Файл данных |
tbl_name.MYI | Файл индексов |
Чтобы получить более полную информацию о свойствах различных типов столбцов, section 6.2 Типы данных столбцов:
Если не указывается ни NULL, ни NOT NULL, то столбец интерпретируется так, как будто указано NULL.
Целочисленный столбец может иметь дополнительный атрибут AUTO_INCREMENT. При записи величины NULL (рекомендуется) или 0 в столбец AUTO_INCREMENT данный столбец устанавливается в значение value+1, где value представляет собой наибольшее для этого столбца значение в таблице на момент записи. Последовательность AUTO_INCREMENT
начинается с 1. See section 8.4.3.31 mysql_insert_id(). Если удалить строку, содержащую максимальную величину для столбца AUTO_INCREMENT, то в таблицах типа ISAM или BDB эта величина будет восстановлена, а в таблицах типа MyISAM или InnoDB - нет. Если удалить все строки в таблице командой DELETE FROM table_name (без выражения WHERE) в режиме AUTOCOMMIT, то для таблиц всех типов последовательность начнется заново.
Примечание: в таблице может быть только один столбец AUTO_INCREMENT, и он должен быть индексирован. Кроме того, версия MySQL 3.23 будет правильно работать только с положительными величинами столбца AUTO_INCREMENT. В случае внесения отрицательного числа оно интерпретируется как очень большое положительное число. Это делается, чтобы избежать проблем с точностью, когда числа ``заворачиваются'' от положительного к отрицательному и, кроме того, для гарантии, что по ошибке не будет получен столбец AUTO_INCREMENT со значением 0. В таблицах MyISAM и BDB можно указать вторичный столбец AUTO_INCREMENT с многостолбцовым ключом. See section 3.5.9 Использование атрибута AUTO_INCREMENT.
Последнюю внесенную строку можно найти с помощью следующего запроса (чтобы сделать MySQL совместимым с некоторыми ODBC-приложениями):
SELECT * FROM tbl_name WHERE auto_col IS NULL
CREATE TABLE автоматически принимает текущую открытую транзакцию в InnoDB если в MySQL включен двоичный журнал.
Величины NULL для столбца типа TIMESTAMP обрабатываются иначе, чем для столбцов других типов. В столбце TIMESTAMP нельзя хранить литерал NULL; при установке данного столбца в NULL он будет установлен в текущее значение даты и времени. Поскольку столбцы TIMESTAMP ведут себя подобным образом, то атрибуты NULL и NOT NULL неприменимы в обычном режиме и игнорируются при их задании.
С другой стороны, чтобы облегчить клиентам MySQL использование столбцов TIMESTAMP, сервер сообщает, что таким столбцам могут быть назначены величины NULL (что соответствует действительности), хотя реально TIMESTAMP никогда не будет содержать величины NULL. Это можно увидеть, применив DESCRIBE tbl_name для получения описания данной таблицы. Следует учитывать, что установка столбца TIMESTAMP в 0 не равнозначна установке его в NULL, поскольку 0 для TIMESTAMP является допустимой величиной.
Величина DEFAULT должна быть константой, она не может быть функцией или выражением. Если для данного столбца не задается никакой величины DEFAULT, то MySQL автоматически назначает ее. Если столбец может принимать NULL как допустимую величину, то по умолчанию присваивается значение NULL. Если столбец объявлен как NOT NULL, то значение по умолчанию зависит от типа столбца:
Для числовых типов, за исключением объявленных с атрибутом AUTO_INCREMENT, значение по умолчанию равно 0. Для столбца AUTO_INCREMENT значением по умолчанию является следующее значение в последовательности для этого столбца.
Для типов даты и времени, отличных от TIMESTAMP, значение по умолчанию равно соответствующей нулевой величине для данного типа. Для первого столбца TIMESTAMP в таблице значение по умолчанию представляет собой текущее значение даты и времени. See section 6.2.2 Типы данных даты и времени.
Для типов даты и времени, отличных от TIMESTAMP, значение по умолчанию равно соответствующей нулевой величине для данного типа. Для первого столбца TIMESTAMP в таблице значение по умолчанию представляет собой текущее значение даты и времени. See section 6.2.2 Типы данных даты и времени.
Для строковых типов, кроме ENUM, значением по умолчанию является пустая строка. Для ENUM значение по умолчанию равно первой перечисляемой величине.
Значения по умолчанию должны быть константами. Это означает, например, что нельзя установить для столбца даты в качестве значения по умолчанию величину функции, такой как NOW() или CURRENT_DATE.
KEY является синонимом для INDEX.
В MySQL ключ UNIQUE может иметь только различающиеся значения. При попытке добавить новую строку с ключом, совпадающим с существующей строкой, возникает ошибка выполнения команды.
PRIMARY KEY представляет собой уникальный ключ KEY с дополнительным ограничением, что все столбцы с данным ключом должны быть определены как NOT NULL. В MySQL этот ключ называется PRIMARY (первичный). Таблица может иметь только один первичный ключ PRIMARY KEY. Если PRIMARY KEY отсутствует в таблицах, а некоторое приложение запрашивает его, то MySQL может превратить в PRIMARY KEY первый ключ UNIQUE, не имеющий ни одного столбца NULL.
PRIMARY KEY может быть многостолбцовым индексом. Однако нельзя создать многостолбцовый индекс, используя в определении столбца атрибут ключа PRIMARY KEY. Именно таким образом только один столбец будет отмечен как первичный. Необходимо использовать синтаксис PRIMARY KEY(index_col_name, ...).
Если ключ PRIMARY или UNIQUE состоит только из одного столбца и он принадлежит к числовому типу, то на него можно сослаться также как на _rowid (новшество версии 3.23.11).
Если индексу не назначено имя, то ему будет присвоено первое имя в index_col_name, возможно, с суффиксами (_2, _3, ...), делающими это имя уникальным. Имена индексов для таблицы можно увидеть, используя SHOW INDEX FROM tbl_name. SHOW Syntax.
Только таблицы типов MyISAM, InnoDB и BDB поддерживают индексы столбцов, которые могут иметь величины NULL. В других случаях, во избежание ошибки, необходимо объявлять такие столбцы как NOT NULL.
С помощью выражения col_name(length) можно указать индекс, для которого используется только часть столбца CHAR или VARCHAR. Это поможет сделать файл индексов намного меньше. See section 5.4.4 Индексы столбцов.
Индексацию столбцов BLOB и TEXT поддерживают только таблицы с типом MyISAM. Назначая индекс столбцу с типом BLOB или TEXT, всегда НЕОБХОДИМО указывать длину этого индекса:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
При использовании выражений ORDER BY или GROUP BY со столбцом типа TEXT или BLOB используются только первые max_sort_length байтов. See section 6.2.3.2 Типы данных BLOB и TEXT.
В версии MySQL 3.23.23 и более поздних можно создавать также специальные индексы FULLTEXT. Они применяются для полнотекстового поиска. Эти индексы поддерживаются только таблицами типа MyISAM и они могут быть созданы только из столбцов CHAR, VARCHAR и TEXT. Индексирование всегда выполняется для всего столбца целиком, частичная индексация не поддерживается. Более подробно эта операция описана в разделе MySQL section 6.8 Полнотекстовый поиск в MySQL.
Выражения FOREIGN KEY, CHECK и REFERENCES фактически ничего не делают. Они введены только из соображений совместимости, чтобы облегчить перенос кода с других SQL-серверов и запускать приложения, создающие таблицы со ссылками. See section 1.9.3 Расширения MySQL к ANSI SQL92.
В MySQL версии 3.23.44 или более поздней, таблицы InnoDB выполняют проверку ограничений внешнего ключа. See section 7.5 Таблицы InnoDB. Однако обратите внимание, что синтаксис FOREIGN KEY в InnoDB более строгий чем приведенный выше. InnoDB не допускает указания index_name. Также столбцы таблицы, на которую ссылаются, должны быть явно указаны. Начиная с 4.0.8 InnoDB поддерживает действия ON DELETE и ON UPDATE.
Для уточнения синтаксиса см. документацию по InnoDB. See section 7.5 Таблицы InnoDB. Для остальных типов таблиц, MySQL делает синтаксической разбор указаний FOREIGN KEY, CHECK и REFERENCES в CREATE TABLE, но при этом успешно их игнорирует. See section 1.9.4.5 Внешние ключи.
Для каждого столбца NULL требуется один дополнительный бит, при этом величина столбца округляется в большую сторону до ближайшего байта.
Максимальную длину записи в байтах можно вычислить следующим образом:
длина записи = 1 + (сумма длин столбцов) + (количество столбцов с допустимым NULL + 7)/8 + (количество столбцов с динамической длинной)
Опции table_options и SELECT реализованы только в версиях MySQL 3.23 и выше. Ниже представлены различные типы таблиц:
Тип таблицы | Описание |
BDB или BerkeleyDB | Таблицы с поддержкой транзакций и блокировкой страниц. See section 7.6 Таблицы BDB или BerkeleyDB. |
HEAP | Данные для этой таблицы хранятся только в памяти. See section 7.4 Таблицы HEAP. |
ISAM | Оригинальный обработчик таблиц. See section 7.3 Таблицы ISAM. |
InnoDB | Таблицы с поддержкой транзакций и блокировкой строк. See section 7.5 Таблицы InnoDB. |
MERGE | Набор таблиц MyISAM, используемый как одна таблица. See section 7.2 Таблицы MERGE. |
MRG_MyISAM | Псевдоним для таблиц MERGE |
MyISAM | Новый обработчик, обеспечивающий переносимость таблиц в бинарном виде, который заменяет ISAM. See section 7.1 Таблицы MyISAM. |
See section 7 Типы таблиц MySQL.
Если задается тип таблицы, который не поддерживается данной версией, то MySQL выберет из возможных типов ближайший к указанному. Например, если задается TYPE=BDB и данный дистрибутив MySQL не поддерживает таблиц BDB, то вместо этого будет создана таблица MyISAM. Другие табличные опции используются для оптимизации характеристик таблицы. Эти опции в большинстве случаев не требуют специальной установки. Данные опции работают с таблицами всех типов, если не указано иное:
Опция | Описание |
AUTO_INCREMENT | Следующая величина AUTO_INCREMENT, которую следует установить для данной таблицы (MyISAM). |
AVG_ROW_LENGTH | Приближенное значение средней длины строки для данной таблицы. Имеет смысл устанавливать только для обширных таблиц с записями переменной длины. |
CHECKSUM | Следует установить в 1, чтобы в MySQL поддерживалась проверка контрольной суммы для всех строк (это делает таблицы немного более медленными при обновлении, но позволяет легче находить поврежденные таблицы) (MyISAM). |
COMMENT | Комментарий для данной таблицы длиной 60 символов. |
MAX_ROWS | Максимальное число строк, которые планируется хранить в данной таблице. |
MIN_ROWS | Минимальное число строк, которые планируется хранить в данной таблице. |
PACK_KEYS | Следует установить в 1 для получения меньшего индекса. Обычно это замедляет обновление и ускоряет чтение (MyISAM, ISAM). Установка в 0 отключит уплотнение ключей. При установке в DEFAULT (MySQL 4.0) обработчик таблиц будет уплотнять только длинные столбцы CHAR/VARCHAR. |
PASSWORD | Шифрует файл `.frm' с помощью пароля. Эта опция не функционирует в стандартной версии MySQL. |
DELAY_KEY_WRITE | Установка в 1 задерживает операции обновления таблицы ключей, пока не закроется указанная таблица (MyISAM). |
ROW_FORMAT | Определяет, каким образом должны храниться строки. В настоящее время эта опция работает только с таблицами MyISAM, которые поддерживают форматы строк DYNAMIC и FIXED. See section 7.1.2 Форматы таблиц MyISAM. |
При использовании таблиц MyISAM MySQL вычисляет выражение max_rows * avg_row_length, чтобы определить, насколько велика будет результирующая таблица. Если не задана ни одна из вышеупомянутых опций, то максимальный размер таблицы будет составлять 4Гб (или 2Гб если данная операционная система поддерживает только таблицы величиной до 2Гб). Это делается для того, чтобы, если нет реальной необходимости в больших файлах, ограничить размеры указателей, что позволит сделать индексы меньше и быстрее. Если опция PACK_KEYS не используется, то по умолчанию уплотняются только строки, но не числа. При использовании PACK_KEYS=1 числа тоже будут уплотняться. При уплотнении двоичных числовых ключей MySQL будет использовать сжатие префиксов. Это означает, что выгода от этого будет значительной только в случае большого количества одинаковых чисел. При сжатии префиксов для каждого ключа требуется один дополнительный байт, в котором указано, сколько байтов предыдущего ключа являются такими же, как и для следующего (следует учитывать, что указатель на строку хранится в порядке "старший-байт-в-начале" сразу после ключа - чтобы улучшить компрессию).
Это означает, что при наличии нескольких одинаковых ключей в двух строках записи все последующие ``аналогичные'' ключи будут занимать только по 2 байта (включая указатель строки). Сравним: в обычном случае для хранения последующих ключей требуется размер_хранения_ключа + размер_указателя (обычно 4) байтов. С другой стороны, если все ключи абсолютно разные, каждый ключ будет занимать на 1 байт больше, если данный ключ не может иметь величину NULL (в этом случае уплотненный ключ будет храниться в том же байте, который используется для указания, что ключ равен NULL).
Если после команды CREATE указывается команда SELECT, то MySQL создаст новые поля для всех элементов в данной команде SELECT. Например:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (a), KEY(b)) TYPE=MyISAM SELECT b,c FROM test2;
Эта команда создаст таблицу MyISAM с тремя столбцами a, b и c. Отметим, что столбцы из команды 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, при этом в новые столбцы в таблице bar записываются величины, заданные по умолчанию. Команда CREATE TABLE ... SELECT не создает автоматически каких-либо индексов. Это сделано преднамеренно, чтобы команда была настолько гибкой, насколько возможно. Чтобы иметь индексы в созданной таблице, необходимо указать их перед данной командой SELECT:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
Если возникает ошибка при копировании данных в таблицу, то они будут автоматически удалены. Чтобы обеспечить возможность использовать для восстановления таблиц журнал обновлений/двоичный журнал, в MySQL во время выполнения команды CREATE TABLE ... SELECT не разрешены параллельные вставки.
Воспользовавшись опцией RAID_TYPE, можно разбить файл данных MyISAM на участки с тем, чтобы преодолеть 2Гб/4Гб лимит файловой системы под управлением ОС, не поддерживающих большие файлы. Разбиение не касается файла индексов. Следует учесть, что для файловых систем, которые поддерживают большие файлы, эта опция не рекомендуется! Для получения более высокой скорости ввода-вывода можно разместить RAID-директории на различных физических дисках. RAID_TYPE будет работать под любой операционной системой, если конфигурация MySQL выполнена с параметром --with-raid. В настоящее время для опции RAID_TYPE возможен только параметр STRIPED (1 и RAID0 являются псевдонимами для него). Если указывается RAID_TYPE=STRIPED для таблицы MyISAM, то MyISAM создаст поддиректории RAID_CHUNKS с именами `00', `01', `02' в директории базы данных. В каждой из этих директорий MyISAM
создаст файл `table_name.MYD'. При записи данных в файл данных обработчик RAID установит соответствие первых RAID_CHUNKSIZE*1024
байтов первому упомянутому файлу, следующих RAID_CHUNKSIZE*1024
байтов - следующему файлу и так далее.
Опция UNION применяется, если необходимо использовать совокупность идентичных таблиц как одну таблицу. Она работает только с таблицами MERGE. See section 7.2 Таблицы MERGE. На данный момент для таблиц, сопоставляемых с таблицей MERGE, необходимо иметь привилегии SELECT, UPDATE и DELETE. Все сопоставляемые таблицы должны принадлежать той же базе данных, что и таблица MERGE.
Для внесения данных в таблицу MERGE необходимо указать с помощью INSERT_METHOD, в какую таблицу данная строка должна быть внесена. See section 7.2 Таблицы MERGE. Эта опция была введена в MySQL 4.0.0.
В созданной таблице ключ PRIMARY будет помещен первым, за ним все ключи UNIQUE и затем простые ключи. Это помогает оптимизатору MySQL определять приоритеты используемых ключей, а также более быстро определять сдублированные ключи UNIQUE.
Используя опции DATA DIRECTORY="каталог" или INDEX DIRECTORY="каталог", можно указать, где обработчик таблицы должен помещать свои табличные и индексные файлы. Следует учитывать, что указываемый параметр directory должен представлять собой полный путь к требуемому каталогу (а не относительный путь). Данные опции работают только для таблиц MyISAM в версии MySQL 4.0, если при этом не используется опция --skip-symlink. See section 5.6.1.2 Использование символических ссылок для таблиц.
Синтаксис оператора ALTER TABLE
ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]
alter_specification: ADD [COLUMN] create_definition [FIRST | AFTER column_name ] или ADD [COLUMN] (create_definition, create_definition,...) или ADD INDEX [index_name] (index_col_name,...) или ADD PRIMARY KEY (index_col_name,...) или ADD UNIQUE [index_name] (index_col_name,...) или ADD FULLTEXT [index_name] (index_col_name,...) или ADD [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition] или ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT} или CHANGE [COLUMN] old_col_name create_definition [FIRST | AFTER column_name] или MODIFY [COLUMN] create_definition [FIRST | AFTER column_name] или DROP [COLUMN] col_name или DROP PRIMARY KEY или DROP INDEX index_name или DISABLE KEYS или ENABLE KEYS или RENAME [TO] new_tbl_name или ORDER BY col или table_options
Оператор ALTER TABLE обеспечивает возможность изменять структуру существующей таблицы. Например, можно добавлять или удалять столбцы, создавать или уничтожать индексы или переименовывать столбцы либо саму таблицу. Можно также изменять комментарий для таблицы и ее тип. See section 6.5.3 Синтаксис оператора CREATE TABLE.
Если оператор ALTER TABLE используется для изменения определения типа столбца, но DESCRIBE tbl_name показывает, что столбец не изменился, то, возможно, MySQL игнорирует данную модификацию по одной из причин, описанных в разделе section 6.5.3.1 Молчаливые изменения определений столбцов. Например, при попытке изменить столбец VARCHAR на CHAR MySQL будет продолжать использовать VARCHAR, если данная таблица содержит другие столбцы с переменной длиной.
Оператор ALTER TABLE во время работы создает временную копию исходной таблицы. Требуемое изменение выполняется на копии, затем исходная таблица удаляется, а новая переименовывается. Так делается для того, чтобы в новую таблицу автоматически попадали все обновления кроме неудавшихся. Во время выполнения ALTER TABLE исходная таблица доступна для чтения другими клиентами. Операции обновления и записи в этой таблице приостанавливаются, пока не будет готова новая таблица.
Следует отметить, что при использовании любой другой опции для ALTER TABLE кроме RENAME, MySQL всегда будет создавать временную таблицу, даже если данные, строго говоря, и не нуждаются в копировании (например, при изменении имени столбца). Мы планируем исправить это в будущем, однако, поскольку ALTER TABLE выполняется не так часто, мы (разработчики MySQL) не считаем эту задачу первоочередной. Для таблиц MyISAM можно увеличить скорость воссоздания индексной части (что является наиболее медленной частью в процессе восстановления таблицы) путем установки переменной myisam_sort_buffer_size достаточно большого значения.
Для использования оператора ALTER TABLE необходимы привилегии ALTER, INSERT и CREATE для данной таблицы.
Опция IGNORE является расширением MySQL по отношению к ANSI SQL92. Она управляет работой ALTER TABLE при наличии дубликатов уникальных ключей в новой таблице. Если опция IGNORE не задана, то для данной копии процесс прерывается и происходит откат назад. Если IGNORE
указывается, тогда для строк с дубликатами уникальных ключей только первая строка используется, а остальные удаляются.
Можно запустить несколько выражений ADD, ALTER, DROP и CHANGE в одной команде ALTER TABLE. Это является расширением MySQL по отношению к ANSI SQL92, где допускается только одно выражение из упомянутых в одной команде ALTER TABLE.
Опции CHANGE col_name, DROP col_name и DROP INDEX также являются расширениями MySQL по отношению к ANSI SQL92.
Опция MODIFY представляет собой расширение Oracle для команды ALTER TABLE.
Необязательное слово COLUMN представляет собой ``белый шум'' и может быть опущено.
При использовании ALTER TABLE имя_таблицы RENAME TO новое_имя без каких-либо других опций MySQL просто переименовывает файлы, соответствующие заданной таблице. В этом случае нет необходимости создавать временную таблицу. See section 6.5.5 Синтаксис оператора RENAME TABLE.
В выражении create_definition для ADD и CHANGE используется тот же синтаксис, что и для CREATE TABLE. Следует учитывать, что этот синтаксис включает имя столбца, а не просто его тип. See section 6.5.3 Синтаксис оператора CREATE TABLE.
Столбец можно переименовывать, используя выражение CHANGE имя_столбца create_definition. Чтобы сделать это, необходимо указать старое и новое имена столбца и его тип в настоящее время. Например, чтобы переименовать столбец INTEGER из a в b, можно сделать следующее:
mysql> ALTER TABLE t1 CHANGE a b INTEGER;
При изменении типа столбца, но не его имени синтаксис выражения CHANGE все равно требует указания обоих имен столбца, даже если они одинаковы. Например:
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
Однако начиная с версии MySQL 3.22.16a можно также использовать выражение MODIFY для изменения типа столбца без переименовывания его:
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
При использовании CHANGE или MODIFY для того, чтобы уменьшить длину столбца, по части которого построен индекс (например, индекс по первым 10 символам столбца VARCHAR), нельзя сделать столбец короче, чем число проиндексированных символов.
При изменении типа столбца с использованием CHANGE или MODIFY MySQL пытается преобразовать данные в новый тип как можно корректнее.
В версии MySQL 3.22 и более поздних можно использовать FIRST или ADD ... AFTER имя_столбца для добавления столбца на заданную позицию внутри табличной строки. По умолчанию столбец добавляется в конце. Начиная с версии MySQL 4.0.1, можно также использовать ключевые слова FIRST и AFTER в опциях CHANGE или MODIFY.
Опция ALTER COLUMN задает для столбца новое значение по умолчанию или удаляет старое. Если старое значение по умолчанию удаляется и данный столбец может принимать значение NULL, то новое значение по умолчанию будет NULL. Если столбец не может быть NULL, то MySQL назначает значение по умолчанию так, как описано в разделе section 6.5.3 Синтаксис оператора CREATE TABLE.
Опция DROP INDEX удаляет индекс. Это является расширением MySQL по отношению к ANSI SQL92. See section 6.5.8 Синтаксис оператора DROP INDEX.
Если столбцы удаляются из таблицы, то эти столбцы удаляются также и из любого индекса, в который они входят как часть. Если все столбцы, составляющие индекс, удаляются, то данный индекс также удаляется.
Если таблица содержит только один столбец, то этот столбец не может быть удален. Вместо этого можно удалить данную таблицу, используя команду DROP TABLE.
Опция DROP PRIMARY KEY удаляет первичный индекс. Если такого индекса в данной таблице не существует, то удаляется первый индекс UNIQUE в этой таблице. (MySQL отмечает первый уникальный ключ UNIQUE
как первичный ключ PRIMARY KEY, если никакой другой первичный ключ PRIMARY KEY не был явно указан). При добавлении UNIQUE INDEX или PRIMARY KEY в таблицу они хранятся перед остальными неуникальными ключами, чтобы можно было определить дублирующиеся ключи как можно раньше.
Опция ORDER BY позволяет создавать новую таблицу со строками, размещенными в заданном порядке. Следует учитывать, что созданная таблица не будет сохранять этот порядок строк после операций вставки и удаления. В некоторых случаях такая возможность может облегчить операцию сортировки в MySQL, если таблица имеет такое расположение столбцов, которое вы хотели бы иметь в дальнейшем. Эта опция в основном полезна, если заранее известен определенный порядок, в котором преимущественно будут запрашиваться строки. Использование данной опции после значительных преобразований таблицы дает возможность получить более высокую производительность.
При использовании команды ALTER TABLE для таблиц MyISAM все неуникальные индексы создаются в отдельном пакете (подобно REPAIR). Благодаря этому команда ALTER TABLE при наличии нескольких индексов будет работать быстрее.
Начиная с MySQL 4.0, вышеуказанная возможность может быть активизирована явным образом. Команда ALTER TABLE ... DISABLE KEYS
блокирует в MySQL обновление неуникальных индексов для таблиц MyISAM. После этого можно применить команду ALTER TABLE ... ENABLE KEYS для воссоздания недостающих индексов. Так как MySQL делает это с помощью специального алгоритма, который намного быстрее в сравнении со вставкой ключей один за другим, блокировка ключей может дать существенное ускорение на больших массивах вставок.
Применяя функцию C API mysql_info(), можно определить, сколько записей было скопировано, а также (при использовании IGNORE) - сколько записей было удалено из-за дублирования значений уникальных ключей.
Выражения FOREIGN KEY, CHECK и REFERENCES фактически ничего не делают во всех типах таблиц, кроме InnoDB. InnoDB поддерживает ADD CONSTRAINT FOREIGN KEY (...) REFERENCES ... (...). Заметьте, что InnoDB не допускает указания index_name. See section 7.5 Таблицы InnoDB. Поддержка синтаксиса FOREIGH KEY введена только из соображений совместимости, чтобы облегчить перенос кода с других серверов SQL и запуск приложений, создающих таблицы со ссылками. See section 1.9.4 Отличия MySQL от ANSI SQL92.
Ниже приводятся примеры, показывающие некоторые случаи употребления команды ALTER TABLE. Пример начинается с таблицы t1, которая создается следующим образом:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
Для того чтобы переименовать таблицу из t1 в t2:
mysql> ALTER TABLE t1 RENAME t2;
Для того чтобы изменить тип столбца с INTEGER на TINYINT NOT NULL
(оставляя имя прежним) и изменить тип столбца b с CHAR(10) на CHAR(20) с переименованием его с b на c:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
Для того чтобы добавить новый столбец TIMESTAMP с именем d:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
Для того чтобы добавить индекс к столбцу d и сделать столбец a первичным ключом:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);
Для того чтобы удалить столбец c:
mysql> ALTER TABLE t2 DROP COLUMN c;
Для того чтобы добавить новый числовой столбец AUTO_INCREMENT с именем c:
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD INDEX (c);
Заметьте, что столбец c индексируется, так как столбцы AUTO_INCREMENT
должны быть индексированы, кроме того, столбец c объявляется как NOT NULL, поскольку индексированные столбцы не могут быть NULL.
При добавлении столбца AUTO_INCREMENT значения этого столбца автоматически заполняются последовательными номерами (при добавлении записей). Первый номер последовательности можно установить путем выполнения команды SET INSERT_ID=# перед ALTER TABLE или использования табличной опции AUTO_INCREMENT = #. See section 5.5.6 Синтаксис команды SET.
Если столбец AUTO_INCREMENT для таблиц MyISAM, не изменяется, то номер последовательности остается прежним. При удалении столбца AUTO_INCREMENT и последующем добавлении другого столбца AUTO_INCREMENT номера будут начинаться снова с 1.
See section A.6.1 Проблемы с ALTER TABLE.
Синтаксис оператора RENAME TABLE
RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]
Операция переименования должна осуществляться как атомарная, т.е. при выполнении переименования никакому другому потоку не разрешается доступ к указанным таблицам. Благодаря этому возможно замещение таблицы пустой таблицей:
CREATE TABLE new_table (...); RENAME TABLE old_table TO backup_table, new_table TO old_table;
Переименование производится слева направо. Таким образом, для обмена именами между двумя таблицами необходимо выполнить следующие действия:
RENAME TABLE old_table TO backup_table, new_table TO old_table, backup_table TO new_table;
Для двух баз данных, находящихся на одном и том же диске, можно также осуществлять обмен именами:
RENAME TABLE current_db.tbl_name TO other_db.tbl_name;
При выполнении команды RENAME не должны иметь место заблокированные таблицы или активные транзакции. Необходимо также иметь привилегии ALTER и DROP для исходной таблицы и привилегии CREATE и INSERT - для новой.
Если MySQL сталкивается с какой-либо ошибкой при переименовании нескольких таблиц, то произойдет обратное переименование для всех переименованных таблиц, чтобы вернуть все в исходное состояние.
Оператор RENAME TABLE был добавлен в MySQL 3.23.23.
Синтаксис оператора DROP TABLE
DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]
Оператор DROP TABLE удаляет одну или несколько таблиц. Все табличные данные и определения удаляются, так что будьте внимательны при работе с этой командой!
В версии MySQL 3.22 и более поздних можно использовать ключевые слова IF EXISTS, чтобы предупредить ошибку, если указанные таблицы не существуют.
В 4.1 будет получено замечание (NOTE) для всех несуществующих таблиц при использовании IF EXISTS. See section 4.5.6.9 SHOW WARNINGS | ERRORS.
Опции RESTRICT и CASCADE позволяют упростить перенос программы. В данный момент они не задействованы.
Примечание: DROP TABLE автоматически принимает текущую активную транзакцию (за исключением случаев, когда вы используетее 4.1 и указано ключевое слово TEMPORARY).
Опция TEMPORARY игнорируется в 4.0. В 4.1 эта опция работает следующим образом:
Только уничтожает временные таблицы.
Не закрывает открытую транзакцию.
Права доступа не проверяются.
Использование слова TEMPORARY - это хороший способ удостовериться что вы случайно не уничтожите настоящую таблицу.
Синтаксис оператора CREATE INDEX
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON tbl_name (col_name[(length)],... )
Команда CREATE INDEX в версиях MySQL до 3.22 не выполняет никаких действий. В версии 3.22 и более поздних CREATE INDEX соответствует команде ALTER TABLE в части создания индексов. See section 6.5.4 Синтаксис оператора ALTER TABLE.
Обычно все индексы создаются в таблице во время создания самой таблицы командой CREATE TABLE. See section 6.5.3 Синтаксис оператора CREATE TABLE. CREATE INDEX дает возможность добавить индексы к существующим таблицам.
Список столбцов в форме (col1,col2,...) создает индекс для нескольких столбцов. Величины индексов формируются путем конкатенации величин указанных столбцов.
Для столбцов типов CHAR и VARCHAR с помощью параметра col_name(length) могут создаваться индексы, для которых используется только часть столбца (для столбцов BLOB и TEXT нужно указывать длину). Команда, приведенная ниже, создает индекс, используя первые 10 символов столбца name:
mysql> CREATE INDEX part_of_name ON customer (name(10));
Поскольку большинство имен обычно имеют отличия друг от друга в первых 10 символах, данный индекс не должен быть намного медленнее, чем созданный из столбца name целиком. Кроме того, используя неполные столбцы для индексов, можно сделать файл индексов намного меньше, а это позволяет сэкономить место на диске и к тому же повысить скорость операций INSERT!
Следует учитывать, что в версии MySQL 3.23.2 и более поздних для таблиц типа MyISAM можно добавлять индекс только для столбцов, которые могут принимать величины NULL или для столбцов BLOB/TEXT.
Чтобы получить более подробную информацию о том, как MySQL использует индексы, See section 5.4.3 Использование индексов в MySQL.
С помощью опции FULLTEXT можно индексировать только столбцы VARCHAR и TEXT
и только в таблицах MyISAM. Эта возможность доступна только в версии MySQL 3.23.23 и выше. See section 6.8 Полнотекстовый поиск в MySQL.
Синтаксис оператора DROP INDEX
DROP INDEX index_name ON tbl_name
Оператор DROP INDEX удаляет индексы, указанные в index_name из таблицы tbl_name. DROP INDEX не выполняет никаких действий в версиях MySQL до 3.22. В версиях 3.22 и более поздних DROP INDEX соответствует команде ALTER TABLE в части удаления индексов. See section 6.5.4 Синтаксис оператора ALTER TABLE.
Синтаксис команды USE
USE db_name
Команда USE db_name предписывает MySQL использовать базу данных с именем db_name в последующих запросах по умолчанию. Указанная база данных остается в этом состоянии до конца данного сеанса или пока не будет выдана еще одна команда USE:
mysql> USE db1; mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable mysql> USE db2; mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable
То обстоятельство, что отдельная база данных посредством команды USE
выбирается как используемая в текущий момент по умолчанию, не является препятствием для доступа к таблицам других баз данных. Следующий пример иллюстрирует получение доступа к таблице author базы данных db1 и к таблице editor базы данных db2:
mysql> USE db1; mysql> SELECT author_name,editor_name FROM author,db2.editor WHERE author.editor_id = db2.editor.editor_id;
Наличие команды USE обеспечивает совместимость с Sybase.
Синтаксис команды DESCRIBE (Получение информации о столбцах)
{DESCRIBE | DESC} tbl_name [col_name | wild]
Команда DESCRIBE представляет собой сокращенный вариант команды SHOW COLUMNS FROM. See section 4.5.6.1 Получение информации по базам данных, таблицам, столбцам и индексам.
Команда DESCRIBE предоставляет информацию о столбцах таблицы. Параметр col_name может содержать имя столбца или строки, включающей такие групповые символы SQL, как `%' и `_' (шаблонные символы, позволяющие получить информацию о всех подходящих столбцах). В кавычки брать строку не нужно.
Следует отметить, что типы столбцов в полученном описании могут отличаться от ожидаемых, первоначально заданных командой CREATE TABLE при создании таблицы, поскольку MySQL иногда изменяет типы столбцов. See section 6.5.3.1 Молчаливые изменения определений столбцов.
Данная команда обеспечивает совместимость с Oracle.
Команда SHOW предоставляет аналогичную информацию. See section 4.5.6 Синтаксис команды SHOW.
Синтаксис команд BEGIN/COMMIT/ROLLBACK
По умолчанию MySQL работает в режиме autocommit. Это означает, что при выполнении обновления данных MySQL будет сразу записывать обновленные данные на диск.
При использовании таблиц, поддерживающих транзакции (таких как InnoDB, BDB), в MySQL можно отключить режим autocommit при помощи следующей команды:
SET AUTOCOMMIT=0
После этого необходимо применить команду COMMIT для записи изменений на диск или команду ROLLBACK, которая позволяет игнорировать изменения, произведенные с начала данной транзакции.
Если необходимо переключиться из режима AUTOCOMMIT только для выполнения одной последовательности команд, то для этого можно использовать команду START TRANSACTION
или BEGIN или BEGIN WORK:
START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summmary=@A WHERE type=1; COMMIT;
START TRANSACTION была добавлена в MySQL 4.0.11. Это - рекомендованный способ открыть транзакцию, в соответствии с синтаксисом ANSI SQL.
Отметим, что при использовании таблиц, не поддерживающих транзакции, изменения будут записаны сразу же, независимо от статуса режима autocommit.
При выполнении команды ROLLBACK после обновления таблицы, не поддерживающей транзакции, пользователь получит ошибку (ER_WARNING_NOT_COMPLETE_ROLLBACK) в виде предупреждения. Все таблицы, поддерживающие транзакции, будут перезаписаны, но ни одна таблица, не поддерживающая транзакции, не будет изменена.
При выполнении команд START TRANSACTION или SET AUTOCOMMIT=0 необходимо использовать двоичный журнал MySQL для резервных копий вместо более старого журнала записи изменений. Транзакции сохраняются в двоичном системном журнале как одна порция данных (перед операцией COMMIT), чтобы гарантировать, что транзакции, по которым происходит откат, не записываются. See section 4.9.4 Бинарный журнал обновлений.
Следующие команды автоматически завершают транзакцию (как если бы перед выполнением данной команды была сделана операция COMMIT ):
Команда | Команда | Команда |
ALTER TABLE | BEGIN | CREATE INDEX |
DROP DATABASE | DROP TABLE | RENAME TABLE |
TRUNCATE | | |
Уровень изоляции для транзакций можно изменить с помощью команды SET TRANSACTION ISOLATION LEVEL .... See section 6.7.3 Синтаксис команды SET TRANSACTION.
Синтаксис команд LOCK TABLES/UNLOCK TABLES
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES
Команда LOCK TABLES блокирует указанные в ней таблицы для данного потока. Команда UNLOCK TABLES снимает любые блокировки, удерживаемые данным потоком. Все таблицы, заблокированные текущим потоком, автоматически разблокируются при появлении в потоке иной команды LOCK TABLES или при прекращении соединения с сервером.
Чтобы использовать команду LOCK TABLES в MySQL 4.0.2, необходимо иметь глобальные привилегии LOCK TABLES и SELECT для заданных таблиц. В MySQL 3.23 для этого необходимы привилегии SELECT, INSERT, DELETE и UPDATE для рассматриваемых таблиц.
Основные преимущества использования команды LOCK TABLES состоят в том, что она позволяет осуществлять эмуляцию транзакций или получить более высокую скорость при обновлении таблиц. Ниже это разъясняется более подробно.
Если в потоке возникает блокировка операции READ для некоторой таблицы, то только этот поток (и все другие потоки) могут читать из данной таблицы. Если для некоторой таблицы в потоке существует блокировка WRITE, тогда только поток, содержащий блокировку, может осуществлять операции чтения (READ) и записи (WRITE) на данной таблице. Остальные потоки блокируются.
Различие между READ LOCAL и READ состоит в том, что READ LOCAL позволяет выполнять неконфликтующие команды INSERT во время существования блокировки. Однако эту команду нельзя использовать для работы с файлами базы данных вне сервера MySQL во время данной блокировки.
При использовании команды LOCK TABLES необходимо блокировать все таблицы, которые предполагается использовать в последующих запросах, употребляя при этом те же самые псевдонимы, которые будут в запросах! Если таблица упоминается в запросе несколько раз (с псевдонимами), необходимо заблокировать каждый псевдоним!
Блокировка WRITE обычно имеет более высокий приоритет, чем блокировка READ, чтобы гарантировать, что изменения обрабатываются так быстро, как возможно. Это означает, что если один поток получает блокировку READ и затем иной поток запрашивает блокировку WRITE, последующие запросы на блокировку READ будут ожидать, пока поток WRITE не получит блокировку и не снимет ее. Можно использовать блокировки LOW_PRIORITY WRITE, позволяющие другим потокам получать блокировки READ в то время, как основной поток находится в состоянии ожидания блокировки WRITE. Блокировки LOW_PRIORITY WRITE могут быть использованы только если есть уверенность, что в конечном итоге будет период времени, когда ни один из потоков не будет иметь блокировки READ.
Команда LOCK TABLES работает следующим образом:
Сортирует все блокируемые таблицы в порядке, который задан внутренним образом, т.е. ``зашит'' (с точки зрения пользователя этот порядок не задан).
Блокировка WRITE ставится перед блокировкой READ, если таблицы блокируются с блокировками READ и WRITE.
Блокирует одну таблицу единовременно, пока поток не получит все блокировки.
Описанный порядок действий гарантирует, что блокирование таблицы не создает тупиковой ситуации. Однако есть и другие вещи, о которых необходимо отдавать себе отчет при работе по описанной схеме:
Использование для таблицы блокировки LOW_PRIORITY WRITE всего лишь означает, что MySQL будет выполнять данную конкретную блокировку, пока не появится поток, запрашивающий блокировку READ. Если поток получил блокировку WRITE и находится в ожидании блокировки следующей таблицы из списка блокируемых таблиц, то все остальные потоки будут ожидать, пока блокировка WRITE не будет снята. Если это представляет серьезную проблему для вашего приложения, то следует подумать о преобразовании имеющихся таблиц в таблицы иного вида, поддерживающие транзакции.
Поток, ожидающий блокировку таблицы, можно безопасно уничтожить с помощью команды KILL. See section 4.5.5 Синтаксис команды KILL.
Учтите, что нельзя блокировать любые таблицы, используемые совместно с оператором INSERT DELAYED, поскольку в этом случае команда INSERT
выполняется как отдельный поток.
Обычно нет необходимости блокировать таблицы, поскольку все единичные команды UPDATE являются неделимыми; никакой другой поток не может взаимодействовать с какой-либо SQL-командой, выполняемой в данное время. Однако в некоторых случаях предпочтительно тем или иным образом осуществлять блокировку таблиц:
Если предполагается выполнить большое количество операций на группе взаимосвязанных таблиц, то быстрее всего это сделать, блокировав таблицы, которые вы собираетесь использовать. Конечно, это имеет свою обратную сторону, поскольку никакой другой поток управления не может обновить таблицу с блокировкой READ или прочитать таблицу с блокировкой WRITE. При блокировке LOCK TABLES операции выполняются быстрее потому, что в этом случае MySQL не производит запись на диск содержимого кэша ключей для заблокированных таблиц, пока не будет вызвана команда UNLOCK TABLES (обычно кэш ключей записывается на диск после каждой SQL-команды). Применение LOCK TABLES увеличивает скорость записи/обновления/удаления в таблицах типа MyISAM.
Если вы используете таблицы, не поддерживающие транзакций, то при использовании программы обработки таблиц необходимо применять команду LOCK TABLES
для гарантии, что никакой другой поток не вклинился между операциями SELECT и UPDATE. Ниже показан пример, требующий использования LOCK TABLES для успешного выполнения операций:
mysql> LOCK TABLES trans READ, customer WRITE; mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id; mysql> UPDATE customer SET total_value=sum_from_previous_statement WHERE customer_id=some_id; mysql> UNLOCK TABLES;
Без использования LOCK TABLES существует вероятность того, что какой-либо иной поток управления может вставить новую строку в таблицу trans между выполнением операций SELECT и UPDATE.
Используя пошаговые обновления (UPDATE customer SET value=value+new_value) или функцию LAST_INSERT_ID(), применения команды LOCK TABLES во многих случаях можно избежать.
Некоторые проблемы можно также решить путем применения блокирующих функций на уровне пользователя GET_LOCK() и RELEASE_LOCK(). Эти блоки хранятся в хэш-таблице на сервере и, чтобы обеспечить высокую скорость, реализованы в виде pthread_mutex_lock() и pthread_mutex_unlock(). See section 6.3.6.2 Разные функции.
Чтобы получить дополнительную информацию о механизме блокировки, обращайтесь к разделу section 5.3.1 Как MySQL блокирует таблицы.
Можно блокировать все таблицы во всех базах данных блокировкой READ с помощью команды FLUSH TABLES WITH READ LOCK. See section 4.5.3 Синтаксис команды FLUSH. Это очень удобно для получения резервной копии файловой системы, подобной Veritas, при работе в которой могут потребоваться заблаговременные копии памяти.
Примечание: Команда LOCK TABLES не сохраняет транзакции и автоматически фиксирует все активные транзакции перед попыткой блокировать таблицы.
Синтаксис команды SET TRANSACTION
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
Устанавливает уровень изоляции транзакций.
По умолчанию уровень изоляции устанавливается для последующей (не начальной) транзакции. При использовании ключевого слова GLOBAL данная команда устанавливает уровень изоляции по умолчанию глобально для всех новых соединений, созданных от этого момента. Однако для того чтобы выполнить данную команду, необходима привилегия SUPER. При использовании ключевого слова SESSION устанавливается уровень изоляции по умолчанию для всех будущих транзакций, выполняемых в текущем соединении.
Установить глобальный уровень изоляции по умолчанию для утилиты mysqld
можно с помощью опции --transaction-isolation=.... See section 4.1.1 Параметры командной строки mysqld.
Ограничения для полнотекстового поиска
Все параметры функции MATCH() должны быть столбцами одной и той же таблицы, т.е. частью одного и того же индекса FULLTEXT, за исключением работы MATCH() в режиме IN BOOLEAN MODE.
Список столбцов в команде MATCH() должен точно соответствовать списку столбцов в определении индекса FULLTEXT для этой таблицы, за исключением работы данной функции MATCH() в режиме IN BOOLEAN MODE.
Аргумент в выражении AGAINST() должен быть неизменяемой строкой.
Тонкая настройка полнотекстового поиска в MySQL
К сожалению, полнотекстовый поиск имеет еще мало настраиваемых пользователем параметров, хотя для последующих модификаций добавление некоторого их количества является очень важной задачей (TODO). Однако при наличии исходного дистрибутива MySQL (see section 2.3 Установка исходного дистрибутива MySQL) имеется больше возможностей управлять полнотекстовым поиском.
Следует отметить, что полнотекстовый поиск был тщательно настроен так, чтобы обеспечить наилучшую эффективность выполнения данной операции. Если изменить установленный по умолчанию режим работы, то в большинстве случаев результаты поиска станут только хуже. Поэтому не вносите какие-либо правки в код MySQL, если не знаете наверняка, что вы делаете!
Минимальная длина подлежащих индексации слов определяется в MySQL переменной ft_min_word_len (see section 4.5.6.4 SHOW VARIABLES). Установите желаемую величину этой переменной и создайте заново индексы FULLTEXT
(эта переменная доступна только в версии MySQL 4.0).
Список стоп-слов может быть загружен с файла, указанного в переменной ft_stopword_file. See section 4.5.6.4 SHOW VARIABLES. После модификации стоп-листа перестройте ваши полнотекствые индексы. (Эта переменная введена в MySQL 4.0.10)
50-процентный порог определяется выбранной конкретной схемой присваивания весовых коэффициентов. Чтобы отменить ее, измените следующую строку в `myisam/ftdefs.h':
#define GWS_IN_USE GWS_PROB
на:
#define GWS_IN_USE GWS_FREQ
Затем перекомпилируйте MySQL. Создавать заново индексы в этом случае нет необходимости.
Примечание: таким образом вы существенно ухудшите способность MySQL продуцировать адекватные величины релевантности для функции MATCH(). Если действительно необходим поиск для таких общеупотребительных слов, то было бы лучше использовать вместо этого поиск в режиме IN BOOLEAN MODE, при котором не предусмотрен 50-процентный порог.
Иногда отладчик поисковой машины желает изменить операторы, используемые для логического поиска по полному тексту. Эти операторы определяются переменной ft_boolean_syntax. See section 4.5.6.4 SHOW VARIABLES. Однако эта переменная доступна только для чтения, ее значение устанавливается в `myisam/ft_static.c'.
Наиболее простым способом перестроить полнотекстовый индекс в тех случаях, когда это нужно - это вот такая команда:
mysql> REPAIR TABLE tbl_name QUICK;
Предстоящие доработки по полнотекстовому поиску
Сделать все операции с индексом FULLTEXT более быстрыми.
Операторы схожести
Поддержка для слов, тождественных индексам, - чтобы словами могли быть любые строки, которые пользователь пожелает трактовать как слова, например "C++", "AS/400", "TCP/IP" и т.д.
Поддержка полнотекстового поиска в таблицах типа MERGE.
Поддержка многобайтовых наборов символов.
Сделать список стоп-слов (``stopword'') зависящим от языка данных.
Стемминг (в зависимости от языка данных, конечно).
Обобщенный синтаксический пре-анализатор с определяемым пользователем функциониями (UDF).
Сделать данную модель поиска более гибкой (путем добавления ряда регулируемых параметров к FULLTEXT в CREATE/ALTER TABLE).
Полнотекстовый поиск в MySQL
С 3.23.23 MySQL поддерживает полнотекстовый поиск и индексацию. Полнотекстовые индексы в MySQL обозначаются как индексы типа FULLTEXT. Эти индексы могут быть созданы в таблицах MyISAM в столбцах VARCHAR и TEXT во время создания таблицы командой CREATE TABLE или добавлены позже с помощью команд ALTER TABLE или CREATE INDEX. Загрузка больших массивов данных в таблицу будет происходить намного быстрее, если таблица не содержит индекс FULLTEXT, который затем создается командой ALTER TABLE (или CREATE INDEX). Загрузка данных в таблицу, уже имеющую индекс FULLTEXT, будет более медленной.
Полнотекстовый поиск выполняется с помощью функции MATCH().
mysql> CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) ); Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO articles VALUES -> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'), -> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'), -> (NULL,'Optimising MySQL','In this tutorial we will show ...'), -> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), -> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'), -> (NULL,'MySQL Security', 'When configured properly, MySQL ...'); Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
Функция MATCH() выполняет поиск в естественном языке, сравнивая строку с содержимым текста (совокупность одного или более столбцов, включенных в индекс FULLTEXT). Строка поиска задается как аргумент в выражении AGAINST(). Поиск выполняется без учета регистра символов. Для каждой строки столбца в заданной таблице команда MATCH() возвращает величину релевантности, т.е. степень сходства между строкой поиска и текстом, содержащимся в данной строке указанного в списке оператора MATCH() столбца.
Когда команда MATCH() используется в выражении WHERE (см. пример выше), возвращенные строки столбцов автоматически сортируются, начиная с наиболее релевантных. Величина релевантности представляет собой неотрицательное число с плавающей точкой. Релевантность вычисляется на основе количества слов в данной строке столбца, количества уникальных слов в этой строке, общего количества слов в тексте и числа документов (строк), содержащих отдельное слово.
Поиск возможен также в логическом режиме, это объясняется ниже в данном разделе.
Предыдущий пример представляет собой общую иллюстрацию использования функции MATCH(). Строки возвращаются в порядке уменьшения релевантности.
В следующем примере показано, как извлекать величины релевантности в явном виде. В случае отсутствия выражений WHERE и ORDER BY возвращаемые строки не упорядочиваются.
mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles; +----+-----------------------------------------+ | id | MATCH (title,body) AGAINST ('Tutorial') | +----+-----------------------------------------+ | 1 | 0.64840710366884 | | 2 | 0 | | 3 | 0.66266459031789 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-----------------------------------------+ 6 rows in set (0.00 sec)
Следующий пример - более сложный. Запрос возвращает значение релевантности и, кроме того, сортирует строки в порядке убывания релевантности. Чтобы получить такой результат, необходимо указать MATCH() дважды. Это не приведет к дополнительным издержкам, так как оптимизатор MySQL учтет, что эти два вызова MATCH() идентичны, и запустит код полнотекстового поиска только однажды.
mysql> SELECT id, body, MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root') AS score -> FROM articles WHERE MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root'); +----+-------------------------------------+-----------------+ | id | body | score | +----+-------------------------------------+-----------------+ | 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 | | 6 | When configured properly, MySQL ... | 1.31140957288 | +----+-------------------------------------+-----------------+ 2 rows in set (0.00 sec)
Для разбивки текста на слова MySQL использует очень простой синтаксический анализатор. ``Словом'' является любая последовательность символов, состоящая из букв, чисел, знаков `'' и `_'. Любое ``слово'', присутствующее в стоп-списке (stopword) или просто слишком короткое (3 символа или меньше), игнорируется.
Каждое правильное слово в наборе проверяемых текстов и в данном запросе оценивается в соответствии с его важностью в этом запросе или наборе текстов. Таким образом, слово, присутствующее во многих документах, будет иметь меньший вес (и даже, возможно, нулевой), как имеющее более низкое смысловое значение в данном конкретном наборе текстов. С другой стороны, редко встречающееся слово получит более высокий вес. Затем полученные значения весов слов объединяются для вычисления релевантности данной строки столбца.
Описанная техника подсчета лучше всего работает для больших наборов текстов (фактически она именно для этого тщательно настраивалась). Для очень малых таблиц распределение слов не отражает адекватно их смысловое значение, и данная модель иногда может выдавать некорректные результаты.
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL'); Empty set (0.00 sec)
Поиск по слову ``MySQL'' в предыдущем примере не приводит к каким-либо результатам, так как это слово присутствует более чем в половине строк. По существу, данное слово целесообразно трактовать как стоп-слово (т.е. слово с нулевой смысловой ценностью). Это наиболее приемлемое решение - запрос на естественном языке не должен возвращать каждую вторую строку из таблицы размером 1Гб.
Маловероятно, что слово, встречающееся в половине строк таблицы, определяет местонахождение релевантных документов. На самом деле, наиболее вероятно, что будет найдено много не относящихся к делу документов. Общеизвестно, что такое случается слишком часто при попытке найти что-либо в Интернет с помощью поисковых машин. Именно на этом основании подобным строкам должно быть назначено низкое смысловое значение в данном конкретном наборе данных.
В MySQL 4.0. 1 возможен полнотекстовый поиск также и в логическом режиме с использованием модификатора IN BOOLEAN MODE.
mysql> SELECT * FROM articles WHERE MATCH (title,body) -> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); +----+------------------------------+-------------------------------------+ | id | title | body | +----+------------------------------+-------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 2 | How To Use MySQL Efficiently | After you went through a ... | | 3 | Optimising MySQL | In this tutorial we will show ... | | 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | | 6 | MySQL Security | When configured properly, MySQL ... | +----+------------------------------+-------------------------------------+
Данный запрос вывел все строки, содержащие слово ``MySQL'' (заметьте, 50-процентная пороговая величина здесь не используется), но эти строки не содержат слова ``YourSQL''. Следует отметить, что логический режим поиска не сортирует автоматически строки в порядке уменьшения релевантности. Это видно по результату предыдущего запроса, где строка с наиболее высокой релевантностью (содержащая слово ``MySQL'' дважды) помещена последней, а не первой. Логический режим полнотекстового поиска может работать даже без индекса FULLTEXT, хотя и очень медленно.
В логическом режиме полнотекстового поиска поддерживаются следующие операторы:
+
Предшествующий слову знак ``плюс'' показывает, что это слово должно присутствовать в каждой возвращенной строке.
-
Предшествующий слову знак ``минус'' означает, что это слово не должно присутствовать в какой-либо возвращенной строке.
По умолчанию (если ни плюс, ни минус не указаны) данное слово является не обязательным, но содержащие его строки будут оцениваться более высоко. Это имитирует поведение команды MATCH() ... AGAINST() без модификатора IN BOOLEAN MODE.
< >
Эти два оператора используются для того, чтобы изменить вклад слова в величину релевантности, которое приписывается строке. Оператор уменьшает этот вклад, а оператор > - увеличивает его. См. пример ниже.
( )
Круглые скобки группируют слова в подвыражения.
~
Предшествующий слову знак ``тильда'' воздействует как оператор отрицания, обуславливая негативный вклад данного слова в релевантность строки. Им отмечают нежелательные слова. Строка, содержащая такое слово, будет оценена ниже других, но не будет исключена совершенно, как в случае оператора - ``минус''.
*
Звездочка является оператором усечения. В отличие от остальных операторов, она должна добавляться в конце слова, а не в начале.
"
Фраза, заключенная в двойные кавычки, соответствует только строкам, содержащим эту фразу, написанную буквально.
Ниже приведен ряд примеров:
apple banana
находит строки, содержащие по меньшей мере одно из этих слов.
+apple +juice
... оба слова.
+apple macintosh
... слово ``apple'', но ранг строки выше, если она также содержит слово ``macintosh''.
+apple -macintosh
... слово ``apple'', но не ``macintosh''.
+apple +(>pie
... ``apple'' и ``pie'', или ``apple'' и ``strudel'' (в любом порядке), но ранг ``apple pie'' выше, чем ``apple strudel''.
apple*
... ``apple'', ``apples'', ``applesauce'', и ``applet''.
"some words"
... ``some words of wisdom'', но не ``some noise words''.
Как работает кэширование запросов
Перед синтаксическим анализом запросы сравниваются, поэтому запросы
SELECT * FROM tbl_name
и
Select * from tbl_name
для кэша запросов рассматриваются как различные, поскольку они должны быть абсолютно одинаковыми (байт в байт), чтобы рассматриваться как идентичные. Помимо этого, запрос может трактоваться как отличающийся, если, например, какой-либо клиент использует протокол соединения нового формата или иной набор символов, чем другой клиент.
Запросы, использующие различные базы данных, различные версии протоколов или различные наборы символов по умолчанию, рассматриваются как различные и кэшируются раздельно.
Рассматриваемый кэш надежно работает для запросов вида SELECT CALC_ROWS ... и SELECT FOUND_ROWS() ..., так как число найденных строк всегда хранится в кэше.
Если результат запроса вернулся из кеша запросов, тогда статусная переменная Com_select не будет увеличена, но вместо нее будет увеличена Qcache_hits. See section 6.9.4 Статус и поддержка кэша запросов.
При изменениях таблицы (INSERT, UPDATE, DELETE, TRUNCATE, ALTER или DROP TABLE|DATABASE), все кэшированные запросы, использовавшие данную таблицу (возможно, через таблицу MRG_MyISAM!), становятся недействительными и удаляются из кэша.
Если изменения были произведены в поддерживающих транзакции таблицах вида InnoDB, то все кэшированные запросы становятся недействительными при выполнении команды COMMIT.
Запрос не будет кэширован, если содержит одну из приведенных ниже функций:
Функция |
Функция |
Функция |
Определяемые пользователем функции (UDF) |
CONNECTION_ID |
FOUND_ROWS |
GET_LOCK |
RELEASE_LOCK |
LOAD_FILE |
MASTER_POS_WAIT |
NOW |
SYSDATE |
CURRENT_TIMESTAMP |
CURDATE |
CURRENT_DATE |
CURTIME |
CURRENT_TIME |
DATABASE |
ENCRYPT (с одним параметром) | LAST_INSERT_ID |
RAND |
UNIX_TIMESTAMP (без параметров) | USER |
BENCHMARK |
Запрос также не будет кэширован, если он содержит переменные пользователя, работает с системными таблицами mysql, или выражен в форме SELECT ... IN SHARE MODE, SELECT ... INTO OUTFILE ..., SELECT ... INTO DUMPFILE ... или в форме SELECT * FROM AUTOINCREMENT_FIELD IS NULL (для получения последнего ID - это для ODBC).
Однако FOUND ROWS() возвратит правильную величину, даже если из кэша был выбран предыдущий запрос.
В случае если запрос не использует таблиц, или использует временные таблицы, или если пользователь обладает привилегиями уровня столбца на какую-либо из задействованных таблиц, запрос не будет кеширован.
Перед выборкой запроса из кэша запросов MySQL проверит, обладает ли пользователь привилегией SELECT для всех включенных баз данных и таблиц. Если это не так, то результат кэширования не используется.
Конфигурация кэша запросов
Для кэша запросов в MySQL добавляется несколько системных переменных для mysqld, которые могут быть установлены в конфигурационном файле или из командной строки при запуске mysqld.
query_cache_limit
Не кэшировать результаты, большие, чем указано (по умолчанию 1Мб).
query_cache_size
Память, выделенная для хранения результатов старых запросов. Если равно 0, то кэширование запроса блокируется (по умолчанию). Указывается в байтах.
query_cache_type
Можно установить следующие (только числовые) значения:
Опция | Описание |
0 | OFF (``ВЫКЛЮЧЕНО''), результаты не кэшировать и не извлекать |
1 | ON (``ВКЛЮЧЕНО''), кэшировать все результаты, за исключением запросов SELECT SQL_NO_CACHE ... |
2 | DEMAND (``ПО ТРЕБОВАНИЮ''), кэшировать только запросы SELECT SQL_CACHE ... |
Внутри потока (соединения) можно изменить функционирование кэша запросов по сравнению с установленным по умолчанию. Синтаксис следующий:
QUERY_CACHE_TYPE = OFF | ON | DEMAND QUERY_CACHE_TYPE = 0 | 1 | 2
Опция | Описание |
0 или OFF | Результаты не кэшировать и не извлекать. |
1 или ON | Кэшировать все результаты за исключением запросов SELECT SQL_NO_CACHE ... |
2 или DEMAND | Кэшировать только запросы SELECT SQL_CACHE ... |
Параметры кэша запросов в запросе SELECT
В запросе SELECT можно указывать две опции для кэша запросов:
Опция | Описание |
SQL_CACHE | Если QUERY_CACHE_TYPE имеет опцию DEMAND, позволяет запросу кэшироваться. Если QUERY_CACHE_TYPE имеет опцию ON, является состоянием по умолчанию. Если QUERY_CACHE_TYPE имеет опцию OFF, ничего не делать. |
SQL_NO_CACHE | Делает данный запрос некэшируемым, не разрешает хранить в кэше данный запрос. |
Статус и поддержка кэша запросов
С помощью команды FLUSH QUERY CACHE можно дефрагментировать кэш запросов с целью лучшего использования его памяти. Эта команда не удалит ни одного запроса из кэша. Команда FLUSH TABLES также записывает на диск содержимое кэша запросов.
Команда RESET QUERY CACHE удаляет все результаты запросов из кэша запросов.
Можно контролировать функционирование кэша запросов в SHOW STATUS:
Переменная | Описание |
Qcache_queries_in_cache | Количество запросов, зарегистрированных в кэше. |
Qcache_inserts | Количество запросов, добавленных в кэш. |
Qcache_hits | Количество результативных обращений в кэш. |
Qcache_lowmem_prunes | Количество запросов, удаленных из кеша по причине недостаточного количества памяти. |
Qcache_not_cached | Количество не кэшированных запросов (не подлежащих кэшированию или из-за установок QUERY_CACHE_TYPE). |
Qcache_free_memory | Величина свободной памяти для кэша запросов. |
Qcache_total_blocks | Общее количество блоков в кэше запросов. |
Qcache_free_blocks | Количество свободных блоков памяти в кэше запросов. |
Общее количество запросов = Qcache_inserts + Qcache_hits + Qcache_not_cached.
Кэш запросов использует блоки переменной длины, так что параметры Qcache_total_blocks и Qcache_free_blocks могут показывать фрагментацию памяти кэша запросов. После команды FLUSH QUERY CACHE остается только один (большой) свободный блок.
Примечание: каждый запрос нуждается как минимум в двух блоках (один для текста данного запроса и один или больше - для результатов запроса). Для каждой используемой в запросе таблицы также требуется один блок, но если два или более запросов используют одну и ту же таблицу, требуется выделение только одного блока.
Вы можете использовать переменную Qcache_lowmem_prunes для настройки размера кеша запросов. В ней подсчитывается количество запросов, которые были удалены из кеша для освобождения памяти под новые результаты запросов. Кеш запросов использует стратегию используется реже всего (least recently used, LRU) для принятия решений о о том, какие запросы удалить из кеша.
Кэш запросов в MySQL
Начиная с версии 4.0.1 сервер MySQL снабжен кэшем запросов. В процессе работы кэш запросов хранит текст запроса SELECT вместе с соответствующим результатом, который посылался клиенту. При получении другого идентичного запроса сервер извлечет результаты из кэша запросов, а не анализировать и выполнять снова тот же самый запрос.
Кэш запросов особенно полезен в средах, где (некоторые) таблицы не обновляются слишком часто и присутствует много идентичных запросов. Эта ситуация типична для многих веб-серверов с обширным активным информационным наполнением.
Ниже приведены некоторые данные функционирования для кэша запросов (они получены во время работы тестового комплекта MySQL под Linux Alpha 2x500 МГц с 2Гб ОЗУ и 64-мегабайтным кэшем запросов):
Если все производимые запросы являются простыми (такими как выбор строки из таблицы с одной строкой), но различаются настолько, что не могут быть кэшированы, непроизводительные затраты при активном состоянии кэша запросов составляют 13%. Это можно было бы рассматривать как сценарий наиболее неблагоприятного варианта. Однако в реальной жизни запросы более сложны, чем приведенный простой пример, так что непроизводительные затраты обычно значительно ниже.
Поиск строки в таблице с одной строкой происходит на 238% быстрее. Можно рассматривать эту величину, как близкую к минимальному увеличению быстродействия, ожидаемого при кэшировании запроса.
Если вы хотите запретить кеш запросов, установите переменную query_cache_size в 0. Запрещение кеша запросов не создает лишних перегрузок для сервера. Вы можете целиком исключить код кеша запросов из сервера путем указания при компиляции опции --without-query-cache в configure.
Справочное руководство по MySQL версии 4.1.1-alpha