Автор: Алексей Паутов
Источник: RussianLDP:MySQL
Число страниц (страница равна 2000 символов) | Краткое описание главы |
5 | Введение. Основные термины и соглашения, использованные в книге. Также обсуждает хронологию. |
7 | Глава 1 Описание стандартов, принятых в MySQL. |
35 | Глава 2 дает краткое введение в MySQL. |
8 | Глава 3 имеет дело со структурой языка. |
30 | Глава 4 рассматривает введение в администрирование. |
25 | Глава 5 подробно рассматривает типы столбцов. |
34 | Глава 6 рассматривает функции
для использования в самых главных операторах языка: SELECT и
WHERE |
18 | Глава 7 описывает определение
данных: вызовы CREATE , DROP и ALTER .
|
25 | Глава 8 объясняет манипуляции с
данными: команды SELECT , INSERT ,
UPDATE и DELETE . |
11 | Глава 9 охватывает обзор прочих инструментов языка MySQL. |
33 | Глава 10 обсуждает общие проблемы защиты и систему привилегий доступа в MySQL. |
27 | Глава 11 объясняет проблемы и общие ошибки. |
19 | Глава 12 описывает клиентские скрипты и утилиты MySQL. |
11 | Глава 13 охватывает поддержку MySQL ODBC. |
75 | Глава 14 рассказывает об оптимизации запросов. |
5 | Заключение. Ссылки на источники дополнительной информации по СУБД MySQL. |
1 | Приложение 1. Здесь описан комплектный CD-ROM. |
1 | Приложение 2. Переменные окружения. |
1 | Приложение 3. Выяснение вопросов или сообщение об ошибках в пакете |
Приложение 4. GNU GENERAL PUBLIC LICENSE. | |
Приложение 5. GNU LESSER GENERAL PUBLIC LICENSE. |
Всего: 370 страниц в формате А4.
Все перечисленные в книге программы доступны в сети. Поэтому первоначально
я не мог решить, нужно ли создавать сопроводительный CD-ROM. Но потом я
убедился, что поиск в сети всех необходимых пакетов, а главное, их скачивание
на свой
Все архивы на диске поставляются в форматах Tar+Gzip и RPM, принятых в Linux и вообще почти всех Unix-системах. Основная масса архивов взята мной с сайта разработчиков MySQL. Диск охватывает все возможные дистрибутивы и дополнения к ним, которые официально представлены для этого пакета.
ВСЕ ПРОГРАММЫ НА СОПРОВОДИТЕЛЬНОМ CD-ROM ВЗЯТЫ МНОЙ ИЗ ОТКРЫТЫХ СЕТЕВЫХ ИСТОЧНИКОВ И РАСПРОСТРАНЯЮТСЯ В СТРОГОМ СООТВЕТСТВИИ С ИХ ЛИЦЕНЗИЯМИ. ДИСК НЕ СОДЕРЖИТ ПИРАТСКИХ КОПИЙ КАКОГО БЫ ТО НИ БЫЛО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ. ОСНОВНАЯ ЧАСТЬ ПРОГРАММ НА НЕМ ПОСТАВЛЯЕТСЯ В ИСХОДНЫХ ТЕКСТАХ.
Имеется список всех системных переменных, которые используются MySQL непосредственно или косвенно. Большинство их также может быть найдено в других местах в этом руководстве.
Обратите внимание, что любые параметры в командной строке будут иметь приоритет над значениями, определенными в файлах конфигурации и системных переменных, а значения в файлах конфигурации всегда имеют приоритет над значениями в системных переменных.
Во многих случаях предпочтительно использовать файл выбора конфигурации вместо системных переменных, чтобы изменить поведение MySQL. Подробности в разделе "4.11 Файл опций my.cnf".
DBI_USER | Заданный по умолчанию пользователь для интерфейса Perl DBI. |
DBI_TRACE | Используется при трассировке Perl DBI. |
HOME | Заданный по умолчанию путь для файла
хронологии mysql , обычно $HOME/.mysql_history. |
LD_RUN_PATH | Используется, чтобы определить, где
находится Ваша библиотека libmysqlclient.so . |
MYSQL_DEBUG | Опции трассировки при отладке. |
MYSQL_HISTFILE | Путь к файлу хронологии
mysql . |
MYSQL_HOST | Заданное по умолчанию имя хоста,
используемое подсказкой командной строки mysql . |
MYSQL_PWD | Заданный по умолчанию пароль при
соединении с mysqld . Обратите внимание, что использование этой
возможности задания пароля опасно! |
MYSQL_TCP_PORT | Заданный по умолчанию порт TCP/IP. |
MYSQL_UNIX_PORT | Сокет по умолчанию. Используется
для связи с localhost . |
PATH | Используется оболочкой для поиска программ и утилит пакета MySQL. |
TMPDIR | Каталог, где будут созданы временные таблицы или файлы. |
TZ | Это должно быть установлено к Вашей зоне местного времени. Подробности в разделе "11.4.6 Проблемы часового пояса". |
UMASK_DIR | Создание каталога пользователя будет
выполнено с данной маской прав доступа. Обратите внимание, что это значение
будет использовано в операции AND с UMASK ! |
UMASK | То же самое, но для создания файлов. |
USER | Заданный по умолчанию пользователь в
Windows, чтобы использовать при соединении с mysqld .
|
Перед отправкой отчета об ошибке или вопроса сделайте следующее:
Если Вы не можете найти ответ в руководстве или архиве, проконсультируйтесь с Вашим локальным экспертом MySQL. Если Вы все еще не можете найти ответ на Ваш вопрос, читайте следующий раздел относительно того, как послать запрос на mysql@lists.mysql.com.
Написание хорошего отчета об ошибке требует немало терпения, но при выполнении этого экономится много времени Вам и всем окружающим. Хороший отчет об ошибке, содержащий полный случай теста для ошибки, делает весьма вероятным скорейшее исправление проблемы. Этот раздел поможет Вам написать Ваш отчет так, чтобы Вы не тратили впустую Ваше время, выполняя действия, которые не могут ничем помочь.
Пользуйтесь скриптом mysqlbug
, чтобы генерировать отчет об
ошибке (или отчет относительно любой проблемы), если возможно. Сам
mysqlbug
может быть найден в каталоге scripts в
дистрибутиве исходного кода или (для двоичного дистрибутива) в каталоге
bin под Вашим каталогом установки MySQL. Если Вы не можете
использовать mysqlbug
, Вы должны все же включать всю необходимую
информацию, перечисленную в этом разделе.
Скрипт mysqlbug
помогает Вам сгенерировать отчет, определяя
многое из следующей информации автоматически, но если кое-что важное
отсутствует, пожалуйста, включите это в Ваше сообщение! Пожалуйста, читайте
этот раздел тщательно и удостоверьтесь, что вся информация, описанная здесь,
включена в Ваш отчет.
Нормальное место, чтобы сообщить ошибки и проблемы:
mysql@lists.mysql.com. Если Вы
можете создать случай теста, который ясно показывает ошибку, Вы должны его
послать на bugs@lists.mysql.com.
Обратите внимание, что в этом списке Вы должны только регистрировать полный
повторимый отчет ошибки, использующий скрипт mysqlbug
. Если Вы
работаете под Windows, Вы должны включить описание операционной системы и
версии MySQL. Предпочтительно, Вы должны проверить проблему при использовании
последнего устойчивого дистрибутива или версии для разработчика. Любой должен
быть способен повторить ошибку, используя только mysql test<script
на включенном случае теста или выполнить скрипт, который включен в
отчет ошибки. Все ошибки, зарегистрированные в списке bugs
,
будут исправлены или зарегистрированы в следующем выпуске MySQL! Если имеются
только маленькие изменения кода, в этом списке может быть опубликован патч.
Не забудьте, что можно ответить на сообщение, содержащее слишком много информации, но не на то, в котором полезных данных очень мало. Часто люди опускают факты потому, что они думают, что они знают причину проблемы и считают, что некоторые важнейшие детали не имеют значения. Хороший принцип: если Вы находитесь в сомнении относительно установления чего-либо, устанавливайте это! Это намного ускорит и упростит работу всем остальным.
Наиболее общие ошибки состоят в том, что люди не указывают номер версии MySQL или ОС (включая ее версию!), на которой работают. Это очень важная информация, и в 99 случаях из 100 отчет об ошибке без нее бесполезен! Часто спрашивают об ошибках, которые есть в старых версиях, но их уже нет в новых. Обновляйте софт, меньше будет проблем! Иногда ошибка платформно-зависимая, в таких ситуациях почти невозможно установить что-нибудь без того, чтобы знать операционную систему и номер версии платформы.
Не забудьте также обеспечивать информацию относительно Вашего компилятора, если это связано с проблемой. Часто люди находят ошибки в компиляторах и считают, что это проблемы MySQL. Большинство компиляторов вечно находятся в состоянии разработки и совершенствования. Чтобы определить, зависит или нет Ваша проблема от компилятора, авторы должны знать, какой именно компилятор используется. Обратите внимание, что каждая проблема компиляции должна быть расценена как отчет об ошибке и сообщена соответственно.
Самые лучшие отчеты такие, которые включают полный пример, показывающий как воспроизвести ошибку или проблему.
Если программа производит сообщение об ошибках, очень важно включить сообщение в Ваш отчет! Если мы пробуем искать данные из архива, используя сведения по этой программе лучше, чтобы присланное сообщение об ошибках точно соответствовало тому, которое программа производит. Вы никогда не должны пробовать запомнить то, что было в сообщении об ошибке, вместо этого скопируйте и вставьте сообщение в Ваш отчет!
Пожалуйста, не забудьте, что многие из тех, кто будет читать Ваш отчет,
применяют монитор в режиме с 80 символами в строке. Следовательно, при
изготовлении отчетов и примеров с использованием клиента mysql
Вы должны использовать опцию --vertical
(или завершать команду
комбинацией символов \G
) для вывода, который не превысит
доступную ширину для такого дисплея (например, инструкция EXPLAIN
SELECT
, подробности ниже).
Пожалуйста, включите следующую информацию в Ваш отчет:
mysqladmin
version
. mysqladmin
может быть найден в каталоге
bin под каталогом установок MySQL.
uname -a
.
mysqld
рухнул, Вы должны также сообщить запрос, который
потерпел крах. Вы можете обычно найти его, запуская
mysqld
с включеным протоколированием.
mysqldump --no-data db_name tbl_name1 tbl_name2 ...
. Это очень
простой и мощный способ получить информацию относительно любой таблицы в базе
данных, которая поможет создать ситуацию, соответствующую той, что у Вас.
SELECT
Вы должны всегда включать вывод
EXPLAIN SELECT ...
и по крайней мере число строк, которые
производит инструкция SELECT
. Большее количество информации,
которую Вы даете относительно Вашей ситуации, делает более вероятным, что
кто-то сможет помочь Вам! Например, следующее представляет собой пример очень
хорошо составленного отчета об ошибке (это должно быть, конечно, создано с
помощью скрипта mysqlbug
). Обратите внимание на использование
признака конца оператора \G
для инструкций, чья ширина вывода
иначе превысила бы 80 символов:
mysql> SHOW VARIABLES; mysql> SHOW COLUMNS FROM ...\G < Вывод SHOW COLUMNS> mysql> EXPLAIN SELECT ...\G < Вывод EXPLAIN> mysql> FLUSH STATUS; mysql> SELECT ...; < Короткая версия вывода из SELECT, включая время, затраченное на обработку запроса> mysql> SHOW STATUS; < Вывод SHOW STATUS>
mysqladmin variables
extended-status processlist
, чтобы обеспечить некоторую информацию о
раболте Вашей системы.
mysqldump
, и создать файл README, который
описывает Вашу проблему. Создайте сжатый архив Ваших файлов, используя
tar
и gzip
(или zip
), и передайте его
по ftp
на
ftp://support.mysql.com/pub/mysql/secret. Затем пошлите короткое описание
проблемы на bugs@lists.mysql.com.
ftp
на
ftp://support.mysql.com/pub/mysql/secret. Если данные совершенно
секретны, используйте другие имена, но это крайние меры.
mysqld
, и что Вы используете, чтобы выполнить любые программы
клиента MySQL. Параметры к программам mysqld
и
mysql
, а также скрипту configure
, часто являются
ключами к решениям и очень нужны. Во всяком случае включить их не помешает.
Если Вы используете любые модули, типа Perl или PHP, пожалуйста, включите
также номера их версий.
mysqlaccess
, mysqladmin reload
и все сообщения об
ошибках, которые Вы получили при попытке подключить! Когда Вы проверяете Ваши
привилегии, Вы должны сначала выполнить mysqlaccess
. После этого
выполните mysqladmin reload version
и попробуйте соединиться с
программой, которая создает проблему. Команда mysqlaccess
есть в
каталоге bin под каталогом установки MySQL.
parse
error
), пожалуйста, проверьте Ваш синтаксис очень тщательно! Если Вы
не можете найти что-то неправильное в нем, чрезвычайно вероятно, что Ваша
текущая версия MySQL просто не поддерживает запрос, который Вы используете.
Если Вы применяете самую свежую версию, и руководство на
http://www.mysql.com/documentation/manual.php не покрывает синтаксис,
который Вы применили, значит MySQL не поддерживает Ваш запрос. Если
руководство покрывает синтаксис, который Вы используете, но Вы имеете старую
версию MySQL, Вы должны проверить хронологию изменения MySQL, чтобы увидеть,
когда синтаксис был реализован. В этом случае следует обновить версию.
myisamchk
или
CHECK TABLE
и REPAIR TABLE
.
mysqld
никогда не должен разрушить таблицу,
если ничто не уничтожило его посреди модификации. Если Вы можете найти
причину слета mysqld
, это сильно облегчит работу.
Направьте отчет на адрес соответствующей рассылки. Может кто-то еще испытал (и возможно решил) такую проблему. Если Вы подписаны на поддержку, пишите на mysql-support@mysql.com.
Когда ответы посланы Вам индивидуально, а не списку рассылки, считается хорошим тоном суммировать ответы и послать резюме в список рассылки, чтобы все могли с ним ознакомиться и решить свои проблемы.
Если Вы полагаете, что Ваш ответ представляет широкий интерес, Вы можете отправить его в список рассылки вместо того, чтобы ответить лично индивидууму, который Вас спросил. Пожалуйста, удостоверьтесь, что Ваш ответ не дублирует другой.
Попробуйте суммировать существенную часть вопроса в Вашем ответе, не надо цитировать все первоначальное сообщение. Пожалуйста, не отправляйте сообщения почты из Вашего браузера с включенным режимом HTML! Много пользователей не читают почту в браузере.
Version 2, June 1991
Copyright © 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
9.4 NO WARRANTY
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.
one line to give the program's name and a brief idea of what it does. Copyright (C) yyyy name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
Version 2.1, February 1999
Copyright © 1991, 1999 Free Software Foundation, Inc. 59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
We call this license the Lesser General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a ``work based on the library'' and a ``work that uses the library''. The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
9.6 NO WARRANTY
If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.
one line to give the library's name and an idea of what it does. Copyright (C) year name of author This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the library, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. signature of Ty Coon, 1 April 1990 Ty Coon, President of Vice
That's all there is to it!
Вот и подошел к концу начальный обзор базовых средств СУБД MySQL. Конечно, данная работа не покрывает все вопросы, связанные с работой пакета MySQL. Это, пожалуй, вообще невозможно: слишком уж многообразны вопросы, очень много существует интересных и сложных тем для обсуждения. Поэтому в конце приведен список рекомендованных сайтов, где можно получить дополнительную информацию и советы по возникшей проблеме.
Автор выражает надежду, что эта книга не является последней, и послужит для читателя лишь первым шагом в изучении сложного и интересного мира под названием "СУБД MySQL".
Тема работы с СУБД MySQL очень сложна и обширна. Охватить все в одной книге едва ли возможно, и я сейчас это понимаю куда лучше, чем перед написанием данной работы.
В этой книге ставилась задача охватить лишь первоначальные сведения о пакете, но сделать это на таком уровне, чтобы рядовой пользователь клиентской части пакета не только научился что-то делать, но и хорошо понимал, что и зачем он делает. Эта книга изначально задумывалась как противовес некоторым современным руководствам системы "шаг в сторону считается побегом", которые лишь дают конкретные решения очень узких проблем, совершенно не объясняя сути всех этих решений.
К сожалению, не могу порекомендовать никакой литературы на русском языке по данному направлению: литература-то есть, хоть ее и мало, но она ориентирована на совсем иной уровень подготовки читателя и другие решаемые задачи. Зато имеется огромное количество ресурсов Internet по MySQL. Большая их часть на английском языке, однако, именно там можно найти много ценного.
Очень хорошую подборку книг по MySQL, разделенную по темам, можно найти на http://www.mysql.com/portal/books/html/index.html. Сразу предупреждаю, что на русском языке в сети есть только одна работа (написана автором этой книги) http://www.botik.ru/~rldp/articles/mysqlrus/mysqlrus.htm. Она есть на множестве зеркал в сети, так что Вы ее без труда найдете. Вся прочая информация доступна, главным образом, на английском языке.
Учебники могут быть найдены на: http://www.mysql.com/portal/development/html/development-61-1.html
Много ссылок есть на сайте разработчиков MySQL: http://www.mysql.com/portal/development/html/index.html
Кроме следующих ссылок Вы можете найти и скачать много программ MySQL, инструментальных средств и API из каталога Contrib.
Учебники и руководства по MySQLmSQL
.
mSQL
Tcl.
DBI
/DBD
.
DBI
/DBD
.
Имеется также много Web-страниц по использованию MySQL. Подробности в разделе "Некоторые пользователи MySQL". Пошлите любые добавления к этому списку на webmaster@mysql.com. Авторы пакета требуют, чтобы Вы показали эмблему MySQL где-нибудь, если Вы желаете, чтобы Ваш сайт был добавлен в список.
Этот раздел представляет списки рассылки по MySQL и дает некоторые руководящие принципы относительно того, как использовать их.
Чтобы подписаться на главный список рассылки MySQL, пошлите сообщение на mysql-subscribe@lists.mysql.com.
Чтобы отписаться от главного списка рассылки MySQL, пошлите сообщение на mysql-unsubscribe@lists.mysql.com.
Только адрес, с которого Вы посылаете Ваши сообщения, важен. Тема и тело письма не рассматриваются.
Если Ваш адрес ответа неправилен, Вы можете определять ваш адрес явно.
Добавление дефиса к слову subscribe или unsubscribe, сопровождаемое Вашим
адресом, произведет нужный эффект. Замените в адресе символ @
на =. Например, чтобы подписать
your_name@host.domain
, направьте письмо на адрес
mysql-subscribe-your_name=host.domain@lists.mysql.com
.
Почта на адреса mysql-subscribe@lists.mysql.com и mysql-unsubscribe@lists.mysql.com автоматически обрабатывается процессором списка адресатов ezmlm. Информация относительно ezmlm доступна на Web-сайте пакета ezmlm http://www.ezmlm.org .
Чтобы регистрировать сообщение в списке, пошлите его на адрес
mysql@lists.mysql.com
. Однако, пожалуйста, не шлите
туда просьбы о подписке или отписке: список их размножит тысячам читателей.
Если на Вашей локальной машине есть несколько подписчиков рассылки
lists.mysql.com
, стоит подумать о создании своего локального
списка рассылки, чтобы письма с lists.mysql.com
приходили на
Вашу систему в одном экземпляре.
Если Вы хотите отфильтровать сообщения из списка в отдельный почтовый ящик
или еще куда-то, поставьте фильтр, реагирующий на поля List-ID:
или Delivered-To:
в заголовках сообщений рассылки.
Есть следующие списки рассылки:
announce-subscribe@lists.mysql.com announce
mysql-subscribe@lists.mysql.com mysql
mysql-digest-subscribe@lists.mysql.com mysql-digest
mysql
. Это означает, что Вы
получаете все индивидуальные сообщения, посланные как одно большое сообщение
почты один раз в день.
bugs-subscribe@lists.mysql.com bugs
mysqlbug
(если Вы работаете под Windows, Вы
должны включить описание операционной системы и версии MySQL).
Предпочтительно, чтобы Вы проверили проблему при использовании последней
версии пакета. Любой должен быть способен повторить ошибку, используя только
mysql test < script
на присланном образце. Все ошибки,
зарегистрированные в этом списке, будут исправлены или зарегистрированы в
следующем выпуске MySQL. Если имеются только маленькие изменения кода, авторы
также публикуют здесь заплатку, которая решает проблему.
bugs-digest-subscribe@lists.mysql.com bugs-digest
bugs
в виде дайджеста.
internals-subscribe@lists.mysql.com internals
internals-digest-subscribe@lists.mysql.com internals-digest
internals
.
java-subscribe@lists.mysql.com java
java-digest-subscribe@lists.mysql.com java-digest
java
.
win32-subscribe@lists.mysql.com win32
win32-digest-subscribe@lists.mysql.com win32-digest
win32
.
myodbc-subscribe@lists.mysql.com myodbc
myodbc-digest-subscribe@lists.mysql.com myodbc-digest
myodbc
.
plusplus-subscribe@lists.mysql.com plusplus
plusplus-digest-subscribe@lists.mysql.com plusplus-digest
plusplus
.
msql-mysql-modules-subscribe@lists.mysql.com msql-mysql-modules
msql-mysql-modules-digest-subscribe@lists.mysql.com
msql-mysql-modules-digest
msql-mysql-modules
.Подписка на любой список рассылки (как и отписка от него) рассмотрены
выше. Например, чтобы подписаться на список myodbc
(или
отписаться от него), просто пошлите любое сообщение на адрес
myodbc-subscribe@lists.mysql.com или на адрес
myodbc-unsubscribe@lists.mysql.com.
Следующая таблица показывает некоторые рассылки по MySQL не на английском языке. Обратите внимание, что они не эксплуатируются MySQL AB, так что мы не можем гарантировать их качество.
mysql-france-subscribe@yahoogroups.com
list@tinc.net
subscribe mysql your@email.address
,
чтобы подписаться.
mysql-de-request@lists.4t2.com
subscribe mysql-de
your@email.address
, чтобы подписаться. Вы можете найти информацию
относительно этого списка на
http://www.4t2.com/mysql.
mysql-br-request@listas.linkway.com.br
subscribe mysql-br
your@email.address
, чтобы подписаться.
mysql-alta@elistas.net
subscribe mysql
your@email.address
, чтобы подписаться.MySQL очень быстрый, многопоточный, многопользовательский и поддерживающий SQL (Structured Query Language) сервер баз данных.
MySQL является free software. Он лицензируется по GNU GENERAL PUBLIC LICENSE http://www.gnu.org.
Сайт MySQL предоставляет последнюю информацию касательно MySQL.
Следующий перечень описывает наиболее интересные места руководства:
ВАЖНО:
Сообщения об ошибках также как вопросы и комментарии, должны быть посланы
списку рассылки
mysql@lists.mysql.com. Подробности в разделе
"Как сообщать о проблемах и сбоях".
Скрипт mysqlbug
должен использоваться, чтобы генерировать отчеты
об ошибках. Для дистрибутивов исходных текстов скрипт mysqlbug
может быть найден в каталоге scripts. Для двоичных дистрибутивов
mysqlbug
находится в каталоге bin. Если Вы нашли ошибку
защиты в MySQL, Вы должны послать e-mail на
security@mysql.com.
Если Вы имеете любые предложения относительно добавлений или исправлений этого руководства, пожалуйста, пошлите их на docs@mysql.com.
MySQL представляет собой очень популярную систему управления базами данных с открытыми исходными текстами, разрабатываемую MySQL AB. MySQL AB является коммерческой компанией, строящей свой бизнес на сервисах, сосредоточенных на базе данных MySQL. Подробности в разделе "1.1.2 Что такое MySQL AB".
Официально MySQL произносится как "Май-Эс-Ку-Эль", а не как MY-SEQUEL.
MySQL AB является шведской компанией, которая владеет правами на исходные тексты сервера и марку MySQL. Она занимается разработкой, распространением и поддержкой пакета MySQL.
Авторы ищут партнеров, которые хотели бы поддерживать разработку MySQL так, чтобы они могли бы ускорить темп разработки. Если Вы заинтересованы в этом, напишите на e-mail partner@mysql.com!
MySQL AB имеет в настоящее время свыше 20 разработчиков ( http://www.mysql.com/development/team.html) в платежной ведомости, и это число возрастает быстро.
Основные источники дохода:
Авторы пакета хотят, чтобы MySQL всегда был:
MySQL AB и команда MySQL AB:
Началось все с попыток добавить к mSQL
драйвер низкого уровня
для связи с только что разработанным форматом таблиц (ISAM). Однако, после
вдумчивого тестирования, было установлено, что mSQL
недостаточно
быстр и гибок для этого дела. Это закончилось созданием нового интерфейса SQL
к нашей базе данных, но почти с тем же самым интерфейсом API, что и у
mSQL
. Этот API был выбран, чтобы облегчить перенос кодов для
других разработчиков программ.
Название возникло из сокращения (а вернее, слияния) слов My SQL, что на английском языке значит "мой SQL". Названию около десяти лет, оно прижилось еще в те времена, когда пакет не был коммерческой разработкой.
Следующий перечень описывает наиболее важные возможности MySQL:
FLOAT
, DOUBLE
, CHAR
,
VARCHAR
, TEXT
, BLOB
,
DATE
, TIME
, DATETIME
,
TIMESTAMP
, YEAR
, SET
и
ENUM
. Подробности приведены в разделе
"5 Типы столбцов". Там все рассказано.
SELECT
и WHERE
. Например:
mysql> SELECT CONCAT(first_name, " ", last_name) FROM tbl_name WHERE income/dependents > 10000 AND age > 30;
GROUP BY
и ORDER
BY
. Поддержка групповых функций (COUNT()
,
COUNT(DISTINCT ...)
, AVG()
, STD()
,
SUM()
, MAX()
и MIN()
).
LEFT OUTER JOIN
и RIGHT OUTER JOIN
с
синтаксисами ANSI SQL и ODBC.
CHAR
или VARCHAR
.
INSERT
, чтобы вставить подмножество столбцов таблицы. Те
столбцы, которым явно не заданы значения, будут автоматически установлены к
их значениям по умолчанию.
myisamchk
, очень быстрая утилита для проверки таблицы,
оптимизации и ремонта. Все функциональные возможности myisamchk
также доступны через интерфейс SQL.
DELETE
, INSERT
, REPLACE
и
UPDATE
возвращают число строк, которые были изменены
(обработаны). Можно взамен вернуть число согласованных строк, устанавливая
флажок при соединении с сервером.
ABS
представляет собой имеющее силу имя столбца. Единственное
ограничение: для обращения к функции никакие пробелы не позволяются между
именем функции и символом скобки (`('), который следует за ним.
--help
или -?
для выдачи справки о параметрах
запуска конкретной программы.
SHOW
может использоваться, чтобы
получить информацию относительно баз данных, таблиц и индексов. Команда
EXPLAIN
может использоваться, чтобы определить, как именно
оптимизатор решает запрос.Этот раздел сводится к вопросам о том, насколько можно доверять пакету, и сколько шансов, что он разнесет на кусочки важный проект, зависящий от него. Строго говоря, MySQL очень надежен.
Попробую разъяснить некоторые проблемы и ответить на некоторые из наиболее важных вопросов, которые, кажется, касаются многих. Этот раздел был собран из информации, собранной из списка рассылки (который является очень активным по части сообщений об ошибках и сбоях).
В TcX MySQL работал без любых проблем в проектах, начиная с середины 1996. Когда MySQL был выпущен на публику, авторы отметили, что имелись некоторые части непроверенного кода, которые были быстро найдены новыми пользователями, делавшими запросы иными способами, чем авторы. Каждый новый выпуск имел меньшее количество проблем мобильности, чем предыдущий (даже при том, что каждый имел много новых свойств).
Каждый выпуск MySQL был пригоден для использования, и имелись проблемы только, когда пользователи начинали использовать код из серых зон. Естественно, пользователи снаружи не видят то, чем являются серые зоны, этот раздел пытается указать, которые зоны в настоящее время известны. Описания имеют дело с MySQL Version 3.23. Все известные и сообщенные ошибки выправлены в последней версии, за исключением ошибок, перечисленных в отдельном разделе, которые являются проблемами, связанными с проектом. Подробности в разделе "1.2.7 Известные ошибки и проблемы".
MySQL написан на нескольких уровнях и различных независимых модулях. Эти модули перечислены ниже с индикацией относительно того, как хорошо проверен каждый из них (сравните с MS SQL Server!):
mysql
, mysqladmin
,
mysqlshow
, mysqldump
и mysqlimport
.
fcntl()
). В
этих случаях Вы должны выполнить MySQL с опцией --skip-locking
.
Проблемы, как известно, происходят на некоторых Linux-системах и на SunOS при
использовании файловых систем по NFS.
fcntl()
,
которое исправлено, используя опцию --skip-locking
для
mysqld
. Некоторые пользователи сообщали о проблемах тупика в
Version 0.5. LinuxThreads должен быть перетранслирован, если Вы планируете
использовать свыше 1000 параллельных подключений. Хотя можно выполнить много
подключений с LinuxThreads по умолчанию (однако, Вы никогда не будете иметь
более, чем 1021 подключение), заданный по умолчанию лимит стека в 2 МБ делает
прикладную программу ненадежной, и она способна свалиться в дамп ядра после
создания 1021 неактивных подключений.
SELECT
обычно выполняются в одном пакете.
LOAD DATA...
, INSERT...SELECT
:
стабильно.
ALTER TABLE
: стабильно.
mysqlaccess
: стабильно.
GRANT
: стабильно.
MySQL
. Они работают хорошо и
могут использоваться после начального тестирования.
MERGE
все еще не
оттестировано как следует. Другая часть кода MERGE
проверена.
MySQL AB обеспечивает поддержку по электронной почте для покупателей соответствующей услуги, но список рассылки MySQL обычно обеспечивает ответы на общие вопросы. Ошибки обычно исправляются сразу же с помощью патча, для серьезных ошибок почти всегда имеется новый выпуск.
MySQL Version 3.22 имеет лимит в 4G на размер таблицы. С новым кодом
MyISAM
в MySQL Version 3.23 максимальный размер таблицы увеличен
до 8 миллионов терабайт (2^63 байт).
Обратите внимание, однако, что операционные системы имеют их собственные ограничения размера файла. Имеются некоторые примеры:
Операционная система | Ограничение размера файла |
Linux-Intel 32 bit | 2G, 4G или больше, зависит от версии Linux |
Linux-Alpha | 8T (?) |
Solaris 2.5.1 | 2G (возможно, до 4G с патчем) |
Solaris 2.6 | 4G |
Solaris 2.7 Intel | 4G |
Solaris 2.7 ULTRA-SPARC | 8T (?) |
В Linux 2.2 Вы можете получать таблицы больше, чем 2G, используя заплату LFS для файловой системы ext2. В Linux 2.4 существует также заплата для ReiserFS, чтобы получить поддержку для больших файлов.
Это означает, что размер таблицы для MySQL обычно ограничивается операционной системой, а не самим пакетом.
По умолчанию таблицы MySQL имеют максимальный размер около 4G. Вы можете
проверять максимальный размер таблицы для каждой конкретной таблицы с помощью
команды SHOW TABLE STATUS
или утилитой myisamchk -dv
table_name
. Подробности приведены в разделе
"4.10 Синтаксис вызова SHOW
".
Если Вы нуждаетесь в таблицах, больших, чем 4G (и Ваша операционная
система поддерживает это), Вы должны установить параметры
AVG_ROW_LENGTH
и MAX_ROWS
, когда Вы создаете Вашу
таблицу. Подробности в разделе "7.3
Синтаксис CREATE TABLE
". Вы можете установить их и позже с
помощью ALTER TABLE
. Подробности в разделе
"7.4 Синтаксис ALTER TABLE
".
Если Ваша большая таблица нужна только для чтения, Вы могли бы
использовать myisampack
, чтобы объединить и сжать много таблиц в
одну. Утилита myisampack
обычно сжимает таблицу по крайней мере
на 50%, так что Вы можете иметь намного большие таблицы.
Вы можете обойти ограничения размера файла операционной системы для
файлов данных MyISAM
, используя опцию RAID
.
Подробности в разделе "7.3 Синтаксис
CREATE TABLE
".
Другое решение может быть реализовано с помощью библиотеки MERGE, которая позволяет Вам обрабатывать совокупность идентичных таблиц как одну.
MySQL непосредственно не имеет никаких трудностей с проблемой 2000 (Y2K):
2069
. Все годы с 2 цифрами расценены в интервале от
1970
до 2069
, это означает, что, если Вы сохраняете
01
в столбце типа year
, MySQL обрабатывает это как
2001
.
YEAR
может
сохранять годы 0
и в интервале от 1901
до
2155
в 1 байте, а также отображать их, используя 2 или 4 цифры.
Вы можете сталкиваться с проблемами в прикладных программах, которые
используют MySQL, но сами несовместимы с проблемой Y2K. Например, много
старых прикладных программ сохраняют или управляют значениями лет,
используя числа с 2 цифрами (которые являются неоднозначными). Эта проблема
также может быть составлена прикладными программами, которые используют
00
или 99
как значения для индикатора "пропустить".
В свое время пришлось столкнуться с программой, которая помечала удаленные
записи, выставляя им год 00
...
К сожалению, эти проблемы могут быть трудными в исправлении потому, что различные прикладные программы могут быть написаны различными программистами, каждый из которых может использовать различный набор соглашений и обрабатывающих даты функций.
Имеется простой пример, иллюстрирующий, что MySQL не имеет любых проблем с датами до года 2030:
mysql> DROP TABLE IF EXISTS y2k; Query OK, 0 rows affected (0.01 sec) mysql> CREATE TABLE y2k (date date, date_time datetime, time_stamp timestamp); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO y2k VALUES -> ("1998-12-31","1998-12-31 23:59:59",19981231235959), -> ("1999-01-01","1999-01-01 00:00:00",19990101000000), -> ("1999-09-09","1999-09-09 23:59:59",19990909235959), -> ("2000-01-01","2000-01-01 00:00:00",20000101000000), -> ("2000-02-28","2000-02-28 00:00:00",20000228000000), -> ("2000-02-29","2000-02-29 00:00:00",20000229000000), -> ("2000-03-01","2000-03-01 00:00:00",20000301000000), -> ("2000-12-31","2000-12-31 23:59:59",20001231235959), -> ("2001-01-01","2001-01-01 00:00:00",20010101000000), -> ("2004-12-31","2004-12-31 23:59:59",20041231235959), -> ("2005-01-01","2005-01-01 00:00:00",20050101000000), -> ("2030-01-01","2030-01-01 00:00:00",20300101000000), -> ("2050-01-01","2050-01-01 00:00:00",20500101000000); Query OK, 13 rows affected (0.01 sec) Records: 13 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM y2k; +------------+---------------------+----------------+ | date | date_time | time_stamp | +------------+---------------------+----------------+ | 1998-12-31 | 1998-12-31 23:59:59 | 19981231235959 | | 1999-01-01 | 1999-01-01 00:00:00 | 19990101000000 | | 1999-09-09 | 1999-09-09 23:59:59 | 19990909235959 | | 2000-01-01 | 2000-01-01 00:00:00 | 20000101000000 | | 2000-02-28 | 2000-02-28 00:00:00 | 20000228000000 | | 2000-02-29 | 2000-02-29 00:00:00 | 20000229000000 | | 2000-03-01 | 2000-03-01 00:00:00 | 20000301000000 | | 2000-12-31 | 2000-12-31 23:59:59 | 20001231235959 | | 2001-01-01 | 2001-01-01 00:00:00 | 20010101000000 | | 2004-12-31 | 2004-12-31 23:59:59 | 20041231235959 | | 2005-01-01 | 2005-01-01 00:00:00 | 20050101000000 | | 2030-01-01 | 2030-01-01 00:00:00 | 20300101000000 | | 2050-01-01 | 2050-01-01 00:00:00 | 00000000000000 | +------------+---------------------+----------------+ 13 rows in set (0.00 sec)
Это показывает, что типы DATE
и DATETIME
не
будут давать никаких проблем с будущими датами (они легко обрабатывают даты
вообще до 9999 года).
Тип TIMESTAMP
, который используется, чтобы сохранить текущее
(актуальное) время, имеет диапазон только до 2030-01-01
.
TIMESTAMP
имеет диапазон от 1970
до
2030
на 32-разрядных машинах (значение со знаком). На
64-разрядных машинах это обрабатывает времена до 2106
года
(значение без знака).
Даже при том, что MySQL Y2K-совместим, Вы отвечаете за то, чтобы обеспечить однозначный ввод. Подробности в разделе "5.2.1 Проблема Y2K и типы Date", там описаны правила MySQL для ввода дат с неоднозначными данными (данные, содержащие значения года с 2 цифрами).
Этот раздел описывает, как MySQL соответствует стандартам ANSI SQL. MySQL имеет много расширений для них, здесь Вы выясните, что они из себя представляют, и как использовать их. Вы также найдете информацию относительно функциональных возможностей, отсутствующих в MySQL, и как обойти проблемы.
MySQL включает некоторые расширения, которые Вы, вероятно, не будете
находить в других базах данных SQL. Предупреждаю, что, если Вы используете
их, Ваш код не будет переносимым на другие SQL-серверы. В некоторых случаях
Вы можете писать код, который включает MySQL-расширения, но все же является
переносимым за счет комментариев формы /*! ... */
. В этом случае
MySQL анализирует и выполнит код внутри комментария, но другие SQL-серверы
игнорируют расширения. Например:
SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...
Если Вы добавляете номер версии после '!'
, синтаксис будет
выполнен только, если версия MySQL равна или больше, чем этот номер версии:
CREATE /*!32302 TEMPORARY */ TABLE (a int);
Это означает, что, если Вы имеете Version 3.23.02 или более новую, MySQL
использует ключевое слово TEMPORARY
.
MySQL-расширения перечислены ниже:
MEDIUMINT
, SET
,
ENUM
и разные типы BLOB
и TEXT
.
AUTO_INCREMENT
, BINARY
,
NULL
, UNSIGNED
и ZEROFILL
.
BINARY
или использовать ключевое слово BINARY
,
которое заставляет сравнения быть выполненными согласно порядку ASCII,
используемому на сервере MySQL.
db_name.tbl_name
. Некоторые
SQL-серверы обеспечивают те же самые функциональные возможности, но называют
это User space
. MySQL не поддерживает пространство таблиц как
in: create table ralph.my_table...IN my_tablespace
.
LIKE
позволяется на числовых столбцах.
INTO OUTFILE
и STRAIGHT_JOIN
допустимо в инструкции SELECT
.
SQL_SMALL_RESULT
в инструкции SELECT
.
EXPLAIN SELECT
, чтобы получить описание
того, как таблицы соединены.
INDEX
или KEY
в инструкции
CREATE TABLE
.
TEMPORARY
или IF NOT EXISTS
с
CREATE TABLE
.
COUNT(DISTINCT list)
, где 'list' включает больше,
чем один элемент.
CHANGE col_name
, DROP col_name
или
DROP INDEX
, IGNORE
или RENAME
в вызове
команды ALTER TABLE
.
RENAME TABLE
.
ADD
, ALTER
,
DROP
или CHANGE
в одном
вызове ALTER TABLE
.
DROP TABLE
с ключевым словом IF EXISTS
.
DROP
TABLE
.
LIMIT
в инструкции DELETE
.
DELAYED
в инструкциях INSERT
и
REPLACE
.
LOW_PRIORITY
в инструкциях INSERT
,
REPLACE
, DELETE
и UPDATE
.
LOAD DATA
INFILE
. Во многих случаях этот синтаксис совместим с Oracle
LOAD DATA INFILE
.
ANALYZE TABLE
, CHECK TABLE
,
OPTIMIZE TABLE
и REPAIR TABLE
.
SHOW
.
SET OPTION
.
GROUP BY
.
Это дает лучшую эффективность для некоторых очень специфических, но
совершенно нормальных запросов.
ASC
и DESC
с вызовом
GROUP BY
. Очень полезно.
||
и &&
в качестве
OR и AND, как в языке программирования C. В MySQL ||
и
OR
синонимы, так же как &&
и AND
.
Из-за этого хорошего синтаксиса MySQL не поддерживает оператор ANSI SQL
||
для конкатенации строк, используйте вместо него
CONCAT()
. Поскольку CONCAT()
берет любое число
параметров, просто преобразовать использование ||
в MySQL.
CREATE DATABASE
или DROP DATABASE
.
%
является синонимом для MOD()
. То есть N%M
равносильно MOD(N,M)
. %
поддержан для
C-программистов и для совместимости с PostgreSQL.
=
, <>
, <=
,
<
, >=
,>
,
<<
, >>
, <=>
,
AND
, OR
или LIKE
могут использоваться
в сравнениях столбца слева от FROM
в инструкции
SELECT
. Например, так:
mysql> SELECT col1=1 AND col2=2 FROM tbl_name;
LAST_INSERT_ID()
.
REGEXP
и
NOT REGEXP
в операторах.
CONCAT()
или CHAR()
с одним
параметром или больше, чем с двумя параметрами. В MySQL эти функции могут
брать любое число параметров.
BIT_COUNT()
, CASE
, ELT()
,
FROM_DAYS()
, FORMAT()
, IF()
,
PASSWORD()
, ENCRYPT()
, md5()
,
ENCODE()
, DECODE()
, PERIOD_ADD()
,
PERIOD_DIFF()
, TO_DAYS()
и WEEKDAY()
.
TRIM()
для подрезания подстрок. ANSI SQL
поддерживает удаление только одиночных символов.
GROUP BY
можно использовать STD()
,
BIT_OR()
и BIT_AND()
.
REPLACE
вместо связки
DELETE
+INSERT
.
FLUSH flush_option
.
:=
:
SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg FROM test_table; SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
Авторы пробуют заставить MySQL следовать стандартам ANSI SQL и ODBC SQL, но в некоторых случаях MySQL обрабатывает некоторые дела по-другому:
--
является комментарием, только если сопровождается
незаполненным пространством. Подробности чуть ниже.
VARCHAR
конечные пробелы будут удалены, когда
значение сохранено. Подробности в разделе "1.2.7
Известные ошибки и проблемы".
CHAR
тихо меняются на столбцы
типа VARCHAR
.
REVOKE
, чтобы отменить все
привилегии для таблицы.
NULL AND FALSE
вернет NULL
вместо
FALSE
, чтобы не возиться долго с оценкой выражений.Если Вы запустили mysqld
с опцией --ansi
,
поведение MySQL изменится следующим образом:
||
является конкатенацией строк, а не OR
.
REAL
превратится в синоним для FLOAT
вместо
синонима для DOUBLE
.
SERIALIZABLE
. Подробности в разделе
"9.2.3 Синтаксис
SET TRANSACTION
".Этого также можно достичь опцией --sql-mode=REAL_AS_FLOAT,
PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,SERIALIZE,ONLY_FULL_GROUP_BY
.
Следующие функциональные возможности отсутствуют в текущей версии MySQL. Есть список, указывающий, когда новые расширения могут быть добавлены к MySQL (с их приоритетами), его можно посмотреть в Интернете по адресу http://www.mysql.com/documentation/manual.php?section=TODO.
MySQL в настоящее время поддерживает sub-selects только в виде
INSERT ... SELECT ...
и REPLACE ... SELECT ...
.
Вы можете, однако, использовать функцию IN()
в других контекстах.
Во многих случаях Вы можете переписать запрос без sub-select:
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
Это может быть переделано так:
SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;
Запросы:
SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2); SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2 where table1.id=table2.id);
Могут быть переделаны так:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id IS NULL
Для более сложных подзапросов Вы можете часто создавать временные таблицы,
чтобы сохранить подзапрос. В некоторых случаях эта опция не будет работать.
Наиболее часто это происходит с инструкциями DELETE
, для которых
стандарт SQL не поддерживает объединения (за исключением sub-selects). Для
этой ситуации имеются два решения, доступные пока подзапросы не поддержаны.
Первое должно использовать процедурный язык программирования (типа Perl
или PHP) чтобы представить на рассмотрение такой запрос SELECT
,
чтобы получить первичные ключи для записей, которые будут удалены, и затем
использовать эти значения, чтобы создать инструкцию DELETE
(DELETE FROM ... WHERE ... IN (key1, key2, ...)
).
Второе решение должно использовать интерактивный SQL для автопостроения
набора инструкций DELETE
при использовании MySQL-расширения
CONCAT()
(вместо стандартного оператора ||
):
SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', tab1.pkid, ';') FROM tab1, tab2 WHERE tab1.col1 = tab2.col2;
Вы можете помещать этот запрос в файл скрипта и переназначать ввод на
интерпретатор командных строк mysql
, отправив вывод на его
вторую копию клиента:
prompt> mysql --skip-column-names mydb < myscript.sql|mysql mydb
MySQL 4.0 поддерживает многотабличное удаление, которое может использоваться, чтобы эффективно удалить строки, основанные на информации из одной таблицы (или даже из многих таблиц) в то же самое время.
SELECT INTO TABLE
MySQL не поддерживает Oracle SQL-расширение SELECT ... INTO
TABLE ...
. MySQL вместо него поддерживает синтаксис ANSI SQL
INSERT INTO ... SELECT ...
, который является в основном той же
самой функциональностью. Подробности в разделе
"8.3.1 Синтаксис INSERT ... SELECT
".
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;
Альтернативно, Вы можете использовать SELECT INTO OUTFILE...
или CREATE TABLE ... SELECT
, чтобы решить Вашу проблему.
Поскольку MySQL в настоящее время поддерживает транзакции, следующее
обсуждение имеет силу, только если Вы используете не транзакционно-безопасные
типы таблицы. Подробности в разделе "9.2.1
Синтаксис BEGIN/COMMIT/ROLLBACK
".
Часто спрашивают, почему MySQL не транзационная база данных?
MySQL сделал сознательное решение поддерживать другую парадигму для целостности данных: атомные операции. Дело в том, что атомные операции предлагают равную или даже лучшую целостность с намного лучшей эффективностью. Однако, авторы пакета тем не менее оценивают и понимают транзакционную парадигму базы данных и планируют в следующих версиях представить транзакционно-безопасные таблицы. Пользователям будет предоставлена возможность решить, нуждаются ли они в быстродействии атомных операций, или они должны использовать свойства транзакций в своих программах.
Давайте разберемся в том, как MySQL поддержает строгую целостность, и сравним эти свойства с транзакциями.
Перво-наперво в транзакционной системе, если Ваши программы в критических ситуациях вызывают rollback вместо commit, транзакционная схема удобней. Кроме того, транзакции гарантируют, что незаконченные модификации или разрушительные действия не будут применены к базе данных немедленно, сервер дает возможность сделать автоматическую обратную перемотку, и Ваша база данных будет сохранена.
MySQL почти во всех случаях позволяет Вам обойти проблемы включением простых проверок перед модификациями и запуском простых скриптов, которые проверяют целостность базы данных, а также автоматически проводят ремонт. Обратите внимание, что только используя файл регистрации MySQL или даже добавляя один дополнительный файл регистрации, обычно можно востанавливать таблицы без потери целостности данных.
Кроме того, фатальные модификации в транзакционной схеме могут быть
переделаны так, чтобы стать атомными. Фактически все проблемы целостности,
которые решают транзакции, могут быть выполнены с помощью LOCK
TABLES
или атомными модификациями, гарантируя, что Вы никогда не
получите автоматическое аварийное прекращение работы базы данных, что
является общей проблемой для транзакционных баз данных.
Далеко не все транзакции могут предотвращать потерю данных, если сервер рушится. В таких случаях даже транзакционная система может терять данные. Никакая система не 100%-но безопасна, речь идет лишь о минимизации потерь. Даже Oracle, как сообщают, иногда теряет данные в таких ситуациях, хоть и считается самой безопасной из транзакционных баз данных.
Чтобы обеспечить безопасность в MySQL, Вы должны только иметь копии и регистрацию модификаций. С этим Вы можете восстановить фактически любое повреждение базы данных.
Транзакционная парадигма имеет выгоды и недостатки. Много пользователей и
разработчиков прикладных программ зависят от легкости, с которой они могут
обойти проблемы, где аварийное прекращение работы появляется или необходимо,
и им, вероятно, придется делать немного больше работы с MySQL, чтобы думать
по-другому или писать больше. Если Вы плохо знакомы с атомной парадигмой
операций или более знакомы с транзакциями, не считайте, что MySQL не знаком с
этими проблемами. Надежность и целостность у авторов этого пакета стоят на
первом месте! Недавние оценки указывают, что имеется больше, чем 1000000
серверов mysqld
, многие из которых находятся в промышленных
средах. Очень редко можно услышать от пользователей, что они потеряли данные,
и почти во всех случаях виноваты были сами пользователи. Это самое лучшее
доказательство стабильности и надежности MySQL.
Наконец, в ситуациях, где целостность имеет самую высокую важность,
текущие свойства MySQL учитывают уровень транзакции или лучшую надежность и
целостность. Если Вы блокируете таблицы с помощью LOCK TABLES
,
все модификации остановятся, пока любые проверки целостности не будут
сделаны. Если Вы только получаете блокировку чтения (в противоположность
блокировке записи), то чтение и вставки продолжают работать. Новые
вставленные записи не будут замечены клиентами, имеющими блокировку
READ
, пока они не освободят их блокировки чтения. С помощью
INSERT DELAYED
Вы можете поместить вставки в локальную очередь,
где они останутся до тех пор, пока блокировки не будут освобождены. Таким
образом, сервер не будет иметь пользователя, который ждет завершения вставки.
Подробности в разделе "8.4 Синтаксис
INSERT DELAYED
".
"Атомная" означает, что Вы можете убедиться в том, что в то время как
каждая специфическая модификация выполняется, никакой другой пользователь не
может сталкиваться с ней, и никакой автоматической обратной перемотки не
будет никогда (хотя это может случаться на транзакционных системах, если Вы
не очень осторожны). MySQL также гарантирует, что не будет иметься лишних
чтений. Вы можете найти пример того, как писать атомные модификации в разделе
"1.2.6 Как справиться без
COMMIT
/ROLLBACK
".
Использование атомной парадигмы позволяет применять много оптимизаций быстродействия, которые иначе не будут возможны. К тому же, при грамотном подходе такая схема ускорит работу в 3-5 раз по сравнению с лучшими транзакционными базами данных при той же надежности.
Для тех случаев, где безопасность более важна, чем быстродействие, я
советую применять транзакционные таблицы типов BDB
или
InnoDB
для всех критических данных.
Одно заключительное примечание: в настоящее время авторы пакета работают над безопасной схемой репликации, которая должна быть лучше, чем любая известная на сегодняшний день поддержка репликации. Эта система будет работать наиболее надежно при атомных операциях, а не транзакциях.
Хранимая процедура представляет собой набор команд SQL, который может компилироваться и храниться на сервере. Как только это было выполнено, клиент не должен хранить весь запрос, а может обратиться к сохраненной процедуре. Это обеспечивает лучшую эффективность потому, что запрос должен анализироваться только однажды, и меньшее количество информации должно быть послано между клиентом и сервером. Вы можете также поднимать концептуальный уровень при наличии библиотек функций.
Триггер представляет собой сохраненную процедуру, которая вызывается, когда специфическое событие происходит. Например, Вы можете устанавливать сохраненную процедуру, которая будет вызвана каждый раз, когда запись удалена из таблицы transaction. Эта процедура автоматически удаляет соответствующего заказчика из таблицы customer, когда все его транзакции удалены.
Запланированный язык модификаций будет способен обработать сохраненные процедуры, но без триггеров. Триггеры обычно замедляют все, даже запросы, к которым не имеют отношения.
Обратите внимание, что внешние ключи в SQL не используются, чтобы
соединить таблицы, но используются обычно для проверки справочной
целостности. Если Вы хотите получить результат из нескольких таблиц командой
SELECT
, Вы делаете это, соединяя таблицы так:
SELECT * from table1,table2 where table1.id = table2.id;
Подробности есть в разделах
"8.1.1 Синтаксис JOIN
" и
"2.5.6
Использование внешних ключей".
Синтаксис FOREIGN KEY
в MySQL существует только для
совместимости с другими версиями SQL-команды CREATE TABLE
, это
не делает ничего. Синтаксис FOREIGN KEY
без ON DELETE ...
обычно используется для документационных целей. Некоторые прикладные
программы стандарта ODBC могут использовать это, чтобы произвести
автоматические предложения WHERE
, но это обычно просто, чтобы
перекрыть. FOREIGN KEY
иногда используется как проверка
ограничения, но эта проверка практически не нужна, если строки вставлены в
таблицы в правильном порядке. MySQL поддерживает эти предложения только
потому, что некоторые прикладные программы требуют, чтобы они существовали
(независимо от того, работают они или нет).
В MySQL Вы можете обойти проблему неработающей конструкции
ON DELETE ...
добавляя соответствующую инструкцию
DELETE
к прикладной программе, когда Вы удаляете записи из
таблицы, которая имеет внешний ключ. Практически это иногда быстрее и намного
более переносимо, чем использование внешних ключей в таблице.
В ближайшем будущем мы расширим реализацию FOREIGN KEY
так,
чтобы по крайней мере информация была сохранена в файле спецификации таблицы
и могла быть получена mysqldump
и ODBC. На более поздней стадии
мы выполним ограничения внешних ключей для прикладной программы, которая не
может легко быть перекодирована, чтобы избежать их.
Много ученых по теории базы данных и программистов чувствуют, что справочная целостность должна быть предписана внутри сервера базы данных. Действительно, во многих случаях этот подход очень полезен. Однако, в разговоре со многими пользователями баз данных авторы наблюдали, что внешние ключи часто неправильно используются, что может вызывать серьезные проблемы. Даже когда все используется правильно, это не волшебное решение для проблемы справочной целостности, хотя это делает все проще в некоторых случаях.
Из-за вышеупомянутых наблюдений авторы не назначали реализации внешних ключей высокий приоритет. Однако, в последние годы ядро пользователей расширилось, и теперь авторы пакета имеют много пользователей, кто хотел бы иметь предписанную поддержку справочной целостности внутри MySQL. Так что в ближайшем будущем внешние ключи все-таки будут реализованы.
Некоторые преимущества применения внешних ключей:
Противопоказания:
MySQL не поддерживает views, но это планируется исправить примерно к 4.1.
Views обычно полезны для разрешения пользователям обращаться к набору отношений как к одной таблице (в режиме только для чтения). Многие базы данных SQL не позволяют модифицировать любые строки в таком представлении: Вы должны делать все модификации в отдельных таблицах.
MySQL обычно используется в прикладных программах и на web-системах, где автор прикладной программы имеет полное управление над применением базы данных. По этой причине views не сочтены очень важными.
Чтобы ограничить доступ к столбцам в MySQL views тоже не требуются: MySQL имеет очень сложную систему предоставления привилегий. Подробности в разделе "10 Общие проблемы защиты и система привилегий доступа MySQL".
Некоторые базы данных SQL применяют -- как начало
комментария. MySQL имеет # как символ начала комментария, даже
если инструмент командной строки mysql
удаляет все строки,
начинающиеся с --. Вы можете также использовать стиль
комментариев языка C (/* это комментарий */
) в MySQL.
MySQL Version 3.23.3 и выше поддерживает стиль комментариев
--, только если комментарий сопровождается пробелом. Это потому,
что стиль комментария вызвал много проблем с автоматически сгенерированными
запросами SQL, которые использовали нечто вроде следующего кода, где мы
автоматически вставляем значение payment вместо !payment!
:
UPDATE tbl_name SET credit=credit-!payment!
Как Вы думаете, что случится, когда значение payment
отрицательное? А вот что. Поскольку 1--1
допустимо в SQL, пакет
думает, что начался комментарий типа --. Вряд ли это
входит в Ваши планы...
В MySQL Version 3.23 Вы можете использовать:
1-- Это был комментарий
Следующее обсуждение касается Вас, только если Вы управляете MySQL Version 3.23 или ранее:
Если Вы имеете программу SQL в текстовом файле, который содержит комментарии --, Вы должны использовать:
shell> replace " --" " #" < text-file-with-funny-comments.sql \ | mysql database
Вместо обычного решения:
shell> mysql database < text-file-with-funny-comments.sql
Вы можете также редактировать командный файл, чтобы сменить комментарии -- на #:
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Замените их обратно этой командой:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
Entry level SQL92. ODBC levels 0-2.
COMMIT
/ROLLBACK
Следующее обычно применяется только для таблиц ISAM
,
MyISAM
и HEAP
. Если Вы используете только
транзакционно-безопасные таблицы (BDB
или InnoDB
) в
модификации, Вы можете также делать COMMIT
и
ROLLBACK
в MySQL. Подробности в разделе
"9.2.1 Синтаксис
BEGIN/COMMIT/ROLLBACK
".
Проблема с эффективной обработкой
COMMIT
-ROLLBACK
с вышеупомянутыми типами таблиц
требует полностью иного размещения таблицы, чем используемое MySQL сегодня.
Тип таблицы также нуждался бы в дополнительных потоках, которые вели бы
автоматические очистки на таблицах, да и использование дисков было бы намного
выше. Это сделало бы эти типы таблицы приблизительно в 2-4 медленнее, чем
они есть сейчас.
Текущей проблемой является ROLLBACK
. Без
ROLLBACK
Вы можете делать любой вид COMMIT
с
помощью LOCK TABLES
. Для поддержки ROLLBACK
с
вышеупомянутыми типами таблицы MySQL должен быть изменен так, чтобы сохранять
все старые записи, которые модифицировались, и иметь возможность быстро
вернуться к отправной точке, если была выдана команда ROLLBACK
.
Для простых случаев это довольно просто (можно приспособить сюда
isamlog
), но будет намного трудней выполнить
ROLLBACK
для ALTER/DROP/CREATE TABLE
.
Чтобы избежать использования ROLLBACK
, Вы можете использовать
следующую стратегию действий:
LOCK TABLES ...
, чтобы блокировать все
таблицы, к которым Вы хотите обращаться.
UNLOCK TABLES
, чтобы снять блокировки.Это обычно намного более быстрый метод, чем использование транзакций с
возможностью ROLLBACK
, хотя и не всегда. Единственная ситуация,
которую это решение не обрабатывает, состоит в том, что кто-то уничтожает
поток в середине модификации. В этом случае все блокировки будут сняты, но
некоторые из модификаций, возможно, не будут выполнены.
Вы можете также использовать функции, чтобы модифицировать записи в одиночной операции. Вы можете получать очень эффективную прикладную программу, применяя следующие методы:
Например, когда мы делаем модификации некоторой информации заказчика, мы
модифицируем только данные заказчика, которые изменились, и проверяем, что ни
один из измененных данных или других данных, которые зависят от измененных
данных, не изменился по сравнению с первоначальной строкой. Тест для
измененных данных выполнен с предложением WHERE
в инструкции
UPDATE
. Если запись не модифицировалась, мы даем пользователю
сообщение о том, что некоторые из данных, которые Вы изменили, были изменены
другим пользователем. Затем мы показываем старую строку против новой строки в
окне, так что пользователь может решать, которую версию записи заказчика он
должен будет использовать.
Это дает нам нечто, что является подобным блокировке столбца, но
фактически это даже лучше потому, что мы модифицируем только некоторые из
столбцов, используя значения, которые вычислены относительно их текущих
значений. Это означает, что типичные инструкции UPDATE
выглядят
примерно таким образом:
UPDATE tablename SET pay_back=pay_back+'relative change'; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_he_owes_us=money_he_owes_us+'new_money' WHERE customer_id=id AND address='old address' AND phone='old phone';
Как Вы можете видеть, это очень эффективно и работает, даже если другой
пользователь изменил значения столбцов pay_back
или
money_he_owes_us
.
Во многих случаях пользователи
хотели использовать ROLLBACK
и/или LOCK TABLES
с
целью управления уникальными идентификаторами для некоторых таблиц. Это может
быть обработано намного более эффективно, используя столбец
AUTO_INCREMENT
и функцию SQL LAST_INSERT_ID()
или
функцию C API mysql_insert_id()
.
В MySQL AB авторы пакета никогда не имели никакой потребности в блокировке уровня строки потому, что всегда могли ее обойти. Некоторые случаи и в самом деле нуждаются в блокировке строки, но они очень немногочисленны. Если Вы хотите иметь блокировку уровня строки, Вы можете использовать столбец флажка в таблице и делать нечто вроде:
UPDATE tbl_name SET row_flag=1 WHERE id=ID;
MySQL вернет для числа обработанных строк, если строка была найдена, и
row_flag
не был 1 в первоначальной строке.
Перечисленные ниже проблемы известны авторам пакета, и их устранение имеет очень высокий приоритет.
ANALYZE TABLE
на таблицах BDB может в некоторых случаях
делать таблицу непригодной, пока Вы не перезапустите mysqld
.
Когда это выполнено, Вы будете видеть ошибки подобные следующим в файле
регистрации ошибок MySQL:
001207 22:07:56 bdb: log_flush: LSN past current end-of-log
ALTER TABLE
на таблице BDB
, на
которой Вы управляете незавершенными многооператорными транзакциями.
Транзакция будет, вероятно, игнорироваться.
ANALYZE TABLE
, OPTIMIZE TABLE
и REPAIR
TABLE
могут вызывать проблемы на таблицах, для которых Вы используете
вызов INSERT DELAYED
.
LOCK TABLE ...
и FLUSH TABLES ...
еще не гарантирует, что не имеется наполовину выполненной транзакции.
mysql
на этой базе данных, если Вы не используете опцию
-A
или применяете rehash
. Это особенно важно, когда
Вы имеете большой кэш таблицы.
LOAD DATA
INFILE
и выравнивать символы признака конца строки, которые сами
занимают больше, чем 1 символ.Следующие проблемы известны и будут устранены в назначенное время:
MATCH
работает только с инструкциями
SELECT
.
SET CHARACTER SET
не могут быть применены
транслируемые символы в базе данных, таблице и столбцах.
DELETE FROM merge_table
, используемый без
WHERE
, только очистит отображение для таблицы, не удаляя ничего
в самих отображенных таблицах.
BLOB
не могут надежно использоваться в GROUP
BY
, ORDER BY
или DISTINCT
. Только первые
max_sort_length
байт (по умолчанию 1024) используются при
сравнении BLOB
в этих случаях. Это может быть изменено с помощью
опции -O max_sort_length
при запуске mysqld
. Обход
для большинства случаев должен использовать подстроку: SELECT DISTINCT
LEFT(blob,2048) FROM tbl_name
.
BIGINT
или DOUBLE
(оба обычно длиной в 64 бита). Это зависит от функции, которую обрабатывает
пакет. Общее правило: битовые функции выполнены с точностью
BIGINT
, IF
и ELT()
с
BIGINT
или DOUBLE
, а все прочие с
DOUBLE
. Нужно пробовать избегать использовать большие длинные
значения без знака (9223372036854775807)!
BLOB
и TEXT
,
автоматически удаляют все конечные пробелы, когда сохраняются. Для типа
CHAR
это разрешено и может быть расценено как свойство согласно
ANSI SQL92. Ошибка в том, что в MySQL столбцы VARCHAR
обрабатываются тем же самым путем.
ENUM
и
SET
для каждой таблицы.
safe_mysqld
переназначает все сообщения mysqld
в файл регистрации mysqld
. Одна проблема с этим состоит в том,
что, если Вы выполняете mysqladmin refresh
, чтобы закрыть и
вновь открыть файл регистрации, stdout
и stderr
все еще переназначаются к старому файлу регистрации. Если Вы используете
опцию --log
, Вы должны редактировать safe_mysqld
,
чтобы регистрировать данные в файле 'hostname'.err вместо
'hostname'.log, чтобы у Вас не было крупных проблем с запуском и
работой с mysqladmin refresh
.
UPDATE
столбцы модифицируются слева направо.
Если Вы обращаетесь к модифицируемому столбцу, Вы получите модифицируемое
значение вместо первоначального значения. Например:
mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;Это модифицирует
KEY
с 2
вместо 1
.
select * from temporary_table, temporary_table as t2;
RENAME
не работает с таблицами TEMPORARY
.
DISTINCT
по-разному, если Вы
используете скрытые столбцы в объединении или нет. В объединении скрытые
столбцы рассчитаны как часть результата (даже если они не показаны) в то
время, как в нормальном запросе они не участвуют в сравнении
DISTINCT
. Мы, вероятно, изменим это в будущем, чтобы никогда не
сравнить скрытые столбцы при выполнении DISTINCT
. Например:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid=9 ORDER BY id DESC;и
SELECT DISTINCT band_downloads.mp3id, FROM band_downloads,band_mp3 WHERE band_downloads.userid=9 AND band_mp3.id=band_downloads.mp3id ORDER BY band_downloads.id DESC;Во втором случае Вы можете в MySQL 3.23.x получить две идентичных строки в наборе результатов (потому, что скрытый столбец 'id' может отличаться). Обратите внимание, что это случается только для запросов, где Вы не имеете ORDER BY в результате, что вообще-то неправильно с точки зрения стандарта ANSI SQL.
rollback
), некоторые вещи ведут себя немного иначе, чем в других
серверах SQL. Это только должно гарантировать, что MySQL никогда не должен
делать обратную перемотку для команд SQL. Это может быть иногда немного
неуклюже, поскольку значения столбца должны проверяться прикладной
программой, но это фактически даст Вам хорошее увеличение быстродействия,
поскольку это позволяет MySQL делать некоторые оптимизации, которые иначе
были бы невозможны или очень трудны. Если Вы устанавливаете столбец к
неправильному значению, MySQL будет, вместо того, чтобы делать обратную
перемотку, сохранять самое лучшее возможное
значение в столбце.
NULL
, который не берет
значения NULL
, MySQL сохранит 0 или ''
(пустую
строку). Это поведение может, однако, быть изменено с опцией компиляции
-DDONT_USE_DEFAULT_FIELDS.
DATE
и DATETIME
. Например, 2000-02-31 или
2000-02-00. Если дата полностью неправильна, MySQL сохранит в столбце
специальное значение даты 0000-00-00.
enum
к неподдерживаемому значению,
это будет установлено к значению ошибки 'empty string' с числовым значением 0.
PROCEDURE
на запросе, который возвращает
пустой набор, в некоторых случаях PROCEDURE
не будет
трансформировать столбцы.
MERGE
не проверяет, имеют ли основные
таблицы совместимые типы.
NaN
,
-Inf
и Inf
в double. Использование их вызовет
проблемы при попытке экспортировать и импортировать данные. Вы должны как
промежуточное решение изменить NaN
на NULL
(если
возможно), а -Inf
и Inf
соответственно к
минимальному и максимальному возможным значениям double
.
LIMIT
на отрицательных числах превращается в очень большие
положительные числа, что ошибочно.
ALTER TABLE
, чтобы сначала добавить
индекс UNIQUE
к таблице, используемой в таблице типа
MERGE
, и затем использовать ALTER TABLE
, чтобы
добавить нормальный индекс уже на таблице MERGE
, порядок ключей
будет иным для таблиц, если имелся старый не уникальный ключ в таблице. Это
потому, что ALTER TABLE
помещает ключи UNIQUE
перед
нормальными ключами, чтобы обнаружить двойные ключи как можно раньше.Следующее представляет известные ошибки в более ранних версиях MySQL:
DROP
TABLE
на таблице, которая является одной среди многих таблиц, которые
блокированы с помощью LOCK TABLES
.
LOCK table
с WRITE
FLUSH TABLES
UPDATE
, который модифицировал ключ
с помощью WHERE
на том же самом ключе, возможно, потерпел
неудачу потому, что та же самая строка использовалась для поиска:
UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;Обойти это можно так:
mysql> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;Это будет работать потому, что MySQL не будет использовать индекс на выражениях в предложении
WHERE
.
Для изучения ошибок, специфических для конкретной платформы, изучите разделы по компиляции и портированию.
Эта глава обеспечивает введение в MySQL, показывая, как использовать
клиент mysql
, чтобы создавать и использовать простую базу
данных. mysql
(иногда упоминаемый как "terminal monitor" или
"monitor") представляет собой интерактивную программу, которая позволяет Вам
соединяться с сервером MySQL, выполнять запросы и просматривать результаты.
Она может также использоваться в пакетном режиме: Вы помещаете Ваши запросы в
файл заранее, затем сообщаете, чтобы клиент mysql
выполнил
содержимое файла. Оба пути использования будут здесь рассмотрены.
Чтобы увидеть список параметров mysql
, вызовите его с опцией
--help
:
shell> mysql --help
Эта глава предполагает, что mysql
установлен на Вашей машине,
и что сервер MySQL доступен.
Эта глава описывает весь процесс создания и использования базы данных. Если Вы заинтересованы только в работе с уже существующей базой данных, Вы можете пропустить части, которые описывают, как создать базу данных и таблицы, которые она хранит.
Чтобы соединяться с сервером, Вы обычно должны обеспечить имя пользователя,
когда Вы вызываете mysql
и, вероятно, пароль. Если сервер
выполняется на другой машине, Вы будете также должны определить hostname.
Войдите в контакт с Вашим администратором, чтобы выяснить, какие параметры
соединения Вы должны использовать, чтобы подключиться (то есть, какой
hostname, порт, имя пользователя и пароль). Как только Вы узнаете
соответствующие параметры, Вы должны иметь возможность соединиться так:
shell> mysql -h host -u user -p Enter password: ********
Здесь ********
представляет Ваш пароль. Введите его, когда
mysql
отобразит сообщение Enter password:
.
Если это работает, Вы должны увидеть некоторую вводную информацию,
сопровождаемую подсказкой mysql>
:
shell> mysql -h host -u user -p Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 459 to server version: 3.22.20a-log Type 'help' for help. mysql>
Подсказка сообщает Вам, что mysql
готов принять команды.
Некоторые инсталляции MySQL позволяют пользователям соединяться как
анонимным (неназванным) пользователям с сервером на локальной машине. Если у
Вас дело обстоит именно так, Вы можете соединиться с таким сервером, вызывая
mysql
без параметров:
shell> mysql
После того, как Вы успешно соединились, Вы можете разъединять соединение в
любое время, набрав команду QUIT
в ответ на подсказку
mysql>
:
mysql> QUIT Bye
Вы можете также разъединять связь, нажимая Control-D.
Большинство примеров в следующих разделах считает, что Вы связаны с
сервером. Они указывают это подсказкой mysql>
.
В этой точке более важно выяснить немного относительно того, как выдавать
запросы, чем правильно создавать базы данных. Этот раздел описывает базисные
принципы ввода команд, использование нескольких запросов, которые Вы можете
испытывать, чтобы ознакомиться с тем, как работает клиент mysql
.
Имеется простая команда, которая просит, чтобы сервер сообщил свою версию
и текущую дату. Напечатайте это как показано ниже после подсказки
mysql>
и нажмите клавишу RETURN:
mysql> SELECT VERSION(), CURRENT_DATE; +--------------+--------------+ | version() | CURRENT_DATE | +--------------+--------------+ | 3.22.20a-log | 1999-03-19 | +--------------+--------------+ 1 row in set (0.01 sec) mysql>
Этот запрос иллюстрирует несколько вещей относительно mysql
:
QUIT
. Мы доберемся
до других позже.
mysql
посылает ее серверу для
выполнения и отображает результаты, затем печатает другой запрос
mysql>
, чтобы указать, что готов для приема другой команды.
mysql
отображает вывод запроса как таблицу (строки и
столбцы). Первая строка содержит метки для столбцов. Следующие строки задают
результаты запроса. Обычно, метки столбца представляют собой имена столбцов,
которые Вы выбираете из таблиц базы данных. Если Вы получаете значение
выражения, а не столбец таблицы, mysql
маркирует столбец,
используя выражение непосредственно.
mysql
показывает, сколько строк было возвращено, и как долго
обрабатывался запрос, что дает Вам грубые данные относительно эффективности
сервера. Эти значения неточны потому, что они представляют не машинное время
или затраты времени CPU, а рамки выполнения запроса. На эти данные действуют,
например, задержки в сетевом канале. Для краткости строка ``rows in set'' не
показывается в оставшихся примерах из этой главы.Ключевые слова могут быть введены в любом регистре. Следующие запросы эквивалентны:
mysql> SELECT VERSION(), CURRENT_DATE; mysql> select version(), current_date; mysql> SeLeCt vErSiOn(), current_DATE;
Имеется другой запрос. Он показывает, что Вы можете использовать
mysql
как простой калькулятор:
mysql> SELECT SIN(PI()/4), (4+1)*5; +-------------+---------+ | SIN(PI()/4) | (4+1)*5 | +-------------+---------+ | 0.707107 | 25 | +-------------+---------+
Команды, показанные к настоящему времени, были относительно короткие, с одной строкой инструкции. Вы можете даже вводить много инструкций на одной строке. Только закончите каждую их них точкой с запятой:
mysql> SELECT VERSION(); SELECT NOW(); +--------------+ | version() | +--------------+ | 3.22.20a-log | +--------------+ +---------------------+ | NOW() | +---------------------+ | 1999-03-19 00:15:33 | +---------------------+
Однако, команды бывают и длинными. Но длинные команды, которые требуют
нескольких строк, не проблема. mysql
определяет конец оператора,
ища точку с запятой, а не конец строки. Другими словами, mysql
принимает ввод свободного формата: он собирает вводимые строки, но не
выполняет их, пока не увидит точку с запятой.
Имеется простая инструкция с длинной строкой:
mysql> SELECT -> USER() -> , -> CURRENT_DATE; +--------------------+--------------+ | USER() | CURRENT_DATE | +--------------------+--------------+ | joesmith@localhost | 1999-03-18 | +--------------------+--------------+
В этом примере обратите внимание, как подсказка изменяется с
mysql>
на ->
после того, как Вы вводите
первую строку запроса. Этим mysql
указывает, что пока не видел
полную инструкцию и ждет остальное. Подсказка Ваш друг потому, что
обеспечивает ценную обратную связь. Если Вы используете эту обратную связь,
Вы будете всегда знать, чего ждет от Вас mysql
.
Если Вы решаете, что Вы не хотите выполнять команду, но находитесь в
процессе ввода, отмените ее вводом \c
:
mysql> SELECT -> USER() -> \c mysql>
Здесь также обратите внимание на подсказку. Она переключилась назад в
mysql>
после ввода \c
, обеспечивая обратную
связь, чтобы указать, что mysql
готов для новой команды.
Следующая таблица показывает все подсказки и обобщает их смысл:
Подсказка | Смысл |
mysql> | Ожидание новой команды |
-> | Ожидание следующей строки многострочной команды |
'> | Ожидание следующей строки при сборе строки, которая начинается с одиночной кавычки (') |
"> | Ожидание следующей строки при сборе строки, которая начинается с двойной кавычки (") |
Иногда многострочные инструкции происходят случайно, когда Вы
предполагаете выдавать команду на одной строке, но забываете точку с запятой
для завершения. В этом случае mysql
ждет продолжение ввода:
mysql> SELECT USER() ->
Если это случается с Вами (Вы думаете, что ввели оператор, но единственный
ответ представляет собой подсказку ->
), наиболее вероятно,
что mysql
ждет точку с запятой. Введите точку с запятой, чтобы
завершить инструкцию, и mysql
ее выполнит:
mysql> SELECT USER() -> ; +--------------------+ | USER() | +--------------------+ | joesmith@localhost | +--------------------+
Подсказки '>
и ">
появляются при работе
со строкой в кавычках. В MySQL Вы можете писать строки в символах
' или " (например, 'hello'
или
"goodbye"
), и mysql
позволяет Вам вводить длинные
строки в виде нескольких коротких строк. Когда Вы видите подсказку
'>
или ">
, это означает, что Вы ввели
строку, которая начинается с символа кавычки ' или
", но еще не ввели вторую кавычку, которая завершает эту строку.
Это также может сообщать и об ошибке:
mysql> SELECT * FROM my_table WHERE name="Smith AND age < 30; ">
Если Вы вводите эту инструкцию SELECT
, то нажатие RETURN
ничего не вернет. Вместо того, чтобы задаваться вопросом, почему этот запрос
так долго выполняется, обратите внимание на подсказку ">
.
Это сообщает Вам, что mysql
ожидает увидеть остальную часть
незавершенной строки. Вы видите ошибку в инструкции? Строка
"Smith
пропускает вторую кавычку.
Что делать? Самая простая вещь: отменить команду. Однако, Вы не можете
в этом случае просто напечатать \c
, так как mysql
интерпретирует это как часть, которая вводится! Вместо этого, введите
заключительный символ кавычки (чтобы mysql
понял, что Вы
закончили строку), а уж потом \c
:
mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30; "> "\c mysql>
Подсказка изменяется обратно на mysql>
, указывая, что
mysql
готов для новой команды.
Важно знать, что сообщают подсказки '>
и
">
, так как если Вы по ошибке вводите незавершенную строку,
любые дальнейшие строки, которые Вы введете, будут игнорироваться
mysql
, включая строку QUIT
! Это может крепко
запутать, особенно, если Вы не знаете, что должны ввести кавычку завершения
прежде, чем Вы сможете отменить текущую команду.
Теперь, когда Вы знаете, как вводить команды, самое время обратиться к базе данных.
Предположим, что Вы имеете несколько домашних животных, и Вы хотели бы следить за различными типами информации относительно их. Вы можете сделать это, создавая таблицы, чтобы хранить Ваши данные и загружая их желательной информацией. Затем Вы можете отвечать на различные типы вопросов относительно Ваших животных, получая данные из таблиц. Этот раздел показывает Вам как:
База данных животных будет простой, но нетрудно думать о реальных
ситуациях, в которых подобный тип базы данных мог бы использоваться.
Например, база данных, подобная этой, могла бы использоваться фермером, чтобы
следить за домашним скотом, или ветеринаром, чтобы наблюдать за пациентами.
Дистрибутив базы животных, содержащий некоторые из запросов и типовых данных,
используемых в следующих разделах, может быть получен с Web-сайта MySQL в
сжатом tar
формате или в
Zip-формате.
Используйте инструкцию SHOW
, чтобы выяснить то, какие базы
данных в настоящее время существуют на Вашем сервере:
mysql> SHOW DATABASES; +----------+ | Database | +----------+ | mysql | | test | | tmp | +----------+
Список баз данных, вероятно, иной на Вашей машине, но базы с именами
mysql
и test
, вероятно, будут среди них. База
данных mysql
вообще обязательна потому, что она описывает
привилегии доступа пользователей. База данных test
часто
обеспечивается как рабочая область для начинающих пользователей (лягушатник).
Именно там проводятся разные "опыты со взрывами".
Если существует база данных test
, попробуйте обратиться к ней:
mysql> USE test Database changed
Обратите внимание, что USE
, подобно QUIT
, не
требует точки с запятой. Вы можете завершать такие инструкции точкой с
запятой, если Вы находите это приятным, такой подход не несет никакого вреда.
Инструкция USE
должна быть задана в одной строке.
Вы можете использовать базу данных тестов test
(если Вы
имеете доступ к ней) для примеров, но все, что Вы там насоздавали, может быть
удалено кем-либо еще с доступом к ней. По этой причине, Вы должны, вероятно,
спросить у Вашего администратора MySQL разрешения использовать собственную
базу данных. Предположим, что Вы хотите вызвать Ваш звероуголок
(menagerie
). Администратор должен выполнить такую команду:
mysql> GRANT ALL ON menagerie.* TO your_mysql_name;
Здесь your_mysql_name
представляет собой имя пользователя
MySQL, назначенное Вам.
Если администратор создал базу данных для Вас и установил Ваши права доступа, Вы можете начинать использовать ее. Иначе, Вы должны создать базу данных самостоятельно. Например:
mysql> CREATE DATABASE menagerie;
Под Unix имена баз данных чувствительны к регистру (в отличие от ключевых
слов SQL), так что Вы должны всегда обращаться к Вашей базе данных как к
menagerie
, но не как Menagerie
,
MENAGERIE
или еще как-то. Это также верно для имен таблицы. Под
Windows это ограничение не применяется, хотя Вы должны обращаться к базам
данных и таблицам, используя тот же самый регистр символов в течение запроса.
Создание базы данных не выбирает ее для использования, Вы должны сделать
это явно. Чтобы объявить menagerie
текущей (актуальной) базой
данных, используйте эту команду:
mysql> USE menagerie Database changed
Ваша база данных должна быть создана только однажды, но Вы должны выбирать
ее для использования каждый раз, когда Вы начинаете сеанс mysql
.
Вы можете сделать это, выдавая инструкцию USE
как показано выше.
Альтернативно, Вы можете выбирать базу данных в командной строке, когда Вы
вызываете mysql
. Только определите имя после любых параметров
подключения к серверу, которые Вы должны обеспечить. Например:
shell> mysql -h host -u user -p menagerie Enter password: ********
Обратите внимание, что menagerie
не Ваш пароль. Если Вы
хотите указать пароль в командной строке после опции -p
, Вы
должны сделать это без пробела (например, как -pmypassword
, но
не как -p mypassword
). Однако, помещение Вашего пароля в
командную строку не рекомендуется потому, что это выставит его на всеобщее
обозрение всем пользователям Вашей машины.
Создание базы данных дело простое, но сейчас база пустая, о чем и сообщает
команда SHOW TABLES
:
mysql> SHOW TABLES; Empty set (0.00 sec)
Наиболее трудная часть этого дела: решить, какова будет структура Вашей базы данных, в каких таблицах Вы будете нуждаться, и какие столбцы будут в каждой из них.
Вы будете иметь таблицу, которая содержит запись для каждого из Ваших
домашних животных. Она может быть названа pet
и должна
содержать, как минимум, имя каждого животного. Так как имя само по себе не
очень интересно, таблица должна содержать и другую информацию. Например, если
больше, чем один человек в Вашем семействе имеет домашних животных, Вы могли
бы внести в список владельца каждого животного. Вы могли бы также записывать
некоторую базисную описательную информацию типа разновидности и пола.
Каков приблизительный возраст? Это могло бы быть интересным, но лучше не вписывать такие данные в таблицу. Возраст изменяется, а это означает, что Вы должны будете часто модифицировать Ваши записи. Вместо этого лучше сохранить фиксированное значение, типа даты рождения. Затем всякий раз, когда Вы нуждаетесь в данных о возрасте, Вы можете вычислить его как различие (но не разность!) между текущей датой и датой рождения. MySQL обеспечивает функции для выполнения арифметики даты, так что это нетрудно. Сохранение даты рождения имеет также и другие преимущества:
Пока в таблице pet
ограничимся данными об имени, владельце,
разновидности, поле, рождении и гибели, если она произошла.
Используйте инструкцию CREATE TABLE
, чтобы определить
размещение Вашей таблицы:
mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
VARCHAR
представляет собой хороший выбор для столбцов имени,
владельца и разновидности потому, что значения столбца изменяются по длине.
Длины столбцов name
, owner
и species
не должны превышать 20 символов. Вообще-то, для этого типа столбцов Вы можете
выбирать любую длину от 1
до 255
, какая кажется
наиболее приемлемой Вам. Если Вы делаете столбец недостаточных размеров,
а позже окажется, что Вы нуждаетесь в более длинном поле, MySQL обеспечивает
инструкцию ALTER TABLE
.
Пол животных можно представить разными путями, например, "m"
и "f"
или словами "male"
и "female"
.
Самое простое: использовать одиночные символы "m"
и
"f"
.
Использование типа данных DATE
для столбцов рождения и гибели
(birth
и death
) явно довольно очевидный выбор.
Теперь, когда Вы создали таблицу, SHOW TABLES
должен
произвести некоторый вывод:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | pet | +---------------------+
Чтобы проверить, что Ваша таблица была создана тем путем, каким Вы
ожидали, используйте инструкцию DESCRIBE
:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | owner | varchar(20) | YES | | NULL | | | species | varchar(20) | YES | | NULL | | | sex | char(1) | YES | | NULL | | | birth | date | YES | | NULL | | | death | date | YES | | NULL | | +---------+-------------+------+-----+---------+-------+
Вы можете использовать DESCRIBE
в любое время, например, если
Вы забываете имена столбцов в Вашей таблице, или каких они типов.
После создания Вашей таблицы Вы должны заполнить ее. Инструкции
LOAD DATA
и INSERT
полезны для этого.
Предположим, что Ваши записи о живности могут быть описаны как показано
ниже. Заметьте, что MySQL ожидает даты в формате YYYY-MM-DD
, это
может быть отлично от того, к чему Вы привыкли.
name | owner | species | sex | birth | death |
Fluffy | Harold | кошка | f | 1993-02-04 | |
Claws | Gwen | кошка | m | 1994-03-17 | |
Buffy | Harold | собака | f | 1989-05-13 | |
Fang | Benny | собака | m | 1990-08-27 | |
Bowser | Diane | собака | m | 1989-08-31 | 1995-07-29 |
Chirpy | Gwen | птичка | f | 1998-09-11 | |
Whistler | Gwen | птичка | 1997-12-09 | ||
Slim | Benny | змея | m | 1996-04-29 |
Поскольку Вы начинаете работу с пустой таблицей, самый простой способ заполнить ее состоит в том, чтобы создать текстовый файл, содержащий строку для каждого из Ваших животных, затем загрузить содержимое файла в таблицу всего одной инструкцией.
Вы могли бы создать текстовый файл pet.txt, содержащий одну
запись на строку, со значениями, отделяемыми позициями табуляции, указанными
в том порядке, в котором столбцы были перечислены в инструкции CREATE
TABLE
. Для отсутствующих значений (типа неизвестного пола или дат
гибели для животных, которые все еще живут), Вы можете использовать значения
NULL
. Чтобы представить их в Вашем текстовом файле, используйте
\N
. Например, запись для птички Whistler выглядит примерно так
(пробелом я обозначил табуляцию):
Whistler Gwen птичка \N 1997-12-09 \N
Чтобы загрузить текстовый файл pet.txt в таблицу
pet
, используйте эту команду:
mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
Вы можете определять разделитель значений столбцов и маркер конца строки
в инструкции явно LOAD DATA
, если Вы желаете, но значениями по
умолчанию являются табуляция и перевод строки. Они достаточны, чтобы
правильно прочитать файл pet.txt.
Когда Вы хотите добавить новые записи по одной, полезна инструкция
INSERT
. В самой простой ее форме Вы обеспечиваете значения для
каждого столбца в том порядке, в котором столбцы были перечислены в
инструкции CREATE TABLE
. Предположим, что Diane получила нового
хомяка Puffball. Вы можете добавить новую запись, используя инструкцию
INSERT
, подобно этому:
mysql> INSERT INTO pet -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
Обратите внимание, что строка и значения даты определены как цитируемые
строки. Вы можете вставлять NULL
непосредственно, чтобы
представить отсутствие значения.
Из этого примера Вы видите, что для непосредственной загрузки в таблицу
пришлось бы печатать довольно много. Инструкция LOAD DATA
сберегла много времени.
Инструкция SELECT
используется, чтобы получить информацию из
таблицы. Общая форма инструкции:
SELECT what_to_select FROM which_table WHERE conditions_to_satisfy
what_to_select
указывает то, что Вы хотите увидеть. Это может
быть список столбцов или *
, чтобы указать все столбцы.
which_table
указывает таблицу, из которой Вы хотите получить
данные. Предложение WHERE
факультативно. Если оно представлено,
conditions_to_satisfy
определяет условия, которым должны
удовлетворять искомые строки.
Самая простая форма SELECT
получает все из таблицы:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+--------+---------+------+------------+------------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Fang | Benny | dog | m | 1990-08-27 | NULL | | Bowser | Diane | dog | m | 1998-08-31 | 1995-07-29 | | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+--------+---------+------+------------+------------+
Эта форма SELECT
полезна, если Вы хотите сделать обзор всей
Вашей таблицы, например, после того, как Вы только что загрузили ее начальным
набором данных. Удобно искать ошибки.
Как показано выше, просто получить всю таблицу. Но обычно Вы не хотите
делать это, особенно, когда таблица становится большой. Вместо этого, Вы
обычно больше заинтересованы в ответе на специфический вопрос, когда Вы
определяете некоторые ограничения на информацию, которую Вы хотите получить.
Давайте рассматривать некоторые запросы SELECT
относительно
Ваших домашних животных в терминах вопросов, на которые они отвечают.
Вы можете выбирать только специфические строки из Вашей таблицы. Например, если Вы хотите проверить изменение, которое Вы сделали в дате рождения Bowser, выберите запись для Bowser подобно этому:
mysql> SELECT * FROM pet WHERE name = "Bowser"; +--------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+-------+---------+------+------------+------------+ | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+-------+---------+------+------------+------------+
Вывод подтверждает, что год теперь правильно зарегистрирован как 1989, а не 1998.
Сравнения строк обычно не чувствительны к регистру, так что Вы можете
определять имя как "bowser"
, "BOWSER"
или как
хотите. Результат запроса будет тот же самый.
Вы можете определять произвольные условия на любом столбце, не только
name
. Например, если Вы хотите знать, какие животные были
рождены после 1998 года, проверьте столбец birth
:
mysql> SELECT * FROM pet WHERE birth >= "1998-1-1"; +----------+-------+---------+-----+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+-----+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+-------+---------+-----+------------+-------+
Вы можете объединять условия, например, найти самок собак:
mysql> SELECT * FROM pet WHERE species="dog" AND sex="f"; +-------+--------+---------+-----+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+-----+------------+-------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+-----+------------+-------+
Предшествующий запрос использует логический оператор AND
.
Имеется также оператор OR
:
mysql> SELECT * FROM pet WHERE species="snake" OR species="bird"; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | +----------+-------+---------+------+------------+-------+
Операторы AND
и OR
могут быть перемешаны. Тут
стоит использовать круглые скобки, чтобы указать, как именно условия
должны быть сгруппированы:
mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m") -> OR (species = "dog" AND sex = "f"); +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Если Вы не хотите видеть все строки из Вашей таблицы, только укажите
столбцы, в которых вы заинтересованы, отделяя их запятыми. Например, если Вы
хотите знать, когда Ваши животные были рождены, выберите столбцы
name
и birth
:
mysql> SELECT name, birth FROM pet; +----------+------------+ | name | birth | +----------+------------+ | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Buffy | 1989-05-13 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Puffball | 1999-03-30 | +----------+------------+
Чтобы выяснить, кто обладает домашним животным, используйте такой запрос:
mysql> SELECT owner FROM pet; +--------+ | owner | +--------+ | Harold | | Gwen | | Harold | | Benny | | Diane | | Gwen | | Gwen | | Benny | | Diane | +--------+
Однако, обратите внимание, что запрос просто находит
поле owner
из каждой записи, и некоторые из них появляются
больше, чем однажды. Чтобы минимизировать вывод, получите каждую уникальную
запись вывода только однажды, добавляя ключевое слово DISTINCT
:
mysql> SELECT DISTINCT owner FROM pet; +--------+ | owner | +--------+ | Benny | | Diane | | Gwen | | Harold | +--------+
Вы можете использовать предложение WHERE
, чтобы объединить
выбор строки с выбором столбца. Например, чтобы получить даты рождения только
для кошек и собак, используйте запрос:
mysql> SELECT name, species, birth FROM pet -> WHERE species = "dog" OR species = "cat"; +--------+---------+------------+ | name | species | birth | +--------+---------+------------+ | Fluffy | cat | 1993-02-04 | | Claws | cat | 1994-03-17 | | Buffy | dog | 1989-05-13 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | +--------+---------+------------+
Вы, возможно, отметили в предшествующих примерах, что строки результатов
не отображаются ни в каком специфическом порядке. Однако, часто проще
исследовать вывод запроса, когда строки сортируются некоторым способом. Чтобы
отсортировать результат, используйте предложение ORDER BY
.
Отсортируем дни рождения нашей живности:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+ | name | birth | +----------+------------+ | Buffy | 1989-05-13 | | Bowser | 1989-08-31 | | Fang | 1990-08-27 | | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Slim | 1996-04-29 | | Whistler | 1997-12-09 | | Chirpy | 1998-09-11 | | Puffball | 1999-03-30 | +----------+------------+
Чтобы сортировать в обратном порядке, добавьте к имени столбца, по
которому Вы сортируете, ключевое слово DESC
:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+ | name | birth | +----------+------------+ | Puffball | 1999-03-30 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Claws | 1994-03-17 | | Fluffy | 1993-02-04 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Buffy | 1989-05-13 | +----------+------------+
Вы можете сортировать по нескольким столбцам сразу. Например, чтобы сортировать типы животных, затем внутри определенных типов выполнить сортировку по датам рождения, выполните (самых молодых зверушек надо поместить в начало списка):
mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC; +----------+---------+------------+ | name | species | birth | +----------+---------+------------+ | Chirpy | bird | 1998-09-11 | | Whistler | bird | 1997-12-09 | | Claws | cat | 1994-03-17 | | Fluffy | cat | 1993-02-04 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | | Buffy | dog | 1989-05-13 | | Puffball | hamster | 1999-03-30 | | Slim | snake | 1996-04-29 | +----------+---------+------------+
Обратите внимание, что ключевое слово DESC
применяется только
к имени столбца непосредственно перед ним (birth
), а значения
species
сортируются в порядке возрастания.
MySQL обеспечивает несколько функций, которые Вы можете использовать, чтобы выполнить вычисления на датах, например, вычислять возрасты животных.
Чтобы определять сколько лет каждому из Ваших домашних животных, надо вычислить разницу между текущей датой и днем рожления. Следующий запрос показывает для каждого домашнего животного дату рождения, текущую дату и возраст в целых годах.
mysql> SELECT name, birth, CURRENT_DATE, -> (YEAR(CURRENT_DATE)-YEAR(birth)) -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5)) AS age FROM pet; +----------+------------+--------------+------+ | name | birth | CURRENT_DATE | age | +----------+------------+--------------+------+ | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | +----------+------------+--------------+------+
Здесь YEAR()
выделяет часть года даты, RIGHT()
убирает пять символов, которые представляют часть MM-DD
даты.
Часть выражения, которое сравнивает значения MM-DD
, выставляется
в 1 или 0, что корректирует различие лет, если CURRENT_DATE
стоит ранее в году, чем рождение (birth
). Полное выражение
несколько перегружено, так что псевдоним (age
) используется,
чтобы заставить столбец вывода обрести более читабельный заголовок.
Запрос работает, но результат мог бы быть просмотрен более легко, если
строки были выведены в некотором порядке. Это может быть выполнено, добавляя
предложение ORDER BY name
, чтобы сортировать вывод:
mysql> SELECT name, birth, CURRENT_DATE, -> (YEAR(CURRENT_DATE)-YEAR(birth)) -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5)) -> AS age FROM pet ORDER BY name; +----------+------------+--------------+------+ | name | birth | CURRENT_DATE | age | +----------+------------+--------------+------+ | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | +----------+------------+--------------+------+
Чтобы отсортировать вывод по возрасту (age
), а не по имени
(name
), примените другое предложение ORDER BY
:
mysql> SELECT name, birth, CURRENT_DATE, -> (YEAR(CURRENT_DATE)-YEAR(birth)) -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5)) -> AS age FROM pet ORDER BY age; +----------+------------+--------------+------+ | name | birth | CURRENT_DATE | age | +----------+------------+--------------+------+ | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | +----------+------------+--------------+------+
Подобный запрос может использоваться, чтобы определить возраст для
животных, которые умерли. Вы определяете такие случаи, проверяя, является или
нет значение death
равным NULL
. Затем, для тех,
которые не-NULL
, вычислите разницу между death
и
birth
:
mysql> SELECT name, birth, death, -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) -> AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+ | name | birth | death | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+
Запрос использует death IS NOT NULL
вместо death !=
NULL
потому, что NULL
специальное значение. Подробности в
разделе "2.3.4.6 Работа со значениями
NULL
".
Что делать, если Вы хотите знать, какие животные имеют дни рождения в
следующем месяце? Для этого типа вычисления, год и день не годятся. Вы просто
хотите извлекать часть месяца из столбца birth
. MySQL
обеспечивает несколько функций извлечения частей даты, типа
YEAR()
, MONTH()
и DAYOFMONTH()
. Чтобы
увидеть, как это работает, выполните простой запрос, который отображает
значения birth
и MONTH(birth)
:
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+ | name | birth | MONTH(birth) | +----------+------------+--------------+ | Fluffy | 1993-02-04 | 2 | | Claws | 1994-03-17 | 3 | | Buffy | 1989-05-13 | 5 | | Fang | 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | | Chirpy | 1998-09-11 | 9 | | Whistler | 1997-12-09 | 12 | | Slim | 1996-04-29 | 4 | | Puffball | 1999-03-30 | 3 | +----------+------------+--------------+
Поиск животных с днями рождения в наступающем месяце прост. Предположим,
что текущий месяц апрель. Значение month равно 4
, и Вы ищете
животных, рожденных в мае (month=5):
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+
Имеется маленькое осложнение, если текущий месяц декабрь. Здесь надо искать животных, рожденных в январе.
Вы можете даже написать запрос так, чтобы это работало независимо от того,
каков текущий месяц. DATE_ADD()
позволяет Вам добавлять интервал
времени к заданной дате. Если Вы добавляете месяц к значению
NOW()
, а затем извлекаете часть месяца с помощью
MONTH()
, результатом как раз и будет тот месяц, в котором надо
искать дни рождения:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));
NULL
Значение NULL
может удивлять, пока Вы не привыкнете к нему.
Концептуально, NULL
означает отсутствие средств для оценки или
неизвестное значение, и это обрабатывается несколько по-другому, чем другие
значения. Для проверки на NULL
Вы не можете использовать
арифметические операторы, например, =
, <
или
!=
. Чтобы показать это, попробуйте следующий запрос:
mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+ | 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL | +----------+-----------+----------+----------+ | NULL | NULL | NULL | NULL | +----------+-----------+----------+----------+
Очевидно, что никакого толка от таких сравнений нет и не будет.
Используйте взамен операторы IS NULL
и IS NOT NULL
:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+ | 1 IS NULL | 1 IS NOT NULL | +-----------+---------------+ | 0 | 1 | +-----------+---------------+
В MySQL 0 или NULL
означает false в логических операциях, а
все остальное значит true. Заданное по умолчанию значение истины в булевых
операциях равно 1.
Эта специальная обработка NULL
является причиной того, почему
в предыдущем разделе было необходимо определить, которые животные умерли,
используя именно death IS NOT NULL
вместо
death!=NULL
.
MySQL обеспечивает стандартные шаблоны SQL, основанные на расширенных
регулярных выражениях, подобных используемым Unix-приложениями, вроде
vi
, grep
и sed
.
SQL-шаблоны позволяют Вам использовать _, чтобы
соответствовать любому одиночному символу и %, чтобы
соответствовать произвольному числу символов (включая нулевое количество).
В MySQL SQL-шаблоны по умолчанию не чувствительны к регистру. Некоторые
примеры показываются ниже. Обратите внимание, что Вы не используете
=
или !=
, когда Вы применяете образцы SQL;
используйте операторы сравнения LIKE
или NOT LIKE
.
Чтобы найти имена, начинающиеся с `b', введите:
mysql> SELECT * FROM pet WHERE name LIKE "b%"; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
Чтобы найти имена, заканчивающиеся на `fy', введите:
mysql> SELECT * FROM pet WHERE name LIKE "%fy"; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
Чтобы найти имена, содержащие `w', введите:
mysql> SELECT * FROM pet WHERE name LIKE "%w%"; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
Чтобы найти имена, содержащие точно пять символов, используйте символ _:
mysql> SELECT * FROM pet WHERE name LIKE "_____"; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Другой тип образца, поддерживаемый MySQL, это расширенные регулярные
выражения. Когда Вы проверяете соответствия для этого типа образца,
используйте операторы REGEXP
и NOT REGEXP
(или
RLIKE
и NOT RLIKE
, которые являются синонимами).
Некоторые характеристики расширенных регулярных выражений:
Чтобы проиллюстрировать, как выполняется работа регулярных выражений,
показанные выше запросы LIKE
переделаны ниже так, чтобы
использовать их с REGEXP
.
Чтобы находить имена, начинающиеся с b, примените ^, чтобы соответствовать началу имени:
mysql> SELECT * FROM pet WHERE name REGEXP "^b"; +--------+--------+---------+-----+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+-----+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+-----+------------+------------+
До MySQL Version 3.23.4 REGEXP
чувствителен к регистру, и
предыдущий запрос не возвратит никаких строк. Чтобы соответствовать нижнему
или верхнему регистру b, используйте этот запрос взамен:
mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";
В MySQL 3.23.4, чтобы вынудить сравнение REGEXP
быть
чувствительным к регистру, используют ключевое слово BINARY
,
чтобы сделать одну из строк двоичной. Этот запрос будет соответствовать
только нижнему регистру b в начале имени:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";
Чтобы находить имена, заканчивающиеся на fy, примените $, чтобы соответствовать концу имени:
mysql> SELECT * FROM pet WHERE name REGEXP "fy$"; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
Чтобы находить имена, содержащие `w', неважно в каком регистре, используйте этот запрос:
mysql> SELECT * FROM pet WHERE name REGEXP "w"; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
Потому, что регулярное выражение срабатывает, если соответствие происходит где-нибудь в значении, в предыдущем запросе необязательно размещать групповой символ с обеих сторон образца, чтобы соответствовать всему значению. Хотя именно так пришлось бы поступить в стандартном SQL.
Чтобы находить имена, содержащие точно пять символов, используйте ^ и $, чтобы соответствовать началу, концу имени и пяти образцам точки . между ними:
mysql> SELECT * FROM pet WHERE name REGEXP "^.....$"; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Вы могли бы также переписать предыдущий запрос, используя
{n} в операторе repeat-n
-times:
mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$"; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Базы данных часто используются, чтобы ответить на вопрос о том, как часто некоторые данные попадаются в таблице. Например, Вы могли бы узнать, сколько домашних животных Вы имеете, или сколько домашних животных имеет каждый владелец, или Вы могли бы выполнять различные виды переписи животных.
Подсчет общего количества животных, которых Вы имеете, аналогичен вопросу
о том, сколько строк находятся в таблице pet
? Дело в том, что
имеется одна запись на домашнее животное. Функция COUNT()
считает число не-NULL
результатов, так что запрос для подсчета
животных выглядит следующим образом:
mysql> SELECT COUNT(*) FROM pet; +----------+ | COUNT(*) | +----------+ | 9 | +----------+
Ранее Вы нашли имена людей, которые имели домашние животных. Вы можете
использовать COUNT()
, если хотите выяснить, сколько домашних
животных имеет каждый владелец:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+ | owner | COUNT(*) | +--------+----------+ | Benny | 2 | | Diane | 2 | | Gwen | 3 | | Harold | 2 | +--------+----------+
Обратите внимание на использование ключевого слова GROUP BY
,
чтобы сгруппировать вместе все записи для каждого владельца
(owner
). Без него все, что Вы получите, это сообщение об ошибках:
mysql> SELECT owner, COUNT(owner) FROM pet; ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause
COUNT()
и GROUP BY
полезны для характеристики
Ваших данных различными способами. Следующие примеры показывают различные
способы выполнить операции переписи.
Число животных на разновидность:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+ | species | COUNT(*) | +---------+----------+ | bird | 2 | | cat | 2 | | dog | 3 | | hamster | 1 | | snake | 1 | +---------+----------+
Число животных на пол:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+ | sex | COUNT(*) | +------+----------+ | NULL | 1 | | f | 4 | | m | 4 | +------+----------+
В этом выводе NULL
указывает неизвестный пол.
Число животных на комбинацию разновидности и пола:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | NULL | 1 | | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+
Вы не должны получать всю таблицу, когда Вы используете
COUNT()
. Например, предыдущий запрос, когда он выполняется
только на кошках и собаках, выглядит следующим образом:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE species = "dog" OR species = "cat" GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | +---------+------+----------+
Если Вы хотите получить число животных каждого пола (только для животных, пол которых известен):
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE sex IS NOT NULL GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+
Таблица pet
описывает, каких домашних животных Вы имеете.
Если Вы хотите записывать другую информацию относительно их, типа событий в
их жизнях, подобно посещениям ветеринара, или когда рождалось потомство, Вы
нуждаетесь в другой таблице. Что эта таблица должна включать? Требуется:
Согласно этим данным инструкция CREATE TABLE
для таблицы
событий (event
) могла бы выглядеть следующим образом:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));
Как с таблицей pet
, проще всего загрузить начальные записи,
создав разграниченный табуляциями текстовый файл, содержащий информацию:
Fluffy | 1995-05-15 | Потомство | 4 котенка, 3 female, 1 male |
Buffy | 1993-06-23 | Потомство | 5 щенков, 2 female, 3 male |
Buffy | 1994-06-19 | Потомство | 3 щенка, 3 female |
Chirpy | 1999-03-21 | Ветеринар | Необходимо выпрямление клюва |
Slim | 1997-08-03 | Ветеринар | Сломано ребро |
Bowser | 1991-10-12 | Конура | |
Fang | 1991-10-12 | Конура | |
Fang | 1998-08-28 | День рождения | Подарок: новая жевательная игрушка |
Claws | 1998-03-17 | День рождения | Подарок: ошейник от блох |
Whistler | 1998-12-09 | День рождения | Первый день рождения |
Загрузите записи так:
mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;
Учитывая то, чему Вы научились (я очень надеюсь, что и правда чему-то
научились) на запросах к таблице pet
, Вы должны быть способны
выполнить поиски на записях в таблице event
, принципы те же
самые. Но что делать, когда таблица event
отдельно недостаточна,
чтобы ответить на вопросы, которые Вы задаете?
Предположим, что Вы хотите выяснить возрасты каждого домашнего животного,
когда они имели потомство. Таблица event
указывает, когда это
произошло, но чтобы вычислить возраст матери, Вы нуждаетесь в ее дате
рождения. Поскольку это сохранено в таблице pet
, Вы нуждаетесь в
обеих таблицах для обработки запроса:
mysql> SELECT pet.name, (TO_DAYS(date)-TO_DAYS(birth))/365 AS age, -> remark FROM pet, event WHERE pet.name=event.name -> AND type="litter"; +--------+------+-----------------------------+ | name | age | remark | +--------+------+-----------------------------+ | Fluffy | 2.27 | 4 kittens, 3 female, 1 male | | Buffy | 4.12 | 5 puppies, 2 female, 3 male | | Buffy | 5.10 | 3 puppies, 3 female | +--------+------+-----------------------------+
Итак, что тут происходит?
FROM
вносит в список две таблицы потому, что
запрос должен получить информацию из обеих таблиц.
name
.
Запрос использует предложение WHERE
, чтобы заставить совпасть
записи в двух таблицах, основываясь на значениях name
.
name
есть в обеих таблицах, Вы должны
указать, относительно которой таблицы Вы его обозначаете. Это выполнено
добавлением имени таблицы к имени столбца.Вы не должны иметь две различных таблицы, чтобы выполнить объединение.
Иногда полезно присоединить таблицу к самой себе, если Вы хотите сравнивать
записи в таблице с другими записями в этой же самой таблице. Например, чтобы
найти размножающиеся пары среди Ваших домашних животных, Вы можете соединять
таблицу pet
с самой собой, чтобы соединить самцов и самок
подобной разновидности:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species -> FROM pet AS p1, pet AS p2 -> WHERE p1.species=p2.species AND p1.sex="f" AND p2.sex="m"; +--------+------+--------+------+---------+ | name | sex | name | sex | species | +--------+------+--------+------+---------+ | Fluffy | f | Claws | m | cat | | Buffy | f | Fang | m | dog | | Buffy | f | Bowser | m | dog | +--------+------+--------+------+---------+
В этом запросе мы определяем псевдонимы для имени таблицы, чтобы обратиться к столбцам и указываем прямо, с которым образцом таблицы каждая ссылка столбца связана.
Что, если Вы забыли имя базы данных, или таблицы или ее структуру (например, как столбцы именованы)? MySQL решает эту проблему через несколько инструкций, которые обеспечивают информацию относительно баз данных и таблиц, которые это поддерживают.
Вы уже видели вызов SHOW DATABASES
, который вносит в список
базы данных, управляемые сервером. Чтобы выяснять, которая база данных в
настоящее время выбрана, используйте функцию DATABASE()
:
mysql> SELECT DATABASE(); +------------+ | DATABASE() | +------------+ | menagerie | +------------+
Если Вы не выбрали базу данных, результат пуст.
Чтобы выяснять какие таблицы хранит текущая база данных (например, когда Вы не уверены относительно имени таблицы), используйте эту команду:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | event | | pet | +---------------------+
Если Вы хотите выяснить что-то относительно структуры таблицы, команда
DESCRIBE
очень полезна. Она отображает информацию относительно
каждого из столбцов таблицы:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | owner | varchar(20) | YES | | NULL | | | species | varchar(20) | YES | | NULL | | | sex | char(1) | YES | | NULL | | | birth | date | YES | | NULL | | | death | date | YES | | NULL | | +---------+-------------+------+-----+---------+-------+
Field
указывает имя столбца, Type
тип данных для
столбца, Null
указывает, может или нет столбец содержать
значения NULL
, Key
указывает, индексирован или нет
столбец, а Default
определяет значение столбца по умолчанию.
Если Вы имеете индексы на таблице, SHOW INDEX FROM tbl_name
производит информацию относительно их.
Имеются примеры того, как решить некоторые общие проблемы с MySQL.
Некоторые из примеров используют таблицы shop
, чтобы хранить
цену каждого изделия (номер элемента, item
) для некоторых
торговцев (trader
). Предположим, что каждый торговец имеет одну
фиксированную цену на изделие, тогда пара (item
,
trader
) является первичным ключом для записей.
Запустите инструмент командной строки mysql
и
выберите базу данных:
mysql your-database-name
В большинстве инсталляций MySQL Вы можете использовать имя базы данных test.
Вы можете создать таблицу для примера так:
CREATE TABLE shop (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, dealer CHAR(20) DEFAULT '' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL, PRIMARY KEY(article, dealer)); INSERT INTO shop VALUES (1,'A',3.45),(1,'B',3.99),(2,'A',10.99), (3,'B',1.45),(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
Посмотрим данные примера:
mysql> SELECT * FROM shop; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0001 | A | 3.45 | | 0001 | B | 3.99 | | 0002 | A | 10.99 | | 0003 | B | 1.45 | | 0003 | C | 1.69 | | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+--------+-------+
Что является самым большим значением для элемента?
SELECT MAX(article) AS article FROM shop +---------+ | article | +---------+ | 4 | +---------+
Допустим, надо найти код, торговца и цену наиболее дорогого изделия.
В ANSI SQL это легко может быть выполнен подзапросом:
SELECT article, dealer, price FROM shop WHERE price=(SELECT MAX(price) FROM shop)
В MySQL (который еще не имеет поддержки вложенных запросов) это делается за два шага:
SELECT
.
SELECT article, dealer, price FROM shop WHERE price=19.95
Другое решение состоит в том, чтобы сортировать все строки по убыванию
цены и получить только первую из них, используя специфическое для MySQL
предложение LIMIT
:
SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1
ОБРАТИТЕ ВНИМАНИЕ: Если имеется несколько изделий с
одинаковой ценой (например, каждое по 19.95), то LIMIT
показывает только одно из них.
Что является самой высокой ценой на изделие?
SELECT article, MAX(price) AS price FROM shop GROUP BY article +---------+-------+ | article | price | +---------+-------+ | 0001 | 3.99 | | 0002 | 10.99 | | 0003 | 1.69 | | 0004 | 19.95 | +---------+-------+
Для каждого изделия, найдите торгового агента с наиболее высокой ценой.
В ANSI SQL я сделал бы это подзапросом:
SELECT article, dealer, price FROM shop s1 WHERE price=(SELECT MAX(s2.price) FROM shop s2 WHERE s1.article = s2.article);
В MySQL проще всего добиться такого эффекта так:
Это может быть легко выполнено через временную таблицу:
CREATE TEMPORARY TABLE tmp (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL); LOCK TABLES shop read; INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article; SELECT shop.article, dealer, shop.price FROM shop, tmp WHERE shop.article=tmp.article AND shop.price=tmp.price; UNLOCK TABLES; DROP TABLE tmp;
Если Вы не используете таблицу TEMPORARY
, Вы должны также
блокировать таблицу tmp.
Можно это сделать одиночным запросом?
Да, но только используя совершенно неэффективный прием MAX-CONCAT trick:
SELECT article, SUBSTRING(MAX(CONCAT(LPAD(price,6,'0'),dealer)), 7) AS dealer, 0.00+LEFT(MAX(CONCAT(LPAD(price,6,'0'),dealer)), 6) AS price FROM shop GROUP BY article; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0001 | B | 3.99 | | 0002 | A | 10.99 | | 0003 | C | 1.69 | | 0004 | D | 19.95 | +---------+--------+-------+
Вы можете применять переменные пользователя MySQL, чтобы помнить результаты без того, чтобы сохранять их во временных переменных на клиенте.
Например, чтобы найти изделия с самыми высокими и низкими ценами, Вы можете сделать следующее:
select @min_price:=min(price),@max_price:=max(price) from shop; select * from shop where price=@min_price or price=@max_price; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+--------+-------+
Вы не нуждаетесь во внешних ключах, чтобы соединить 2 таблицы.
Единственная вещь, которую MySQL не делает, это CHECK
, чтобы
удостовериться, что ключи, которые Вы используете, действительно, существуют
в таблице и автоматически не удаляет строки из таблицы с внешним ключом. Если
Вы используете Ваши ключи обычным порядком, это только улучшит работу:
CREATE TABLE persons (id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id)); CREATE TABLE shirts (id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('t-shirt', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES persons, PRIMARY KEY (id)); INSERT INTO persons VALUES (NULL, 'Antonio Paz'); INSERT INTO shirts VALUES (NULL, 'polo', 'blue', LAST_INSERT_ID()), (NULL, 'dress', 'white', LAST_INSERT_ID()), (NULL, 't-shirt', 'blue', LAST_INSERT_ID()); INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska'); INSERT INTO shirts VALUES (NULL, 'dress', 'orange', LAST_INSERT_ID()), (NULL, 'polo', 'red', LAST_INSERT_ID()), (NULL, 'dress', 'blue', LAST_INSERT_ID()), (NULL, 't-shirt', 'white', LAST_INSERT_ID()); SELECT * FROM persons; +----+---------------------+ | id | name | +----+---------------------+ | 1 | Antonio Paz | | 2 | Lilliana Angelovska | +----+---------------------+ SELECT * FROM shirts; +----+---------+--------+-------+ | id | style | color | owner | +----+---------+--------+-------+ | 1 | polo | blue | 1 | | 2 | dress | white | 1 | | 3 | t-shirt | blue | 1 | | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | | 7 | t-shirt | white | 2 | +----+---------+--------+-------+ SELECT s.* FROM persons p, shirts s WHERE p.name LIKE 'Lilliana%' AND s.owner = p.id AND s.color <> 'white'; +----+-------+--------+-------+ | id | style | color | owner | +----+-------+--------+-------+ | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | +----+-------+--------+-------+
MySQL не оптимизирует запрос, когда Вы ищете на двух различных ключах,
объединенных с помощью OR
. Поиск на одном ключе с
OR
оптимизирован хорошо.
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' OR field2_index = '1'
Причина в том, что авторы не имели времени, чтобы придумать эффективный
способ обработать это в общем случае. Обработка AND
теперь
полностью общая и работает очень хорошо.
Сейчас Вы можете сделать все это очень эффективно, используя таблицу
TEMPORARY
. Этот тип оптимизации также очень хорош, если Вы
используете очень сложные запросы, где сервер SQL путается и делает
оптимизацию в неправильном порядке.
CREATE TEMPORARY TABLE tmp SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'; INSERT INTO tmp SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1'; SELECT * from tmp; DROP TABLE tmp;
Вышеупомянутый способ выполнить этот запрос в действительности вызывает
UNION
для двух запросов.
Следующее предлагает идею относительно того, как Вы можете использовать разрядные функции группы, чтобы вычислить число дней, которое пользователь посетил страничку в сети.
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30), (2000,2,2),(2000,2,23),(2000,2,23); SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month; +------+-------+------+ | year | month | days | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+
Вышеупомянутый запрос вычисляет, сколько различных дней использовались для данной комбинации лет с конкретным месяцем с автоматическим удалением двойных записей.
mysql
в пакетном режимеВ предыдущих разделах Вы использовали mysql
в интерактивном
режиме, чтобы ввести запросы и рассматривать результаты. Вы можете также
выполнять mysql
в пакетном режиме. Чтобы сделать это, поместите
команды, Вы хотите выполнить в файл, затем сообщать, чтобы mysql
читал ввод из файла:
shell> mysql < batch-file
Если Вы должны определить параметры подключения в командной строке, команда вызова могла бы выглядеть следующим образом:
shell> mysql -h host -u user -p < batch-file Enter password: ********
Когда Вы используете mysql
этим способом, Вы создаете файл
скрипта, а затем выполняете скрипт.
Почему использование скриптов удобно? Имеется несколько причин:
mysql
выполнил его снова.
shell> mysql < batch-file|more
shell> mysql < batch-file > mysql.out
cron
. В этом случае
Вы должны использовать пакетный режим.Заданный по умолчанию выходной формат несколько иной (более краткий),
когда Вы выполняете mysql
в пакетном режиме. Например, вывод
SELECT DISTINCT species FROM pet
напоминает этот образец, когда
выполнен в интерактивном режиме:
+---------+ | species | +---------+ | bird | | cat | | dog | | hamster | | snake | +---------+
Но когда выполнен в пакетном режиме, он подобен этому:
species bird cat dog hamster snake
Если Вы хотите получать интерактивный выходной формат в пакетном режиме,
используйте mysql -t
. Для добавления к выводу команд, которые
были выполнены, используется mysql -vvv
.
Два университета ведут большой исследовательский проект. Проект включает часть опроса, где все близнецы в Швеции старше, чем 65 лет, интервьюируются по телефону. Близнецы, у которых встречаются некоторые критерии, передаются на следующюю стадию. На этой последней стадии близнецы, которые хотят участвовать, посещаются группой врачей и подвергаются всесторонним тестам. Большее количество информации относительно проекта есть по адресу:
http://www.imm.ki.se/TWIN/TWINUKW.HTM
Последняя часть проекта управляется Web-интерфесом, написанным на Perl с базой данных под MySQL.
Каждую ночь (исследования ведутся днем) все данные из интервью перемещаются в базу данных MySQL.
Следующий запрос используется, чтобы определить, кто из близнецов идет во вторую часть проекта:
select concat(p1.id, p1.tvab) + 0 as tvid, concat(p1.christian_name, " ", p1.surname) as Name, p1.postal_code as Code, p1.city as City, pg.abrev as Area, if(td.participation = "Aborted", "A", " ") as A, p1.dead as dead1, l.event as event1, td.suspect as tsuspect1, id.suspect as isuspect1, td.severe as tsevere1, id.severe as isevere1, p2.dead as dead2, l2.event as event2, h2.nurse as nurse2, h2.doctor as doctor2, td2.suspect as tsuspect2, id2.suspect as isuspect2, td2.severe as tsevere2, id2.severe as isevere2, l.finish_date from twin_project as tp left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab left join informant_data as id on tp.id = id.id and tp.tvab=id.tvab left join harmony as h on tp.id = h.id and tp.tvab = h.tvab left join lentus as l on tp.id = l.id and tp.tvab = l.tvab left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab left join informant_data as id2 on p2.id = id2.id and p2.tvab=id2.tvab left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab, person_data as p1, person_data as p2, postal_groups as pg where p1.id = tp.id and p1.tvab = tp.tvab and p2.id = p1.id and p2.ptvab = p1.tvab and tp.survey_no = 5 and (p2.dead = 0 or p2.dead=9 or (p2.dead=1 and (p2.death_date=0 or (((to_days(p2.death_date)-to_days(p2.birthday))/365) >= 65)))) and ((td.future_contact = 'Yes' and td.suspect = 2) or (td.future_contact = 'Yes' and td.suspect = 1 and id.suspect=1) or (ISNULL(td.suspect) and id.suspect=1 and id.future_contact='Yes') or (td.participation = 'Aborted' and id.suspect = 1 and id.future_contact = 'Yes') or (td.participation = 'Aborted' and ISNULL(id.suspect) and p2.dead = 0)) and l.event = 'Finished' and substring(p1.postal_code, 1, 2) = pg.code and (h.nurse is NULL or h.nurse=00 or h.doctor=00) and not (h.status = 'Refused' or h.status = 'Aborted' or h.status = 'Died' or h.status = 'Other') order by tvid;
Как Вам такой запрос? Даю некоторые объяснения:
concat(p1.id, p1.tvab) + 0 as tvid
id
и
tvab
в числовом порядке. Добавление 0
к результату
заставляет MySQL обрабатывать его именно как число.
id
tvab
1
или 2
.
ptvab
tvab
. Когда tvab
равно
1
, ptvab
принимает значение 2
, и
наоборот. Это существует, чтобы проще оптимизировать запрос.Этот запрос показывает среди других вещей, как делать поиск на таблице из
той же самой таблицы с объединением (p1
и p2
). В
примере это используется, чтобы проверить, умер ли партнер близнецов до 65
лет. Если так, строка не будет возвращена.
Все вышеприведенное существует во всех таблицах с информацией по
близнецам. Мы имеем ключ на паре id,tvab
(все таблицы) и другой
паре id,ptvab
(только в person_data
), чтобы
сделать запросы быстрее.
На нашей машине (200MHz UltraSPARC) этот запрос возвращает приблизительно 150-200 строк и требует времени меньше, чем одна секунда.
Текущее число записей в таблицах, используемых выше:
Таблица | Строк |
person_data | 71074 |
lentus | 5291 |
twin_project | 5286 |
twin_data | 2012 |
informant_data | 663 |
harmony | 381 |
postal_groups | 100 |
Каждое интервью завершается кодом состояния event
. Запрос,
показанный ниже, используется, чтобы отобразить таблицу по всем парам
близнецов, у которых код одинаковый.
select t1.event, t2.event, count(*) from lentus as t1, lentus as t2, twin_project as tp where t1.id = tp.id and t1.tvab=tp.tvab and t1.id = t2.id and tp.survey_no = 5 and t1.tvab='1' and t2.tvab='2' group by t1.event, t2.event;
Этот раздел описывает различные способы записи строк и чисел в MySQL. Это также покрывает различные нюансы, с которыми Вы можете сталкиваться, когда имеете дело с этими базисными типами в MySQL.
Строка представляет собой последовательность символов, окруженных одиночными кавычками (') или двойными кавычками ("). Допустима только одиночная кавычка, если Вы работаете в ANSI-режиме. Примеры:
'a string' "another string"
Внутри строки некоторые последовательности имеют специальное значение. Каждая из этих последовательностей начинается с наклонной черты влево (\), известной как escape character. MySQL распознает следующие управляющие последовательности:
\0
NUL
).
\'
\"
\b
\n
\r
\t
\z
mysql database < filename
.
\\
\%
\_
Обратите внимание, что, если Вы используете \% или \_ в некоторых контекстах, они возвратят строки \% и \_ вместо % и _.
Имеется несколько способов включить кавычки в строку:
Инструкции SELECT
, приведенные ниже, показывают как работают
цитирование и экранировка:
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello'; +-------+---------+-----------+--------+--------+ | hello | "hello" | ""hello"" | hel'lo | 'hello | +-------+---------+-----------+--------+--------+ mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello"; +-------+---------+-----------+--------+--------+ | hello | 'hello' | ''hello'' | hel"lo | "hello | +-------+---------+-----------+--------+--------+ mysql> SELECT "This\nIs\nFour\nlines"; +--------------------+ | This Is Four lines | +--------------------+
Если Вы хотите вставлять двоичные данные в столбец BLOB
,
следующие символы должны представляться в соответствии с управляющими
последовательностями, экранирующими их:
NUL
\
'
"
Если Вы пишете код на C, Вы можете использовать функцию
C API mysql_escape_string()
для инструкции INSERT
.
В языке Perl Вы можете использовать метод quote
пакета
DBI
, чтобы преобразовать специальные символы в соответствующие
управляющие последовательности.
Вы должны использовать функцию escape на любой строке, которая могла бы содержать любой из специальных символов, перечисленных выше!
Целые числа представляются как последовательность цифр. Числа с плавающей точкой используют точку (.) как десятичный разделитель. Любому типу числа может предшествовать знак -, чтобы указать отрицательное значение числа.
Примеры имеющих силу целых чисел:
1221 0 -32
Примеры чисел с плавающей запятой:
294.42 -32032.6809e+10 148.00
Целое число может использоваться в контексте с плавающей запятой: это интерпретируется как эквивалентное число с плавающей запятой.
MySQL поддерживает шестнадцатеричные значения. В контексте числа это аналогично целому числу (64-разрядная точность). В контексте строки такое число эквивалентно двоичной строке, где каждая пара шестнадцатеричных цифр преобразована в соответствующий символ:
mysql> SELECT x'FF' -> 255 mysql> SELECT 0xa+0; -> 10 mysql> select 0x5061756c; -> Paul
Синтаксис x'hexstring' (нововведение в версии 4.0) основан на ANSI SQL и синтаксисе 0x из ODBC. Шестнадцатеричные строки часто используются ODBC, чтобы задать значения для столбцов типа BLOB.
NULL
Значение NULL
не означает "никакие данные" и отличается от
значений типа 0
для числовых типов или пустой строки для типов
строковых. Подробности в разделе "
11.5.3 Проблемы со значениями NULL
".
NULL
может представляться как \N
при
использовании импортирования текстового файла или экспортных форматов
(LOAD DATA INFILE
, SELECT ... INTO OUTFILE
).
Подробности в разделе "8.4.9 Синтаксис
LOAD DATA INFILE
".
Имена для баз данных, таблиц, индексов, столбцов и псевдонимов задаются по общим правилам в MySQL.
Обратите внимание, что правила изменились, начиная с MySQL Version 3.23.6, когда авторы представили цитирование идентификаторов (имена баз данных, таблиц и столбцов) с помощью апострофа (`). Двойная кавычка (") также будет работать, чтобы цитировать идентификаторы, если Вы выполняетесь в ANSI-режиме. Подробности в разделе "1.4.3 Запуск MySQL в ANSI-режиме".
Идентификатор | Максимальная длина | Допустимые символы |
База данных | 64 | Любые символы, допустимые в имени каталога, кроме / или .. |
Таблица | 64 | Любые символы, допустимые в имени файла, кроме / или .. |
Столбец | 64 | Все символы. |
Псевдоним | 255 | Все символы. |
Обратите внимание, что в дополнение к вышеупомянутому, Вы не можете иметь в идентификаторе символы цитирования, а также ASCII(0) или ASCII(255).
Обратите внимание, что, если идентификатор представляет собой ограниченное
слово или содержит специальные символы, Вы должны всегда цитировать его с
`
:
SELECT * from `select` where `select`.id > 100;
В предыдущих версиях MySQL правила для имен были следующими:
--default-character-set
в mysqld
.
Рекомендуется, чтобы Вы не использовали имена, подобные 1e
потому, что выражение вроде 1e+1
неоднозначно. Это может
интерпретироваться как выражение 1e+1
или как число
1e+1
.
В MySQL Вы можете обратиться к столбцу, используя любую из следующих форм:
Ссылка на столбец | Значение |
col_name | Столбец col_name из любой
таблицы, используемой в запросе, содержащем это имя. |
tbl_name.col_name | Столбец col_name
из таблицы tbl_name текущей базы данных. |
db_name.tbl_name.col_name | Столбец
col_name из таблицы tbl_name базы данных
db_name . Эта форма доступна в MySQL Version 3.22 или позже. |
`column_name` | Столбец, который является ключевым словом или содержит специальные символы. |
Вы не должны определять префикс tbl_name
или
db_name.tbl_name
для столбца в инструкции, если ссылка
однозначна. Например, есть таблицы t1
и t2
, каждая
содержит столбец c
, и Вы получаете c
командой
SELECT
, которая использует t1
и t2
. В
этом случае c
неоднозначен потому, что он не уникален среди
таблиц, используемых в инструкции, так что Вы должны указать, что Вы имеете
в виду: t1.c
или t2.c
. Точно так же, если Вы
получаете данные из таблицы t
в базе данных db1
и
из таблицы t
в базе данных db2
, Вы должны
обратиться к столбцам в тех таблицах как db1.t.col_name
и
db2.t.col_name
.
Синтаксис .tbl_name
означает таблицу tbl_name
в текущей базе данных. Этот синтаксис
принят для ODBC-совместимости потому, что некоторые ODBC-программы используют
имена таблиц с префиксом-точкой (.).
В MySQL базы данных и таблицы соответствуют каталогам и файлам внутри тех каталогов. Следовательно, чувствительность операционной системы определяет чувствительность к регистру имен таблицы и базы данных. Это означает, что имена баз данных и таблиц чувствительны к регистру в Unix и нечувствительны в Windows. Подробности в разделе "1.4.1 MySQL-расширения для ANSI SQL92".
ОБРАТИТЕ ВНИМАНИЕ: Несмотря на отсутствие чувствительности
к регистру имен баз данных и таблиц в Windows, СУБД все же такое различие
делает. Так что в рамках одного запроса надо использовать одно и то же имя.
Например, этот запрос не сработает из-за одновременного применения
my_table
и MY_TABLE
:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
Имена столбца нечувствительны к регистру символов во всех случаях.
Псевдонимы для таблиц чувствительны к регистру. Например, этот запрос не
сработает из-за одновременного применения a
и A
:
mysql> SELECT col_name FROM tbl_name AS a WHERE a.col_name = 1 OR A.col_name = 2;
Псевдонимы для столбцов нечувствительны к регистру.
Если Вы имеете проблему при запоминании используемых имен таблиц, примите непротиворечивое соглашение, типа всегда создавать базы данных и таблицы, использующих имена нижнего регистра.
Один способ избежать этой проблемы состоит в том, чтобы запустить
mysqld
с опцией -O lower_case_table_names=1
. По
умолчанию эта опция установлена в 1 под Windows и в 0 под Unix.
Если lower_case_table_names
равен 1, MySQL преобразует все
имена таблицы в строчные буквы. Обратите внимание, что, если Вы изменяете
эту опцию, Вы должны сначала преобразовать Ваши старые имена таблиц в
строчные буквы перед запуском сервера mysqld
.
MySQL поддерживает поточно-зависимые переменные с синтаксисом
@variablename
. Имя переменной может состоять из
алфавитно-цифровых символов из текущего набора символов, а также из
_, $ и ..
Переменные не должны быть инициализированы. Они содержат NULL
по умолчанию и могут сохранять целое число, реальное или строковое значение.
Все переменные для потока будут освобождены, когда поток завершится.
Вы можете устанавливать переменную через вызов SET
:
SET @variable = {integer expression|real expression|string expression} [,@variable= ...].
Вы можете также устанавливать переменную в выражении
@variable:=expr
:
select @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3; +----------------------+------+------+------+ | @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 | +----------------------+------+------+------+ | 5 | 5 | 1 | 4 | +----------------------+------+------+------+
Здесь надо использовать синтаксис :=
потому, что
=
был зарезервирован для сравнений.
Переменные пользователя могут применяться там, где позволяются выражения.
Обратите внимание, что это в настоящее время не включает использование в
контекстах, где явно требуется число, например, в предложении
LIMIT
вызова SELECT
, или в предложении IGNORE
number LINES
в инструкции LOAD DATA
.
ОБРАТИТЕ ВНИМАНИЕ: В инструкции SELECT
каждое выражение вычислено только тогда, когда оно послано пользователю. Это
означает, что в HAVING
, GROUP BY
или ORDER
BY
Вы не можете обратиться к выражению, которое включает переменные,
которые установлены в SELECT
. Например, следующая инструкция НЕ
будет работать как ожидается:
SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;
Причина: @aa
будет содержать не значение текущей строки, а
значение id
предыдущей принятой строки.
Сервер MySQL поддерживает стили комментариев # до конца
строки
, -- до конца строки
и /* в строке или в
нескольких строках */
:
mysql> select 1+1; # Этот комментарий продолжается до конца строки. mysql> select 1+1; -- Этот тоже. mysql> select 1 /* это комментарий, встроенный в строку */ + 1; mysql> select 1+ /* Это комментарий, занимающий несколько строк. */ 1;
Обратите внимание, что стиль комментария --
требует, чтобы Вы
имели по крайней мере один пробел после --
!
Хотя сервер понимает синтаксис комментария, имеются некоторые ограничения
на путь, которым клиент mysql
анализирует комментарии
/* ... */
:
mysql
в интерактивном
режиме, Вы можете крепко запутаться с приглашением командной строки, которое
меняется с mysql>
на '>
или на
">
.
Эти ограничения применяются, когда Вы выполняете mysql
в
интерактивном режиме и тогда, когда Вы помещаете команды в файл и сообщаете,
чтобы mysql
читал ввод из этого файла командой
mysql < some-file
.
MySQL не поддерживает ANSI SQL стиль комментария `--'. Подробности в разделе "1.4.4.8 `--' как начало комментария".
Пробемы возникают при попытке создать таблицу с именами столбцов, которые
используют имена типов или функций, встроенных в MySQL, подобно
TIMESTAMP
или GROUP
. Вам позволяют делать это
(например, ABS
позволенное имя столбца), но пробелы между именем
функции и ( при использовании функций, чьи имена также являются
именами столбцов, не допускаются.
Следующие слова явно зарезервированы в MySQL. Большинство их запрещается
ANSI SQL92 для имен таблицы или столбца (например, group
).
Несколько слов зарезервированы потому, что MySQL нуждается в них и (в
настоящее время) использует синтаксический анализатор yacc
:
action | add |
aggregate | all |
alter | after |
and | as |
asc | avg |
avg_row_length | auto_increment |
between | bigint |
bit | binary |
blob | bool | both
| by |
cascade | case |
char | character |
change | check |
checksum | column |
columns | comment |
constraint | create |
cross | current_date |
current_time | current_timestamp |
data | database |
databases | date |
datetime | day |
day_hour | day_minute |
day_second | dayofmonth |
dayofweek | dayofyear |
dec | decimal |
default | delayed |
delay_key_write | delete |
desc | describe |
distinct | distinctrow |
double | drop |
end | else | escape
| escaped |
enclosed | enum |
explain | exists |
fields | file |
first | float |
float4 | float8 |
flush | foreign |
from | for | full
| function |
global | grant |
grants | group |
having | heap |
high_priority | hour |
hour_minute | hour_second |
hosts | identified |
ignore | in | index
| infile |
inner | insert |
insert_id | int |
integer | interval |
int1 | int2 |
int3 | int4 | int8
| into |
if | is | isam
| join |
key | keys | kill
| last_insert_id |
leading | left | length
| like |
lines | limit | load
| local |
lock | logs | long
| longblob |
longtext | low_priority |
max | max_rows |
match | mediumblob |
mediumtext | mediumint |
middleint | min_rows |
minute | minute_second |
modify | month |
monthname | myisam |
natural | numeric | no
| not |
null | on | optimize
| option |
optionally | or | order
| outer |
outfile | pack_keys |
partial | password |
precision | primary |
procedure | process |
processlist | privileges |
read | real |
references | reload |
regexp | rename |
replace | restrict |
returns | revoke |
rlike | row | rows
| second |
select | set | show
| shutdown |
smallint | soname |
sql_big_tables | sql_big_selects |
sql_low_priority_updates | sql_log_off
| sql_log_update | sql_select_limit
|
sql_small_result | sql_big_result
| sql_warnings | straight_join |
starting | status |
string | table |
tables | temporary |
terminated | text |
then | time | timestamp
| tinyblob |
tinytext | tinyint |
trailing | to |
type | use | using
| unique |
unlock | unsigned |
update | usage |
values | varchar |
variables | varying |
varbinary | with | write
| when |
where | year | year_month
| zerofill |
Следующие символы (из таблицы выше) отвергнуты ANSI SQL, но позволены MySQL как имена столбца/таблицы. Это потому, что некоторые из них представляют собой очень естественные и удобные имена, и много людей уже использовали их в работе:
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
Несмотря на то, что данная работа ориентирована на пользователей пакета, иногда им требуется выполнять простые административные задачи, например, резервирование и восстановление баз данных. Сложными делами, понятно, должен заниматься выделенный администратор, но иногда он может доверить выполнение простых задач достаточно квалифицированному пользователю.
Поскольку таблицы MySQL сохранены как файлы, просто делайте копию. Чтобы
получать непротиворечивую копию, скомандуйте LOCK TABLES
на
релевантных таблицах и дополните это командой FLUSH TABLES
для
них, дабы все данные были гарантированно сброшены на диск. Подробности по
этим командам есть в разделах
"9.7.2 Синтаксис LOCK TABLES/UNLOCK
TABLES
" и "4.8 Синтаксис
FLUSH
". Вам нужна только блокировка записи. Это позволяет
другим потокам продолжать делать запросы к таблицам в то время, как Вы
делаете копию файлов в каталоге баз данных. Команда FLUSH TABLE
необходима, чтобы гарантировать, что все активные индексные страницы записаны
на диск прежде, чем Вы запускаете процесс копирования.
Если Вы хотите делать копию уровня SQL из таблицы, Вы можете использовать
SELECT INTO OUTFILE
или BACKUP TABLE
. Подробности в
разделах "8.1 Синтаксис SELECT
" и "4.2 Синтаксис BACKUP
TABLE
".
Другой способ поддержать базу данных состоит в том, чтобы использовать
программу mysqldump
или скрипт mysqlhotcopy
.
Подробности в разделах
"12.5 mysqldump, Дамп структур таблиц и
данных" и "12.6 mysqlhotcopy,
Копирование баз данных и таблиц MySQL".
shell> mysqldump --tab=/path/to/some/dir --opt --fullили
shell> mysqlhotcopy database /path/to/some/dirВы можете также просто копировать все файлы таблицы (*.frm, *.MYD и *.MYI), пока сервер что-нибудь не модифицирует. Скрипт
mysqlhotcopy
использует этот метод.
mysqld
запущен, остановите его, а
затем запустите с опцией --log-update[=file_name]
. Подробнее об
этой опции можно узнать в разделе "4.9.3
Файл регистрации модификаций". Файлы протоколов предоставляют Вам
информацию относительно того, что изменилось со времени
последнего вызова mysqldump
.Если Вы должны восстановить что-либо, попробуйте восстанавливать Ваши
таблицы, используя REPAIR TABLE
или myisamchk -r
.
Это эффективно в 99.9% случаев. Если myisamchk
ничего хорошего
не сделал, попробуйте следующую процедуру (это будет работать только, если Вы
запустили MySQL с опцией --log-update
):
mysqldump
.
shell> mysqlbinlog hostname-bin.[0-9]* | mysqlЕсли Вы используете файл регистрации модификации, Вы можете использовать:
shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql
ls
используется, чтобы получить все журналы модификации в
правильном порядке.
Вы можете также делать выборочные копии: SELECT * INTO OUTFILE
file_name FROM tbl_name
и восстанавливать их: LOAD DATA INFILE
file_name REPLACE ...
. Чтобы избежать двойных записей, Вам нужен
PRIMARY KEY
или UNIQUE
в таблице. Ключевое слово
REPLACE
заменяет старые записи на новые, когда новая запись
дублирует старую запись на уникальном значении ключа.
Если Вы получаете проблемы эффективности при создании копий на Вашей системе, можно решить их установкой репликации и созданием копий на подчиненной системе вместо главной. Это задачи администратора.
Если Вы используете файловую систему Veritas, Вы можете делать следующее:
FLUSH TABLES WITH READ LOCK
mount vxfs
snapshot
.
UNLOCK TABLES
BACKUP TABLE
BACKUP TABLE tbl_name[,tbl_name...] TO '/path/to/backup/directory'
Эта команда делает копию всех файлов таблицы в резервный каталог, что
является минимумом, необходимым, чтобы восстановить ее. Сейчас это работает
только для таблиц MyISAM
. Для них копируются файлы
.frm
(определение) и .MYD
(данные). Индексный файл
может быть восстановлен из этих двух.
Перед использованием этой команды, пожалуйста, ознакомьтесь с разделом "4.1 Резервирование баз данных".
Пока таблица резервируется, она блокируется. Если нужно резервировать
сразу несколько таблиц, выполните команду LOCK TABLES
для каждой
таблицы в этой группе.
Команда возвращает таблицу со следующими столбцами:
Столбец | Значение |
Table | Имя таблицы |
Op | Обязательно ``backup'' |
Msg_type | Одно из status , error ,
info или warning . |
Msg_text | Собственно сообщение. |
Обратите внимание, что команда BACKUP TABLE
доступна только в
MySQL версии 3.23.25 и старше.
RESTORE TABLE
RESTORE TABLE tbl_name[,tbl_name...] FROM '/path/to/backup/directory'
Восстанавливает таблицу из копии, которая была сделана с помощью
BACKUP TABLE
. Существующие таблицы не будут перезаписаны, если
Вы попробуете восстанавливать существующую таблицу, получите ошибку.
Восстановление занимает больше времени, чем резервирование из-за
необходимости сгенерировать индексный файл. Чем больше имеется ключей, тем
дольше система будет его строить. Также, как и BACKUP TABLE
, эта
функция работает только с таблицами MyISAM
.
Команда возвращает таблицу со следующими столбцами:
Столбец | Значение |
Table | Имя таблицы |
Op | Обязательно ``restore'' |
Msg_type | Одно из status , error ,
info или warning . |
Msg_text | Собственно сообщение. |
CHECK TABLE
CHECK TABLE tbl_name[,tbl_name...] [option [option...]] option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED
CHECK TABLE
работает только с таблицами типа
MyISAM
. На них данная команда эквивалентна
myisamchk -m table_name
.
Если Вы не определяете опций, используется MEDIUM
.
Данная команда проверяет таблицу на ошибки. Для таблиц типа
MyISAM
модифицируется статистика ключа. Команда возвращает
таблицу со следующими столбцами:
Столбец | Значение |
Table | Имя таблицы. |
Op | Обязательно ``check''. |
Msg_type | Одно из status , error ,
info или warning . |
Msg_text | Собственно сообщение. |
Обратите внимание, что Вы можете получать много строк информации для
каждой проверенной таблицы. Последняя строка будет иметь тип Msg_type
status
и значение OK
, если все хорошо. Если ответов
OK
или Not checked
нет, Вы должны выполнить ремонт
таблицы. Сообщение Not checked
говорит о том, что для данной
таблицы TYPE
сообщил MySQL, что там не было никакой
потребности проверять таблицу.
Различные типы проверки:
Тип | Значение |
QUICK | Не просматривать строки, чтобы проверить неправильные связи. |
FAST | Проверить только те таблицы, которые не были закрыты правильно. |
CHANGED | Проверить только те таблицы, которые не были закрыты правильно, и те, которые изменились со времен последней проверки. |
MEDIUM | Сканировать строки для проверки правильности удаленных связей. Это также вычисляет контрольную сумму ключа для строк и проверяет ее правильность. |
EXTENDED | Выполнить полную проверку всех ключей для всех строк в таблице. Это гарантирует, что таблица на 100% непротиворечива, но требует много времени! |
Для динамических таблиц MyISAM
запущенная проверка будет
всегда использовать опцию MEDIUM
. Для статических строк не
выполняется просмотр строки для режимов QUICK
и
FAST
, поскольку строки очень редко разрушаются.
Вы можете объединять параметры проверки:
CHECK TABLE test_table FAST QUICK;
Это предписывает провести быструю проверку на таблице, если она не была закрыта правильно.
ОБРАТИТЕ ВНИМАНИЕ: в ряде случаев
CHECK TABLE
изменяет таблицу! Это случается, если таблица
отмечена как 'corrupted' (повреждена) или 'not closed properly' (не закрыта
правильно), но команда CHECK TABLE
не нашла проблем в таблице. В
этой ситуации CHECK TABLE
отметит таблицу как ok.
Если таблица разрушена, то наиболее вероятное, что проблема находится в индексах, а не в части данных. Все приведенные выше типы проверки тестируют индексы и должны таким образом найти большинство ошибок.
Если Вы хотите только проверить таблицу, Вы не должны использовать никакие
параметры проверки или опцию QUICK
. Последний должен
использоваться, когда Вы спешите и можете позволить пропустить то малое число
ошибок, которое QUICK
не находит. Например, это ошибка в файле
данных. В большинстве случаев MySQL, при нормальном использовании, должен сам
найти любую ошибку в файле данных. Если это случается, таблица будет отмечена
как 'разрушено', тогда таблица не сможет использоваться, пока ошибка не
восстановлена, чтобы не развалить данные окончательно.
FAST
и CHANGED
обычно предназначены, чтобы
использоваться из скрипта (например, из cron), если Вы хотите проверять
таблицу время от времени. В большинстве случаев FAST
имеет
приоритет перед CHANGED
.
EXTENDED
должен использоваться после того, как Вы выполнили
нормальную проверку, но все еще получаете странные ошибки из таблицы, когда
MySQL пробует модифицировать строку или найти строку по ключу (это ОЧЕНЬ
маловероятно, если нормальная проверка прошла спокойно!).
Некоторые вещи, сообщаемые проверкой таблиц, не могут быть исправлены в автоматическом режиме:
Найденная строка, где столбец auto_increment имеет значение 0
.
Это означает, что Вы имеете в таблице строку, где столбец индекса
auto_increment
содержит значение 0. Можно создать такую
конструкцию командой UPDATE
.
Это не ошибка само по себе, но может вызывать проблему, если Вы сбрасываете
таблицу в дамп, а потом восстановите ее оттуда или скомандуете
ALTER TABLE
на таблице. В этом случае столбец auto_increment
изменит значение, согласно правилам auto_increment, что может вызвать
проблемы подобно ошибке дублирования ключа.
Избавиться от предупреждения можно, только выполнив инструкцию
UPDATE
, чтобы установить столбец к некоторому другому значению
(не 0).REPAIR TABLE
REPAIR TABLE tbl_name[,tbl_name...] [QUICK] [EXTENDED]
REPAIR TABLE
тоже работает только на таблицах типа
MyISAM
и аналогичен вызову myisamchk -r table_name
.
Обычно Вам никогда не придется выполнять эту команду, но в случае ошибок
Вы, очень вероятно, вернете все Ваши данные из таблицы MyISAM с помощью
команды REPAIR TABLE
. Если Ваши таблицы разрушаются, Вы должны
попробовать нахйти причину этого! Подробности по этому вопросу есть в разделе
"11.4.1 Что делать, если MySQL рухнул".
REPAIR TABLE
восстанавливает разрушенную таблицу. Команда
возвращает таблицу со следующими столбцами:
Столбец | Значение |
Table | Имя таблицы |
Op | Обязательно ``repair'' |
Msg_type | Одно из status , error ,
info или warning . |
Msg_text | Собственно сообщение. |
Обратите внимание, что Вы можете получать много строк информации для
каждой восстановленной таблицы. Последняя будет иметь тип Msg_type
status
и значение OK
, если все в порядке. Если значение
OK
так и не появилось, Вы должны попробовать восстанавливать
таблицу с помощью myisamchk -o
, поскольку REPAIR
TABLE
еще не выполняет все параметры myisamchk
. В
ближайшем будущем планируется сделать ее более гибкой.
Если задан QUICK
, MySQL пробует делать REPAIR
только для индексного дерева.
Если Вы используете EXTENDED
, MySQL создаст индекс по строкам
вместо того, чтобы создать индекс одновременно с сортировкой: это может быть
лучше, чем сортировка по ключам фиксированной длины, если Вы имеете длинные
ключи типа char()
, которые сжимаются очень хорошо.
OPTIMIZE TABLE
OPTIMIZE TABLE tbl_name[,tbl_name]...
OPTIMIZE TABLE
должен использоваться, если Вы удалили большую
часть таблицы, или если Вы сделали много изменений для таблицы со строками
переменных длин (таблицы, которые имеют VARCHAR
,
BLOB
или TEXT
). Удаленные записи поддерживаются в
связанном списке, и при последующем использовании операций
INSERT
повторно применяются старые позиции записей. Вы можете
использовать OPTIMIZE TABLE
, чтобы освободить неиспользуемое
место и дефрагментировать файл данных.
Сейчас OPTIMIZE TABLE
применим только к таблицам типов
MyISAM и BDB
. Для таблиц типа BDB
OPTIMIZE TABLE
в настоящее время отображается на вызов
ANALYZE TABLE
. Подробности об этом вызове в разделе
"4.7 Синтаксис ANALYZE TABLE
".
Вы можете оптимизировать и другие типы таблиц запуском mysqld
с опциями --skip-new
или --safe-mode
, но в этом
случае OPTIMIZE TABLE
превратится в вызов ALTER
TABLE
.
OPTIMIZE TABLE
работает следующим образом:
OPTIMIZE TABLE
для таблиц типа MyISAM
эквивалентен вызову myisamchk --quick --check-changed-tables
--sort-index --analyze
.
Обратите внимание, что таблица будет блокирована в течение всего времени
работы команды OPTIMIZE TABLE
!
ANALYZE TABLE
ANALYZE TABLE tbl_name[,tbl_name...]
Анализирует и сохраняет распределение ключей для таблицы. Во время
процесса анализа таблица будет блокирована с доступом только на чтение. Это
работает на таблицах типов MyISAM
и BDB
.
Это эквивалентно вызову myisamchk -a
.
MySQL использует сохраненное распределение ключей, чтобы решить, в каком порядке таблицы должны быть соединены, когда выполняется объединение.
Команда возвращает таблицу со следующими столбцами:
Столбец | Значение |
Table | Имя таблицы |
Op | Обязательно ``analyze'' |
Msg_type | Одно из status , error ,
info или warning . |
Msg_text | Собственно сообщение. |
Вы можете проверять сохраненное распределение ключей командой SHOW
INDEX
. Подробности в разделе
"4.10.1 Получение информации о базах
данных, таблицах, столбцах и индексах".
Если таблица не изменилась после последней команды ANALYZE
TABLE
, она не будет проанализирована снова.
FLUSH
FLUSH flush_option [,flush_option]
Вы должны использовать команду FLUSH
, если Вы хотите очищать
внутренние кэши MySQL. Для выполнения FLUSH
Вы должны иметь
право RELOAD.
flush_option
может быть любой из следующего списка:
HOSTS | Освобождает ведущие таблицы кэша. Вы
должны это сделать, если некоторые из Ваших хостов изменяют IP, или если Вы
получили сообщение об ошибке "Host ... is blocked ". Когда в
строке для данного компьютера происходит больше, чем
max_connect_errors ошибок за время связи с сервером, MySQL
приходит к выводу, что что-то пошло неправильно, и блокирует компьютер.
Подробности в разделе "11.2.4 Ошибка
Host '...' is blocked . Вы можете запустить
mysqld с опцией -O max_connection_errors=999999999 ,
чтобы избежать этого сообщения об ошибке. |
LOGS | Закрывает и вновь открывает все журналы.
Если Вы определили журнал модификаций или двоичный журнал без расширения,
номер расширения журнала будет увеличен на один относительно предыдущего
файла. Если Вы использовали расширение в имени файла, MySQL закроет и вновь
откроет журнал модификаций. Это эквивалентно посылке на сервер
mysqld сигнала SIGHUP . |
PRIVILEGES | Перезагружает привилегии из таблиц в
базе данных mysql . |
TABLES | Закрывает все открытые таблицы. |
[TABLE|TABLES] table_name [,table_name...] |
Применяет предыдущую команду только к заданным таблицам. |
TABLES WITH READ LOCK | Закрывает все открытые
таблицы и блокирует все таблицы для всех баз данных с доступом только на
чтение, пока не будет выполнена команда UNLOCK TABLES . Это очень
удобный способ получить резервную копию, если Вы имеете файловую систему,
подобную Veritas. |
STATUS | Сбрасывает большинство переменных состояния к нулю. Используется при отладке запроса. |
Вы можете также обращаться к каждой из команд, показанных выше с помощью
утилиты mysqladmin
, используя команды flush-hosts
,
flush-logs
, reload
или flush-tables
.
KILL
KILL thread_id
Каждое подключение к mysqld
выполняется в отдельном процессе.
Вы можете видеть запущенные процессы командой SHOW PROCESSLIST
и уничтожать процесс командой KILL thread_id
.
Если Вы имеете привилегию process, Вы можете видеть и уничтожать все процессы. Иначе Вы можете видеть и уничтожать только Ваши собственные процессы.
Вы можете также использовать команды mysqladmin processlist
и
mysqladmin kill
, чтобы исследовать и уничтожать процессы.
При вызове KILL
для процесса устанавливается флаг kill
flag
.
В большинстве случаев может требоваться некоторое время для того, чтобы
процесс уничтожился, поскольку флаг kill flag
может быть
проверен только в специфических интервалах:
SELECT
, ORDER BY
и GROUP
BY
флажок будет проверен после чтения блока строк. Если он установлен,
инструкция будет прервана.
ALTER TABLE
флаг будет проверен прежде, чем
каждый блок строк считается из первоначальной таблицы. Если он установлен,
команда будет прервана, а временная таблица удалена.
UPDATE TABLE
и DELETE TABLE
,
флажок будет проверен после каждого чтения блока и после каждого обновления
или удаления строки. Если он установлен, инструкция будет прервана. Обратите
внимание, что, если Вы не используете транзакции, сделанные в таблице
изменения не будут отменены!
GET_LOCK()
прервется с NULL
.
INSERT DELAYED
быстренько сбросят на диск все
строки, которые у них лежат в памяти и завершатся.
Locked
), блокировка таблицы будет быстро прервана.
write
, запись немедленно прерывается с сообщением об
ошибке переполнения диска.SHOW
SHOW DATABASES [LIKE wild] SHOW [OPEN] TABLES [FROM db_name] [LIKE wild] SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE wild] SHOW INDEX FROM tbl_name [FROM db_name] SHOW TABLE STATUS [FROM db_name] [LIKE wild] SHOW STATUS [LIKE wild] SHOW VARIABLES [LIKE wild] SHOW LOGS SHOW [FULL] PROCESSLIST SHOW GRANTS FOR user SHOW CREATE TABLE table_name SHOW MASTER STATUS SHOW MASTER LOGS SHOW SLAVE STATUS
SHOW
обеспечивает информацию относительно баз данных, таблиц,
столбцов или информацию состояния сервера. Если используется часть
LIKE wild
, строка wild
может быть строкой, которая
использует групповые символы SQL % и _.
Вы можете использовать db_name.tbl_name
как вариант для
tbl_name FROM db_name
. Эти две инструкции эквивалентны:
mysql> SHOW INDEX FROM mytable FROM mydb; mysql> SHOW INDEX FROM mydb.mytable;
SHOW DATABASES
вносит в список базы данных на сервере
MySQL. Вы можете также получать этот список, используя команду
mysqlshow
.
SHOW TABLES
вносит в список таблицы в заданной базе данных.
Вы можете также получать этот список, используя команду
mysqlshow db_name
.
ОБРАТИТЕ ВНИМАНИЕ: Если пользователь не имеет привилегий
для таблицы, соответствующая таблица не будет обнаруживаться в выводе
SHOW TABLES
или mysqlshow db_name
.
SHOW OPEN TABLES
вносит в список таблицы, которые являются в
настоящее время открытыми в кэше таблиц. Поле Comment
сообщает
сколько раз таблица кэшируется (cached
) и используется
(in_use
).
SHOW COLUMNS
вносит в список столбцы в данной таблице. Если
Вы определяете опцию FULL
, Вы также получите привилегии, которые
Вы имеете для каждого столбца. Если типы столбцов отличны от ожидаемых, они
будут основаны на инструкции CREATE TABLE
, заметьте, что MySQL
иногда сам изменяет типы столбца. Подробности в разделе
"7.3.1 Тихие изменения
спецификации столбца".
Инструкция DESCRIBE
обеспечивает информацию, подобную
SHOW COLUMNS
. Подробности в разделе
"9.1.2 Синтаксис DESCRIBE
(получение информации о столбцах)".
SHOW FIELDS
является синонимом для SHOW COLUMNS
,
а SHOW KEYS
синонимом для SHOW INDEX
. Вы можете
также вносить в список столбцы таблицы или индексы с помощью команд
mysqlshow db_name tbl_name
или
mysqlshow -k db_name tbl_name
.
SHOW INDEX
возвращает индексную информацию в формате, который
очень походит на вызов SQLStatistics
в ODBC. Следующие столбцы
всегда будут возвращены:
Столбец | Назначение |
Table | Имя таблицы. |
Non_unique | 0, если индекс не может содержать дубликаты. |
Key_name | Имя индекса. |
Seq_in_index | Номер последовательности столбца в индексе, начиная с 1 (не с 0!). |
Column_name | Имя столбца. |
Collation | Как столбец сортируется в индексе. В
MySQL это может иметь варианты `A' (по возрастанию) или
NULL (не сортируемый). |
Cardinality | Число уникальных значений в индексе.
Это модифицируется запуском isamchk -a . |
Sub_part | Число индексированных символов, если
столбец только частично индексирован. NULL если весь ключ
индексирован в полном объеме. |
Comment | Различные замечания. Пока это сообщает, является ли индекс полнотекстовым (FULLTEXT) или нет. |
Обратите внимание, что, поскольку Cardinality
будет
рассчитано, основываясь на статистике, сохраненной как целые числа, оно не
обязательно точно для маленьких таблиц.
SHOW TABLE STATUS
SHOW TABLE STATUS [FROM db_name] [LIKE wild]
SHOW TABLE STATUS
(новинка в Version 3.23) работает подобно
SHOW STATUS
, но обеспечивает много информации относительно
каждой таблицы. Вы можете также получать этот список, используя команду
mysqlshow --status db_name
. Следующие столбцы возвращены:
Столбец | Зачем он нужен |
Name | Имя таблицы. |
Type | Тип таблицы. |
Row_format | Формат хранения строки (фиксированный, динамический или сжатый). |
Rows | Число строк. |
Avg_row_length | Средняя длина строки. |
Data_length | Длина файла данных. |
Max_data_length | Максимальная длина файла данных. |
Index_length | Длина индексного файла. |
Data_free | Число распределенных, но не используемых байт. |
Auto_increment | Следующее значение auto_increment. |
Create_time | Когда таблица была создана. |
Update_time | Когда файл данных был в последний раз модифицирован. |
Check_time | Когда таблица была в последний раз проверена на ошибки. |
Create_options | Дополнительные параметры,
используемые с CREATE TABLE . |
Comment | Комментарий, используемый при создании таблицы (или информация о том, почему MySQL не может обращаться к информации по данной таблицы). |
Таблицы InnoDB
сообщат свободное пространство в ней через
поле комментария таблицы.
SHOW STATUS
SHOW STATUS
обеспечивает информацию состояния сервера (подобно
mysqladmin extended-status
). Вывод походит на показанное ниже,
хотя формат и числа будут другими:
+--------------------------+------------+ | Variable_name | Value | +--------------------------+------------+ | Aborted_clients | 0 | | Aborted_connects | 0 | | Bytes_received | 155372598 | | Bytes_sent | 1176560426 | | Connections | 30023 | | Created_tmp_disk_tables | 0 | | Created_tmp_tables | 8340 | | Created_tmp_files | 60 | | Delayed_insert_threads | 0 | | Delayed_writes | 0 | | Delayed_errors | 0 | | Flush_commands | 1 | | Handler_delete | 462604 | | Handler_read_first | 105881 | | Handler_read_key | 27820558 | | Handler_read_next | 390681754 | | Handler_read_prev | 6022500 | | Handler_read_rnd | 30546748 | | Handler_read_rnd_next | 246216530 | | Handler_update | 16945404 | | Handler_write | 60356676 | | Key_blocks_used | 14955 | | Key_read_requests | 96854827 | | Key_reads | 162040 | | Key_write_requests | 7589728 | | Key_writes | 3813196 | | Max_used_connections | 0 | | Not_flushed_key_blocks | 0 | | Not_flushed_delayed_rows | 0 | | Open_tables | 1 | | Open_files | 2 | | Open_streams | 0 | | Opened_tables | 44600 | | Questions | 2026873 | | Select_full_join | 0 | | Select_full_range_join | 0 | | Select_range | 99646 | | Select_range_check | 0 | | Select_scan | 30802 | | Slave_running | OFF | | Slave_open_temp_tables | 0 | | Slow_launch_threads | 0 | | Slow_queries | 0 | | Sort_merge_passes | 30 | | Sort_range | 500 | | Sort_rows | 30296250 | | Sort_scan | 4650 | | Table_locks_immediate | 1920382 | | Table_locks_waited | 0 | | Threads_cached | 0 | | Threads_created | 30022 | | Threads_connected | 1 | | Threads_running | 1 | | Uptime | 80380 | +--------------------------+------------+
Переменные состояния, перечисленные выше, имеют следующие значения:
Переменная | Значение |
Aborted_clients | Число подключений, прерванных потому, что клиент не закрыл подключение правильно. Подробности в разделе "11.2.9 Ошибки связи/прерванные соединения". |
Aborted_connects | Число попыток соединиться с сервером MySQL, которые потерпели неудачу. Подробности в разделе "11.2.9 Ошибки связи/прерванные соединения". |
Bytes_received | Число байт, полученных с клиентов. |
Bytes_sent | Число байт, посланных клиентам. |
Connections | Число попыток подключения к серверу MySQL. |
Created_tmp_disk_tables | Число неявных временных таблиц на диске, созданных при выполнении инструкций. |
Created_tmp_tables | Число неявных временных таблиц в памяти, созданных при выполнении инструкций. |
Created_tmp_files | Сколько временных файлов
создал mysqld . |
Delayed_insert_threads | Число отсроченных потоков драйвера вставки в использовании. |
Delayed_writes | Число строк, записанных со
INSERT DELAYED . |
Delayed_errors | Число строк, записанных со
INSERT DELAYED , для которых произошла ошибка (вероятно, двойной
ключ (duplicate key ) был использован). |
Flush_commands | Число выполненных команд
FLUSH . |
Handler_delete | Сколько раз строка была удалена из таблицы. |
Handler_read_first | Сколько раз первая запись
читалась из индекса. Если это значение высоко, предполагается, что сервер
делал много полных просмотров индекса, например, SELECT col1 FROM
foo , считая, что col1 индексирован. |
Handler_read_key | Число запросов на чтение строки, основанных на ключе. Если это значение высоко, это значит, что Ваши запросы и таблицы были правильно индексированы. |
Handler_read_next | Число запросов на чтение следующей строки в порядке ключа. Это значение будет увеличено, если Вы запрашиваете индексный столбец с ограничением диапазона. Это также будет увеличено, если Вы делаете индексный просмотр. |
Handler_read_rnd | Число запросов на чтение строк, основанных на фиксированной позиции. Это значение будет высоким, если Вы делаете много запросов, которые требуют сортировки результата. |
Handler_read_rnd_next | Число запросов на чтение следующей строки в файле данных. Это значение будет высоким, если Вы делаете много просмотров таблицы. Вообще это предполагает, что Ваши таблицы не были правильно индексированы, или что Ваши запросы не используют индексы. |
Handler_update | Число запросов на модификацию строк в таблице. |
Handler_write | Число запросов на вставку строки в таблицу. |
Key_blocks_used | Число используемых блоков в кэше ключа. |
Key_read_requests | Число запросов на чтение блока ключа из кэша. |
Key_reads | Число физических чтений блока ключа с диска, а не из кэша. |
Key_write_requests | Число запросов на запись блока ключа в кэш. |
Key_writes | Число физических записей блока ключа на диск, а не в кэш. |
Max_used_connections | Максимальное число подключений в использовании одновременно. |
Not_flushed_key_blocks | Число блоков ключей в кэше ключа, которые изменились, но не сброшены на диск. |
Not_flushed_delayed_rows | Число строк, ждущих
записи в очередях запросов INSERT DELAY . |
Open_tables | Число таблиц, которые являются открытыми. |
Open_files | Число файлов, которые являются открытыми. |
Open_streams | Число потоков, которые являются открытыми (используемыми, главным образом, для протоколирования). |
Opened_tables | Число таблиц, которые были открыты. |
Select_full_join | Число объединений без ключей (должно быть 0). |
Select_full_range_join | Число объединений, где использовали поиск диапазона по таблице ссылок. |
Select_range | Число объединений, где использовали диапазоны в первой таблице. Это обычно не критическое, даже если это большое. |
Select_scan | Число объединений, где просмотрели первую таблицу. |
Select_range_check | Число объединений без ключей, где проверяем использование ключа после каждой строки (должно быть 0). |
Questions | Число запросов, посланных серверу. |
Slave_open_temp_tables | Число временных таблиц, в настоящее время открытых подчиненным процессом. |
Slow_launch_threads | Число потоков, которым
понадобилось для установления соединения больше, чем
slow_launch_time . |
Slow_queries | Число запросов, которые заняли
больше, чем long_query_time . |
Sort_merge_passes | Число объединений,
потребовавших сортировки. Если это значение большое, Вы должны рассмотреть
увеличение sort_buffer . |
Sort_range | Число сортировок с диапазонами. |
Sort_rows | Число сортируемых строк. |
Sort_scan | Число сортировок выполненных, просматривая таблицу. |
Table_locks_immediate | Сколько раз блокировка таблицы применялась сразу. Доступно после версии 3.23.33. |
Table_locks_waited | Сколько раз блокировка таблицы не могла быть применена сразу и пришлось ждать. Если это значение высоко, и Вы имеете проблемы с эффективностью, Вы должны сначала оптимизировать Ваши запросы, а затем или разделить таблицу, или использовать репликацию. Доступно после 3.23.33. |
Threads_cached | Число потоков в кэше. |
Threads_connected | Сколько в настоящее время открыто подключений. |
Threads_created | Число потоков созданных, чтобы обработать подключения. |
Threads_running | Число потоков, которые сейчас не бездействуют. |
Uptime | Сколько секунд сервер уже работает. |
Некоторые комментарии относительно вышеупомянутого:
Opened_tables
велико, то переменная
table_cache
, вероятно, слишком маленькая.
key_reads
велико, то переменная key_cache
,
вероятно, слишком маленькая. Коэффицент кэширования может быть вычислен по
формуле: key_reads
/key_read_requests
.
Handler_read_rnd
велико, то Вы, вероятно, имеете много
запросов, которые требуют, чтобы MySQL просматривал целые таблицы, или Вы
имеете объединения, которые не используют ключи правильно.
Threads_created
велико, то следует увеличить переменную
thread_cache_size
.SHOW VARIABLES
SHOW VARIABLES [LIKE wild]
SHOW VARIABLES
показывает значения некоторых переменных
системы MySQL. Вы можете также получить эту информацию, используя команду
mysqladmin variables
.
Вывод походит на показанное ниже, хотя формат и числа будут иными:
+-------------------------+---------------------------+ | Variable_name | Value | +-------------------------+---------------------------+ | ansi_mode | OFF | | back_log | 50 | | basedir | /my/monty/ | | bdb_cache_size | 16777216 | | bdb_log_buffer_size | 32768 | | bdb_home | /my/monty/data/ | | bdb_max_lock | 10000 | | bdb_logdir | | | bdb_shared_data | OFF | | bdb_tmpdir | /tmp/ | | binlog_cache_size | 32768 | | concurrent_insert | ON | | connect_timeout | 5 | | datadir | /my/monty/data/ | | delay_key_write | ON | | delayed_insert_limit | 100 | | delayed_insert_timeout | 300 | | delayed_queue_size | 1000 | | flush | OFF | | flush_time | 0 | | have_bdb | YES | | have_innodb | YES | | have_raid | YES | | have_ssl | NO | | init_file | | | interactive_timeout | 28800 | | join_buffer_size | 131072 | | key_buffer_size | 16776192 | | language | /my/monty/share/english/ | | large_files_support | ON | | log | OFF | | log_update | OFF | | log_bin | OFF | | log_slave_updates | OFF | | long_query_time | 10 | | low_priority_updates | OFF | | lower_case_table_names | 0 | | max_allowed_packet | 1048576 | | max_binlog_cache_size | 4294967295 | | max_connections | 100 | | max_connect_errors | 10 | | max_delayed_threads | 20 | | max_heap_table_size | 16777216 | | max_join_size | 4294967295 | | max_sort_length | 1024 | | max_tmp_tables | 32 | | max_write_lock_count | 4294967295 | | myisam_recover_options | DEFAULT | | myisam_sort_buffer_size | 8388608 | | net_buffer_length | 16384 | | net_read_timeout | 30 | | net_retry_count | 10 | | net_write_timeout | 60 | | open_files_limit | 0 | | pid_file | /my/monty/data/donna.pid | | port | 3306 | | protocol_version | 10 | | record_buffer | 131072 | | query_buffer_size | 0 | | safe_show_database | OFF | | server_id | 0 | | skip_locking | ON | | skip_networking | OFF | | skip_show_database | OFF | | slow_launch_time | 2 | | socket | /tmp/mysql.sock | | sort_buffer | 2097116 | | table_cache | 64 | | table_type | MYISAM | | thread_cache_size | 4 | | thread_stack | 65536 | | tmp_table_size | 1048576 | | tmpdir | /tmp/ | | version | 3.23.29a-gamma-debug | | wait_timeout | 28800 | +-------------------------+---------------------------+
Каждая опция описана ниже. Значения для буферных размеров, длин и размеров
стека даны в байтах. Вы можете определять значения с суффиксами
`K' или `M', чтобы указать килобайты или мегабайты.
Например, 16M
указывает 16 мегабайтов. Регистр символов суффикса
не имеет значения: 16M
и 16m
эквивалентны.
ansi_mode
.
ON
, если mysqld
запущен с опцией
--ansi
. Подробности в разделе
"1.4.3 Запуск MySQL в режиме ANSI".
back_log
back_log
указывает, сколько
запросов могут быть сложены в стек в течение этого короткого времени прежде,
чем MySQL на мгновение остановит ответы на новые запросы. Вы должны увеличить
это только, если Вы ожидаете большое количество подключений за короткий
периоде времени (сервер работает интенсивно).
Другими словами, это значение задает размер слушающей очереди для входящих
подключений TCP/IP. Ваша операционная система имеет собственное ограничение
размера этой очереди. В Unix man-страница listen(2)
должна
иметь большее количество деталей. Проверьте документацию на Вашу ОС для
выяснения максимального значения для этой переменной. Попытка устанавливать
back_log
выше, чем это ограничение операционной системы, будет
неэффективна, хотя и безопасна.
basedir
--basedir
.
bdb_cache_size
BDB
-таблиц. Если Вы не используете таблицы BDB
, Вы
должны запустить mysqld
с опцией --skip-bdb
, чтобы
не тратить впустую память для этого кэша.
bdb_log_buffer_size
BDB
-таблиц. Если Вы не используете таблицы BDB
, Вы
должны запустить mysqld
с опцией --skip-bdb
, чтобы
не тратить впустую память для этого кэша.
bdb_home
--bdb-home
.
bdb_max_lock
bdb: Lock table is out of available locks
или Got error 12 from ...
, когда Вы делаете длинные транзакции,
или когда mysqld
должен исследовать много строк, чтобы
вычислить и обработать запрос.
bdb_logdir
--bdb-logdir
.
bdb_shared_data
ON
, если Вы используете --bdb-shared-data
.
bdb_tmpdir
--bdb-tmpdir
.
binlog_cache_size
.
BEGIN/COMMIT/ROLLBACK
".
character_set
character_sets
concurrent_inserts
ON
(значение по умолчанию), MySQL позволит Вам
использовать INSERT
на таблицах системы MyISAM
в то
же самое время, когда Вы выполняете на них запросы SELECT
.
Вы можете выключить эту опцию запуском mysqld
с параметрами
--safe
или --skip-new
.
connect_timeout
mysqld
ждет подключения перед
ответом Bad handshake
.
datadir
--datadir
.
delay_key_write
delay_key_write
в CREATE TABLE
. Это означает, что
буфер ключей для таблиц с этой опцией не будет сбрасываться на каждой
индексной модификации, а только когда таблица будет закрыта. Это ускорит
работу по записи, но Вы должны добавить автоматическую проверку всех таблиц
командой myisamchk --fast --force
. Обратите внимание, что, если
Вы запускаете mysqld
с опцией
--delay-key-write-for-all-tables
, это означает, что все таблицы
будут обрабатываться так, как будто они были созданы с опцией
delay_key_write
. Вы можете очищать этот флажок, запуская
mysqld
с параметрами --skip-new
или
--safe-mode
.
delayed_insert_limit
delayed_insert_limit
строк, драйвер
INSERT DELAYED
проверит, имеется ли любая задержка инструкций
SELECT
. Если так, это позволяет им выполниться перед
продолжением работ с таблицей.
delayed_insert_timeout
INSERT DELAYED
должен ждать инструкции
INSERT
перед своим завершением.
delayed_queue_size
INSERT DELAYED
. Если очередь заполняется, любой пользователь,
который вызвал INSERT DELAYED
, будет ждать до появления
свободного места в очереди.
flush
ON
, если MySQL был запущен с опцией --flush
.
flush_time
flush_time
секунд все таблицы будут закрыты (чтобы освободить
ресурсы и сбросить данные на диск). Я рекомендую эту опцию только на Win95,
Win98 или на системах, где Вы имеете очень небольшое количество ресурсов.
have_bdb
YES
, если mysqld
поддерживает таблицы Berkeley
DB. DISABLED
, если использован параметр
--skip-bdb
.
have_innodb
YES
, если mysqld
поддерживает таблицы InnoDB.
DISABLED
, если использован параметр --skip-innodb
.
have_raid
YES
, если mysqld
поддерживает опцию
RAID
.
have_ssl
YES
, если mysqld
поддерживает SSL (шифрование)
по протоколу клиент/сервер.
init_file
--init-file
при запуске
сервера. Это файл инструкций SQL, которые Вы хотите всегда выполнять при
каждом запуске сервера.
interactive_timeout
CLIENT_INTERACTIVE
для
mysql_real_connect()
. См. также wait_timeout
.
join_buffer_size
key_buffer_size
key_buffer_size
как раз и задает размер буфера, используемого
для индексных блоков. Увеличьте это значение, чтобы улучшить индексную
обработку. Но если Вы сделаете его слишком большим (больше, чем 50% общей
памяти?), Ваша система может начать использовать своп и стать ДЕЙСТВИТЕЛЬНО
медленной. Не забудьте, что поскольку MySQL не кэширует чтение данных, Вы
должны оставить некоторый участок памяти для кэша файловой системы ОС.
Вы можете проверять эффективность буфера ключей выполнением show
status
и изучением переменных Key_read_requests
,
Key_reads
, Key_write_requests
и
Key_writes
. Коэффициент Key_reads/Key_read_request
обычно должен быть < 0.01. Key_write/Key_write_requests
обычно близко к 1, если Вы используете обычное обновление/удаление, но может
быть намного меньше, если Вы имеете тенденцию делать модификации, которые
воздействуют на много данных сразу, или если Вы используете
delay_key_write
. Подробности в разделе
"4.10 Синтаксис SHOW
".
Чтобы получить заметное ускорение при записи многих строк сразу,
используйте LOCK TABLES
. Подробности в разделе
"9.2.2 Синтаксис LOCK
TABLES/UNLOCK TABLES
".
language
large_file_support
mysqld
компилировался с параметрами для поддержки
больших файлов.
locked_in_memory
mysqld
был блокирован в памяти опцией
--memlock
log
log_update
log_bin
log_slave_updates
long_query_time
Slow_queries
будет увеличен. Если Вы используете
--log-slow-queries
, запрос будут регистрироваться в файле
регистрации медленных запросов.
lower_case_table_names
max_allowed_packet
net_buffer_length
байт, но может вырасти до
max_allowed_packet
байт, когда необходимо. Это значение по
умолчанию маленькое, но позволяет захватывать большие (возможно,
неправильные) пакеты. Вы должны увеличить это значение, если используете
большие столбцы BLOB
. Он должно быть столь же большим как самый
крупный BLOB
, который Вы хотите использовать. Текущий протокол
ограничивает max_allowed_packet
размером 16M.
max_binlog_cache_size
max_binlog_size
max_connections
mysqld
.
Подробности в разделе "11.2.5
Ошибка Too many connections
".
max_connect_errors
FLUSH HOSTS
.
max_delayed_threads
INSERT DELAYED
. Если Вы попробуете вставлять данные в новую
таблицу после того, как все потоки INSERT DELAYED
будут заняты,
строка будет вставлена, как будто атрибут DELAYED
не был
определен вовсе, то есть немедленно.
max_heap_table_size
max_join_size
max_join_size
, возвращают ошибку. Установите это значение, если
Ваши пользователи имеют тенденцию выполнять объединения, которые испытывают
недостаток предложения WHERE
, занимают много времени или
возвращают миллионы строк.
max_sort_length
BLOB
или TEXT
(только первые
max_sort_length
байтов из каждого значения реально используются,
остальное игнорируется вообще).
max_user_connections
max_tmp_tables
max_write_lock_count
myisam_recover_options
--myisam-recover
.
myisam_sort_buffer_size
REPAIR
или при создании индексов с помощью CREATE
INDEX
или ALTER TABLE
.
myisam_max_extra_sort_file_size
.
myisam_max_sort_file_size
REPAIR
,
ALTER TABLE
или LOAD DATA INFILE
. Если размер файла
больше, чем это значение, индекс будет создан через кэш ключа, который
является более медленным. ОБРАТИТЕ ВНИМАНИЕ, что этот
параметр задан в мегабайтах!
net_buffer_length
max_allowed_packet
байт.
net_read_timeout
write_timeout
. См. также
slave_read_timeout
.
net_retry_count
FreeBSD
, поскольку там внутренние прерывания посланы всем
серверным процессам чтения.
net_write_timeout
open_files_limit
mysqld
использует это значение, чтобы
резервировать описатели файла для применения с setrlimit()
. Если
это значение = 0, mysqld
резервирует
max_connections*5
или max_connections+table_cache*2
(используется большее из этих значений) число файлов. Вы должны попробовать
увеличивать это значение, если mysqld
выдает Вам ошибку
'Too many open files'.
pid_file
--pid-file
.
port
--port
.
protocol_version
record_buffer
record_rnd_buffer
record_buffer
.
query_buffer_size
safe_show_databases
skip_show_databases
.
server_id
--server-id
.
skip_locking
mysqld
использует внешнюю блокировку.
skip_networking
skip_show_databases
SHOW DATABASES
, если
пользователь не имеет привилегии PROCESS_PRIV
. Это может
улучшить защиту. См. также safe_show_databases
.
slave_read_timeout
slow_launch_time
Slow_launch_threads
будет увеличен.
socket
sort_buffer
ORDER BY
или GROUP BY
. Подробности в разделе
"11.4.4 Где MySQL
хранит временные файлы".
table_cache
mysqld
.
MySQL нуждается в двух описателях файла для каждой уникальной открытой
таблицы. Вы можете проверять, должны ли Вы увеличить кэш таблицы, анализируя
переменную Opened_tables
. Подробности в разделе
"4.10 Синтаксис SHOW
".
Удостоверьтесь, что Ваша операционная система может обрабатывать число
описателей файла, подразумеваемых установкой table_cache
. Если
table_cache
слишком велико, MySQL может исчерпать описатели
файла и начать сбоить.
table_type
thread_cache_size
thread_cache_size
потоков. Все новые потоки
сначала принимаются из кэша и только, когда кэш пуст, создаются новые. Эта
переменная может увеличиваться, чтобы улучшить эффективность, если Вы имеете
много новых подключений.
thread_concurrency
mysqld
вызовет thr_setconcurrency()
с этим значением. thr_setconcurrency()
разрешает прикладной
программе давать системе управления данные относительно желательного числа
потоков, которые должны быть выполнены в одно и то же время.
thread_stack
crash-me
, зависят от этого значения. Значение по
умолчанию достаточно большое для нормальной работы.
timezone
tmp_table_size
MyISAM
на диске.
Увеличьте значение tmp_table_size
, если Вы делаете много
продвинутых запросов GROUP BY
, и Вы имеете много памяти.
tmpdir
version
wait_timeout
interactive_timeout
.Раздел, который описывает настройку MySQL, содержит некоторую информацию относительно того, как настроить вышеупомянутые переменные.
SHOW LOGS
SHOW LOGS
показывает Вам информацию относительно состояния
существующих журналов. В настоящее время этот вызов отображает только
информацию относительно журналов Berkeley DB.
File
показывает полный путь к журналу.
Type
показывает тип журнала (BDB
для журналов
типа Berkeley DB).
Status
показывает состояние журнала (FREE
если
файл может быть удален, или IN USE
если файл необходим
подсистеме транзакций).SHOW PROCESSLIST
SHOW PROCESSLIST
показывает Вам, которые процессы работают.
Вы можете также получать эту информацию, используя команду mysqladmin
processlist
. Если Вы имеете привилегию process, Вы
можете видеть все процессы. Иначе Вы можете видеть только Ваши собственные
процессы. Если Вы не используете опцию FULL
, то только первые
100 символов каждого запроса будут показаны. Подробности в разделе
"4.9 Синтаксис KILL
".
Эта команда очень полезна, если Вы получаете сообщения об ошибках 'too
many connections' и хотите выяснить, что происходит. MySQL резервирует одно
подключение дополнительно для пользователя с привилегией
Process_priv
, чтобы гарантировать, что Вы всегда способны ко
входу в систему и ее проверке (эта ситуация не дает такую же привилегию всем
Вашим пользователям).
SHOW GRANTS
SHOW GRANTS FOR user
вносит в список команды, который должны
быть выданы, чтобы дублировать права пользователя. Например:
mysql> SHOW GRANTS FOR root@localhost; +---------------------------------------------------------------------+ | Grants for root@localhost | +---------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION | +---------------------------------------------------------------------+
SHOW CREATE TABLE
Показывает инструкцию CREATE TABLE
, которая создаст
данную таблицу. Например:
mysql> show create table t\G *************************** 1. row *************************** Table: t Create Table: CREATE TABLE t ( id int(11) default NULL auto_increment, s char(60) default NULL, PRIMARY KEY (id) ) TYPE=MyISAM
MySQL может, начиная с версии 3.22, читать заданные по умолчанию параметры запуска для клиентов и сервера из файлов опций.
MySQL читает заданные по умолчанию параметры из следующих файлов (в Unix):
Имя файла | Зачем он нужен |
/etc/my.cnf | Глобальные опции для всех |
DATADIR/my.cnf | Опции для сервера |
defaults-extra-file | Файл, определенный через --defaults-extra-file=# |
~/.my.cnf | Специфические для пользователей опции |
DATADIR
представляет собой каталог данных MySQL (обычно
/usr/local/mysql/data для бинарного дистрибутива или
/usr/local/var для установки из исходников). Обратите внимание,
что это тот каталог, который был определен в конфигурации, а не указан в
опции --datadir
при запуске mysqld
! Параметр
--datadir
не имеет никакого эффекта в то время, когда сервер
ищет файлы опций потому, что он их ищет прежде, чем обрабатывает любые
параметры командной строки.
MySQL читает заданные по умолчанию параметры из следующих файлов (только в ОС Windows):
Имя файла | Зачем он нужен |
windows-system-directory\my.ini | Глобальные опции |
C:\my.cnf | Глобальные опции |
C:\mysql\data\my.cnf | Опции для сервера |
Обратите внимание, что в Windows Вы должны определить все пути с
/
вместо \
. Если Вы используете \
, Вы
должны определить это дважды, поскольку \
символ ESC в MySQL.
MySQL пробует читать файлы опции в порядке, перечисленном выше. Если есть несколько файлов настроек, используется опция, определенная в том файле, который читается позже. Параметры, определенные в командной строке имеют приоритет над параметрами, определенными в любом файле опций. Некоторые параметры могут быть определены, используя системные переменные. Параметры, определенные в командной строке или в файлах опций имеют приоритет над значением соответствующей системной переменной.
Следующие программы поддерживают файлы опций: mysql
,
mysqladmin
, mysqld
, mysqldump
,
mysqlimport
, mysql.server
, myisamchk
и
myisampack
.
Вы можете использовать файлы опций, чтобы определить любую длинную опцию,
которую программа поддерживает! Выполните программу с параметром
--help
, чтобы получить список доступных параметров.
Файл опций может содержать строки следующих форм:
#comment
[group]
group
представляет собой имя программы или группы, для
которой Вы хотите устанавливать параметры. После строки группы любая строка
option
или set-variable
обращается к именованной
группе, пока не будет достигнут конец файла опций или другая строка группы.
option
--option
в командной строке.
option=value
--option=value
в командной строке.
set-variable = variable=value
--set-variable variable=value
в командной
строке. Этот синтаксис должен использоваться, чтобы установить переменную
mysqld
.Группа client
позволяет Вам определять параметры, которые
обращаются ко всей клиентуре MySQL (но не к mysqld
). Это
самая подходящая группа, чтобы определить в ней пароль, который Вы
используете, чтобы соединиться с сервером. Но удостоверьтесь, что файл опций
читаем и перезаписываем только Вами.
Обратите внимание, что для параметров и значений все конечные и начальные пробелы автоматически удалены. Вы можете использовать управляющие последовательности \b, \t, \n, \r, \\ и \s в Вашей строке (\s==пробел).
Имеется типичный глобальный файл опций:
[client] port=3306 socket=/tmp/mysql.sock [mysqld] port=3306 socket=/tmp/mysql.sock set-variable = key_buffer_size=16M set-variable = max_allowed_packet=1M [mysqldump] quick
Имеется типичный файл опций пользователя:
[client] # The following password will be sent to all standard MySQL clients password=my_password [mysql] no-auto-rehash set-variable=connect_timeout=2 [mysqlhotcopy] interactive-timeout
Если Вы имеете дистрибутив с исходниками, Вы найдете,
что типовые файлы конфигурации называются my-xxxx.cnf в каталоге
support-files. А вот в двоичном дистрибутиве смотрите в каталоге
DIR/support-files, где DIR
задает имя пути к каталогу
установки MySQL (обычно /usr/local/mysql). В настоящее время
имеются типовые файлы конфигурации для маленькой, средней, большой и очень
большой системы. Вы можете копировать my-xxxx.cnf в Ваш основной
каталог (переименуйте копию в .my.cnf), чтобы экспериментировать.
Вся клиентура MySQL, которая поддерживает файлы опций, использует и следующие параметры:
--no-defaults | Не читать любые файлы опций. |
--print-defaults | Печатать имя программы и все параметры, которые ей передаются. |
--defaults-file=full-path-to-default-file | Использовать только данный файл конфигурации. |
--defaults-extra-file=full-path-to-default-file | Читать этот файл конфигурации после глобального файла опций, но перед чтением файла настроек пользователя. |
Обратите внимание, что вышеупомянутые параметры должны быть первыми в
командной строке, чтобы они работали! Однако, --print-defaults
может использоваться непосредственно после команды
--defaults-xxx-file
.
В скриптах оболочки Вы можете использовать команду my_print_defaults, чтобы анализировать файлы конфигурации:
shell> my_print_defaults client mysql --port=3306 --socket=/tmp/mysql.sock --no-auto-rehash
Вышеупомянутый вывод содержит все параметры для групп client и mysql.
MySQL поддерживает ряд типов столбцов, которые могут быть сгруппированы в три категории: числовые, типы даты и времени и строковые (символьные). Этот раздел сначала дает краткий обзор доступных типов и суммирует требования к памяти для хранения каждого типа столбцов, затем обеспечивает более детальное описание свойств типов в каждой категории. Краткий обзор преднамеренно краток. Ниже следуют более подробные описания, с которыми нужно консультироваться для получения дополнительной информации относительно специфических типов столбцов, типа допустимых форматов значений, которые Вы можете определять.
Типы столбцов, поддерживаемые MySQL, перечислены ниже. Следующие символы кода используются в описаниях:
M
D
M
-2.Квадратные скобки ([ и ]) указывают части спецификаторов типа, которые являются факультативными.
Обратите внимание, что, если Вы определяете для столбца
ZEROFILL
, MySQL автоматически добавит к столбцу атрибут
UNSIGNED
.
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
-128
до 127
. Диапазон значений без знака
от 0
до 255
.
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
-32768
до
32767
. Диапазон без знака от 0
до
65535
.
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
-8388608
до 8388607
. Диапазон значений без знака от 0
до
16777215
.
INT[(M)] [UNSIGNED] [ZEROFILL]
-2147483648
до 2147483647
. Диапазон значений без
знака от 0
до 4294967295
.
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
INT
.
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
-9223372036854775808
до 9223372036854775807
.
Диапазон значений без знака от 0
до
18446744073709551615
.
Некоторые вещи, которые Вы должны знать относительно столбцов типа
BIGINT
:
BIGINT
или DOUBLE
, Вы не должны
использовать большие целые числа без знака, которые имеют значение по модулю
большее, чем 9223372036854775807
(63 бита) за исключением
битовых функций! Если Вы это сделаете, некоторые из последних цифр в
результате могут быть ошибочными из-за округления при преобразовании
BIGINT
в DOUBLE
.
BIGINT
, сохраняя его как строку, в этом случае не будет никакого
промежуточного двойного представления.
BIGINT
.
BIGINT
, когда оба параметра представляют собой значения типа
INTEGER
. Это означает, что, если Вы умножаете два больших целых
числа (или результаты функций, которые возвращают целые числа), Вы можете
получить непредвиденные эффекты, когда результат больше, чем
9223372036854775807
.FLOAT(precision) [ZEROFILL]
precision
) может быть в пределах <=24
, для
числа с одиночной точностью, или между 25 и 53, для числа двойной точности.
Эти типы подобны FLOAT
и DOUBLE
, описанным ниже.
FLOAT(X)
имеет тот же самый диапазон, что и соответствующие типы
FLOAT
и DOUBLE
, но размер отображения и число
десятичных чисел неопределенны. В MySQL Version 3.23 это и есть истинное
значение с плавающей запятой. В старых версиях MySQL
FLOAT(precision)
всегда имеет 2 десятичных числа. Обратите
внимание, что использование типа FLOAT
может создавать Вам
некоторые непредвиденные проблемы, поскольку все вычисления в MySQL всегда
выполнены с двойной точностью. Этот синтаксис предусмотрен
для ODBC-совместимости.
FLOAT[(M,D)] [ZEROFILL]
-3.402823466E+38
до
-1.175494351E-38
, 0
и от
1.175494351E-38
до 3.402823466E+38
. M задает размер
отображения, а D число десятичных чисел. Соответствует FLOAT(X)
,
где X <= 24.
DOUBLE[(M,D)] [ZEROFILL]
-1.7976931348623157E+308
до
-2.2250738585072014E-308
, 0
и от
2.2250738585072014E-308
до 1.7976931348623157E+308
.
M задает размер отображения, а D число десятичных чисел. Соответствует
DOUBLE
без параметра или FLOAT(X)
, где
25 <= X <= 53.
DOUBLE PRECISION[(M,D)] [ZEROFILL]
REAL[(M,D)] [ZEROFILL]
DOUBLE
.
DECIMAL[(M[,D])] [ZEROFILL]
CHAR
: "распакованный" означает, что число
сохранено как строка, используя один символ для каждой цифры значения.
Десятичная отметка и, для отрицательных чисел, знак - не
рассчитана в M (но пробел для них зарезервирован). Если D
=0,
значения не будут иметь никакой десятичной отметки или дробной части.
Максимальный диапазон значений DECIMAL
аналогичен
DOUBLE
, но фактический диапазон для данного столбца
DECIMAL
может быть задан через M
и D
.
Если D
не задано, оно будет установлено в 0. Если же не задано
M
, оно считается равным 10. Обратите внимание, что в MySQL
Version 3.22 аргумент M
должен включать пробел, необходимый для
знака и десятичной отметки.
NUMERIC(M,D) [ZEROFILL]
DECIMAL
.
DATE
1000-01-01
до
9999-12-31
. MySQL отображает значения DATE
в
формате YYYY-MM-DD
, но позволяет Вам назначать значения столбцам
DATE
используя строки или числа.
DATETIME
1000-01-01
00:00:00
до 9999-12-31 23:59:59
. MySQL отображает
значения типа DATETIME
в формате
YYYY-MM-DD HH:MM:SS
, но позволяет Вам назначать значения
столбцам DATETIME
, используя строки или числа.
TIMESTAMP[(M)]
1970-01-01
00:00:00
примерно до 2037
. MySQL отображает значения
типа TIMESTAMP
в форматах YYYYMMDDHHMMSS
,
YYMMDDHHMMSS
, YYYYMMDD
или YYMMDD
, в
зависмости от значения M
: 14
(или пропущено),
12
, 8
или 6
, но позволяет Вам задавать
значения столбцам TIMESTAMP
, используя строки или числа. Столбец
TIMESTAMP
полезен для записи даты и времени операции
INSERT
или UPDATE
потому, что он будет
автоматически установлен к дате и времени самой последней операции, если Вы
не задаете значение самостоятельно. Вы можете также устанавливать его к
текущей дате и времени, назначая значение NULL
.
TIMESTAMP
всегда сохраняется в 4 байтах. Параметр M
воздействует только на то, как отображается столбец TIMESTAMP
.
Обратите внимание, что столбцы TIMESTAMP(X)
при X, равном 8 или
14, являются числами, в то время как другие столбцы TIMESTAMP(X)
представляют собой строки! Это только должно гарантировать, что можно надежно
сбросить таблицу в дамп, а потом восстанавливать ее с этими типами!
TIME
-838:59:59
до
838:59:59
. MySQL отображает значения типа TIME
в
формате HH:MM:SS
, но позволяет Вам задавать значения столбцам
TIME
, используя строки или числа.
YEAR[(2|4)]
1901
до 2155
, 0000
в
формате года с 4 цифрами, и 1970-2069, если Вы используете формат с 2
цифрами (70-69). MySQL отображают значения YEAR
в формате
YYYY
, но позволяет Вам указывать значения столбцам типа
YEAR
, используя строки или числа. Впервые тип YEAR
появился в MySQL Version 3.22.
[NATIONAL] CHAR(M) [BINARY]
M
от 1 до 255 символов. Конечные
пробелы будут удалены, когда значение извлекается из таблицы. Переменные
CHAR
сортируются и сравниваются без учета регистра согласно
заданному по умолчанию набору символов, если не задано ключевое слово
BINARY
. NATIONAL CHAR
(короткая форма
NCHAR
) представляет собой взятый из ANSI SQL способ определить,
что столбец CHAR должен использовать заданный набор символов CHARACTER. Это
значение по умолчанию в MySQL.
CHAR
является сокращением для CHARACTER
. MySQL
позволяет Вам создавать столбец типа CHAR(0)
. Это главным
образом полезно, когда Вы должны обеспечить совместимость с некоторыми
старыми прикладными программами, которые зависят от существования столбца, но
фактически не использует значение. Это также очень удобно, когда Вы
нуждаетесь в столбце, который может брать только 2 значения:
CHAR(0)
, который не определен как NOT NULL
, займет
всего лишь один бит и может принимать только 2 значения: NULL
или ""
.
[NATIONAL] VARCHAR(M) [BINARY]
M
от 1 до 255 символов.
Значения типа VARCHAR
сортируются и сравниваются без учета
регистра согласно заданному по умолчанию набору символов, если не задано
ключевое слово BINARY
. VARCHAR
является сокращением
для CHARACTER VARYING
.
TINYBLOB
TINYTEXT
BLOB
или TEXT
имеют максимальную длину
в 255 (2^8-1) символов.
BLOB
TEXT
BLOB
или TEXT
имеют максимальную длину
в 65535 (2^16-1) символов.
MEDIUMBLOB
MEDIUMTEXT
MEDIUMBLOB
или MEDIUMTEXT
имеют
максимальную длину в 16777215 (2^24-1) символов.
LONGBLOB
LONGTEXT
LONGBLOB
или LONGTEXT
имеют
максимальную длину в 4294967295 (2^32-1) символов. Обратите внимание, что
поскольку протокол клиент-сервер и таблицы MyISAM имеет в настоящее время
ограничение в 16M на пакет связи/строку таблицы, Вы не можете использовать
весь диапазон этого типа.
ENUM('value1','value2',...)
value1
, value2
,
...
, NULL
или специальное значение ошибки
""
. ENUM
может иметь максимум 65535 разных значений.
SET('value1','value2',...)
value1
, value2
, ...
. SET
может иметь максимум 64 члена.MySQL поддерживает все числовые типы ANSI/ISO SQL92. Эти типы включают
точные числовые типы данных (NUMERIC
, DECIMAL
,
INTEGER
и SMALLINT
), а также приблизительные
числовые типы данных (FLOAT
, REAL
и DOUBLE
PRECISION
). Ключевое слово INT
представляет собой синоним
для INTEGER
, а ключевое слово DEC
является
синонимом для DECIMAL
.
Типы NUMERIC
и DECIMAL
выполнены как тот же
самый тип MySQL, как разрешено стандартом SQL92. Они используются для
значений, для которых важно сохранить идеальную точность, например, с
валютными данными. При объявлении столбца одного из этих типов точность и
масштаб могут быть (и обычно бывают) определены, например:
salary DECIMAL(9,2)
В этом примере 9
(точность, precision
)
представляет число значащих десятичных цифр, которые будут сохранены для
значений, а 2
(масштаб, scale
) представляет число
цифр, которые будут сохранены после десятичной отметки. В этом случае,
следовательно, диапазон значений, которые могут быть сохранены в столбце
salary
от -9999999.99
до 9999999.99
.
(MySQL может фактически сохранять числа до 9999999.99
в этом
столбце потому, что не требуется сохранять знак для положительных чисел).
В ANSI/ISO SQL92 синтаксис DECIMAL(p)
эквивалентен
DECIMAL(p,0)
. Точно так же синтаксис DECIMAL
является эквивалентным DECIMAL(p,0)
, где реализации позволяют
менять значение p
. MySQL в настоящее время не поддерживает
никакую из этих различных форм типов данных
DECIMAL
/NUMERIC
. Это не серьезная проблема,
поскольку принципиальные выгоды этих типов происходят от способности
управлять точностью и масштабом явно.
Значения типов DECIMAL
и NUMERIC
сохранены как
строки, в не как двоичные числа с плавающей запятой, чтобы сохранить
десятичную точность значений. Один символ используется для каждой цифры
значения, десятичной отметки (если scale
> 0) и знака
- (для отрицательных чисел). Если scale
равен 0,
значения DECIMAL
и NUMERIC
не содержат никакой
десятичной отметки или дробной части.
Максимальный диапазон значений DECIMAL
и NUMERIC
аналогичен диапазону для DOUBLE
, но фактический диапазон для
данного столбца DECIMAL
или NUMERIC
может быть
ограничен точностью или масштабом для данного столбца. Когда такой столбец
назначен, значение с большим количеством цифр после десятичной отметки, чем
позволяется определенным масштабом, будет округлено до заданного масштаба.
Когда происходит переполнение (столбцу присваивается значение, превышающее
его диапазон), MySQL сохраняет значение, представляющее соответствующий
максимум этого диапазона.
MySQL поддерживает как расширение стандарта ANSI/ISO SQL92 встроенные типы
TINYINT
, MEDIUMINT
и BIGINT
как
перечислено в таблицах выше. Другое расширение поддержано MySQL для
факультативного определения ширины отображения значения в круглых скобках
после основного ключевого слова для типа (например, INT(4)
).
Эта факультативная спецификация ширины используется для вывода значений, чья
ширина меньше, чем ширина, определенная для столбца, но не сдерживает
диапазон значений, которые могут быть сохранены в столбце, или число цифр,
которые будут отображаться для значений, чья ширина превышает заданную. Когда
используется вместе с факультативным атрибутом расширения
ZEROFILL
, дополнение значения по умолчанию пробелами заменено на
нули. Например, для столбца, объявленного как INT(5) ZEROFILL
,
значение 4
превратится в 00004
. Обратите внимание,
что, если Вы сохраняете значения большие, чем ширина отображения в
целочисленном столбце, Вы можете испытывать проблемы, когда MySQL генерирует
временные таблицы для некоторых сложных объединений, поскольку в этих случаях
MySQL полагает, что данные вписывались в первоначальную ширину столбца.
Все встроенные типы могут иметь факультативный (ненормативный) атрибут
UNSIGNED
. Значения без знака могут использоваться, когда Вы
хотите позволять только положительные числа в столбце, и Вы нуждаетесь в
немного большем числовом диапазоне столбца.
Тип FLOAT
используется, чтобы представить приблизительные
числовые типы данных. Стандарт ANSI/ISO SQL92 позволяет факультативную
спецификацию точности (но не диапазон образца) в битах после ключевого слова
FLOAT
в круглых скобках. MySQL-реализация также поддерживает эту
факультативную спецификацию точности. Когда ключевое слово FLOAT
используется для типа столбца без спецификации точности, MySQL применяет
четыре байта, чтобы сохранить значения. Различный синтаксис также поддержан,
с двумя числами, заданными в круглых скобках после ключевого слова
FLOAT
. С этой опцией первое число продолжает представлять
требования к памяти для значения в байтах, а второе определяет число цифр,
которые будут сохранены и отображаться после десятичной отметки (как с
DECIMAL
и NUMERIC
). Когда MySQL нужно сохранить
число для такого столбца с большим количеством цифр после десятичной отметки,
чем определено для столбца, значение будет автоматически округлено, чтобы
устранить лишние цифры.
Типы REAL
и DOUBLE PRECISION
не принимают
спецификации точности. В качестве дополнения к стандарту ANSI/ISO SQL92 MySQL
распознает DOUBLE
как синоним для DOUBLE PRECISION
.
В отличие от требования стандарта, чтобы точность для REAL
была
меньшие, чем используемая для DOUBLE PRECISION
, MySQL реализует
то и другое как 8-байтные double-precision floating-point значения (при
работе не в ANSI mode). Для максимальной мобильности код, требующий
хранение приблизительных числовых значений данных должен использовать
FLOAT
или DOUBLE PRECISION
без спецификации
точности или количества чисел после десятичной точки.
Когда нужно сохранить значение в числовом столбце, которое выходит за диапазон, MySQL отсекает значение к соответствующей границе диапазона и сохраняет возникающее в результате значение.
Например, диапазон столбца INT
от -2147483648
до
2147483647
. Если Вы пробуете вставлять -9999999999
в столбец типа INT
, значение будет усечено к нижей границе
диапазона и сохранено -2147483648
. Точно так же, если Вы
пробуете вставлять 9999999999
, вместо этого будет сохранено
2147483647
.
Если столбец INT
определен как UNSIGNED
, размер
диапазона столбца тот же самый, но произойдет сдвиг значений на
0
и 4294967295
. Если Вы пробуете сохранять
-9999999999
и 9999999999
, значения, сохраненные в
столбце, станут соответственно 0
и 4294967296
.
Преобразования, которые происходят из-за усечения, сообщаются как
``warnings'' для инструкций ALTER TABLE
, LOAD DATA
INFILE
, UPDATE
и многострочного варианта
INSERT
.
Типы даты и времени: DATETIME
, DATE
,
TIMESTAMP
, TIME
и YEAR
. Каждый из них
имеет диапазон допустимых значений, также как и некий ноль, который
используется, когда Вы определяете, действительно, запрещенное значение.
Обратите внимание, что MySQL позволяет Вам сохранять некоторые недопустимые
значения даты, например, 1999-11-31
. Причина этого в том, что
обрабатывать проверку даты ответственность прикладной программы, а не сервера
SQL. Чтобы сделать проверку даты быстрой, MySQL проверяет только то, что
месяц находится в диапазоне 0-12, и день находится в диапазоне 0-31.
Вышеупомянутые диапазоны определены так потому, что MySQL позволяет Вам
сохранять в столбцах DATE
или DATETIME
даты, где
день или месяц нулевой. Это чрезвычайно полезно для прикладных программ,
которые должны сохранить дату рождения, для которой Вы не знаете точную дату.
В этом случае Вы просто сохраняете дату подобно 1999-00-00
или
1999-01-00
. Вы, конечно, не можете получать правильное значение
из функций, подобных DATE_SUB()
или DATE_ADD
, для
таких неправильных дат.
Имеются некоторые общие вещи, которые стоит иметь в виду при работе с типами даты и времени:
98-09-04
).
TIME
урезаются до соответствующей границы. Таблица ниже
показывает нулевые значения каждого типа:
Тип столбца | Нулевое значение |
DATETIME | '0000-00-00 00:00:00'
|
DATE | '0000-00-00' |
TIMESTAMP | 00000000000000 (длина
зависит от размера отображения) |
TIME | '00:00:00' |
YEAR | 0000 |
'0'
или 0
.
NULL
в MyODBC Version 2.50.12 и выше потому,
что ODBC не может обрабатывать такие значения.MySQL непосредственно Y2K-безопасен, но вводимые значения таковыми не явдяются. Любой ввод, содержащий значения года с 2 цифрами, неоднозначен потому, что столетие неизвестно. Такие значения должны интерпретироваться в форму с 4 цифрами потому, что MySQL сохраняет годы, внутренне всегда используя четыре цифры.
Для типов DATETIME
, DATE
, TIMESTAMP
и YEAR
MySQL интерпретирует даты с неоднозначным годом так:
00-69
будут преобразованы в
2000-2069
.
70-99
будут преобразованы в
1970-1999
.Не забудьте, что эти правила обеспечивают только приемлемые предположения относительно того, что Ваши данные означают. Если логика, используемая MySQL, не производит правильные значения, Вы должны обеспечить однозначный ввод, содержащий значения года с 4 цифрами.
ORDER BY
сортирует значения типов
YEAR/DATE/DATETIME
с 2 цифрами правильно.
Обратите внимание также, что некоторые функции, подобно MIN()
и MAX()
, преобразуют TIMESTAMP/DATE
в число. Это
означает, что timestamp с годом с 2 цифрами не будет работать правильно с
этими функциями. Исправление в этом случае должно преобразовать
TIMESTAMP/DATE
к формату года с 4 цифрами или использовать нечто
вроде MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS))
.
DATETIME
, DATE
и TIMESTAMP
Типы DATETIME
, DATE
и TIMESTAMP
связаны. Этот раздел описывает их характеристики и чем они отличаются.
Тип DATETIME
используется, когда Вы нуждаетесь в значениях,
которые содержат информацию о дате и времени. MySQL получает и отображает
значения DATETIME
в формате YYYY-MM-DD HH:MM:SS
.
Поддерживаемый диапазон от 1000-01-01 00:00:00
до
9999-12-31 23:59:59
.
Тип DATE
используется, когда Вы нуждаетесь только в значении
даты, без части времени. MySQL получает и отображает значения
DATE
в формате YYYY-MM-DD
. Поддерживаемый диапазон
от 1000-01-01
до 9999-12-31
.
Тип столбца TIMESTAMP
обеспечивает тип, который Вы можете
использовать, чтобы автоматически отметить операции INSERT
или
UPDATE
текущей датой и временем. Если Вы имеете много столбцов
типа TIMESTAMP
, только первый модифицируется автоматически.
Автоматическое модифицирование первого столбца TIMESTAMP
происходит при любом из условий:
INSERT
или
LOAD DATA INFILE
.
UPDATE
и некотором
другом значении изменений столбца. Обратите внимание, что
UPDATE
, который устанавливает столбец к значению, которое тот
уже имеет, не будет заставлять столбец типа TIMESTAMP
модифицироваться потому, что, если Вы устанавливаете столбец к текущему
значению, MySQL игнорирует модификацию для эффективности.
TIMESTAMP
в
NULL
.Второй и последующие столбцы типа TIMESTAMP
также могут быть
установлены к текущей дате и времени. Только установите столбец в
NULL
или в NOW()
.
Вы можете устанавливать любой столбец TIMESTAMP
к значению
иному, чем текущая дата и время, устанавливая это явно. Это истинно даже для
первого столбца TIMESTAMP
. Вы можете использовать это свойство,
если, например, Вы хотите, чтобы TIMESTAMP
был установлен
к текущей дате и времени, когда Вы создаете строку, но не был изменен всякий
раз, когда строка модифицируется позже:
TIMESTAMP
явно в текущее значение.Значения TIMESTAMP
имеют точность в одну секунду. Значения
отображаются как числа.
Формат, в котором MySQL получает и отображает значения
TIMESTAMP
, зависят от размера отображения, как иллюстрируется
таблицей ниже. Полный формат TIMESTAMP
имеет 14 цифр, но столбцы
могут быть созданы с более короткими размерами отображения:
Тип столбца | Формат отображения |
TIMESTAMP(14) | YYYYMMDDHHMMSS |
TIMESTAMP(12) | YYMMDDHHMMSS |
TIMESTAMP(10) | YYMMDDHHMM |
TIMESTAMP(8) | YYYYMMDD |
TIMESTAMP(6) | YYMMDD |
TIMESTAMP(4) | YYMM |
TIMESTAMP(2) | YY |
Все столбцы типа TIMESTAMP
имеют тот же самый размер памяти,
независимо от размера отображения. Наиболее распространенные размеры: 6, 8,
12 и 14. Вы можете определять произвольный размер при создании таблицы, но
значения 0 или больше, чем 14, будут установлены в 14. Нечетные размеры в
диапазоне от 1 до 13 будут приведены к следующему четному числу.
Вы можете определять значения DATETIME
, DATE
и
TIMESTAMP
, использующие любой из общего набора форматов:
YYYY-MM-DD HH:MM:SS
или YY-MM-DD
HH:MM:SS
. Облегченный синтаксис позволяется: любой символ пунктуации
может использоваться как разделитель между частями даты или частями времени.
Например, 98-12-31 11:30:45
, 98.12.31 11+30+45
,
98/12/31 11*30*45
и 98@12@31 11^30^45
равны.
YYYY-MM-DD
или YY-MM-DD
.
Облегченный синтаксис позволяется и здесь: например, строки
98-12-31
, 98.12.31
, 98/12/31
и
98@12@31
являются эквивалентными.
YYYYMMDDHHMMSS
или
YYMMDDHHMMSS
, при условии, что строка имеет смысл как дата.
Например, 19970523091528
и 970523091528
интерпретируются как 1997-05-23 09:15:28
, но
971122129015
запрещен (это имеет неправильную минутную часть) и
становится 0000-00-00 00:00:00
.
YYYYMMDD
или
YYMMDD
, при условии, что строка имеет смысл как дата. Например,
19970523
и 970523
интерпретируются как
1997-05-23
, но 971332
запрещен (это имеет
неправильную часть месяца) и становится 0000-00-00
.
YYYYMMDDHHMMSS
или YYMMDDHHMMSS
,
при условии, что число имеет смысл как дата. Например,
19830905132800
и 830905132800
интерпретируются как
1983-09-05 13:28:00
.
YYYYMMDD
или YYMMDD
при
условии, что число имеет смысл как дата. Например, 19830905
и
830905
интерпретируются как 1983-09-05
.
DATETIME
, DATE
или
TIMESTAMP
, типа NOW()
или
CURRENT_DATE
.Запрещенные значения DATETIME
, DATE
или
TIMESTAMP
преобразованы в нулевое значение соответствующего типа
(0000-00-00 00:00:00
, 0000-00-00
или
00000000000000
).
Для значений, определенных как строки, которые включают разделители частей
даты, не требуется определять две цифры для значений месяца или дня, которые
являются меньше, чем 10
. 1979-6-9
эквивалентно
1979-06-09
. Точно так же для значений, определенных как строки,
которые включают разделители части времени, необязательно определять две
цифры для значений часа, минут или секунды, которые меньше, чем
10
. 1979-10-30 1:2:3
то же самое, что и
1979-10-30 01:02:03
.
Значения, определенные как числа, должны быть длиной в 6, 8, 12 или 14
цифр. Если число длиной в 8 или 14 цифр, считается, что оно в формате
YYYYMMDD
или YYYYMMDDHHMMSS
, и что год задан
первыми 4 цифрами. Если число длиной в 6 или 12 цифр, считается, что оно в
формате YYMMDD
или YYMMDDHHMMSS
, и что год задан
первыми 2 цифрами. Числа, которые не соответствуют этим длинам, дополняются
нулями до самой близкой длины.
Значения, определенные как
неразграниченные строки интерпретируются, используя их длину как она есть.
Это означает, что Вы не должны использовать строки короче шести символов.
Например, если Вы определяете 9903
, думая, что представите март
1999 года, Вы найдете, что MySQL вставляет ноль для даты в Вашу таблицу. Это
потому, что значения года и месяца 99
и 03
, но
часть дня пропущено, так что значение не является допустимой датой.
Столбцы TIMESTAMP
сохраняют допустимые значения, используя
полную точность, с которой значение было определено, независимо от размера
отображения. Это имеет несколько значений:
TIMESTAMP(4)
или TIMESTAMP(2)
. Иначе, значение не
будет допустимой датой, и будет сохранен 0
.
ALTER TABLE
, чтобы расширить узкий
столбец TIMESTAMP
, будет отображаться та информация, которая
раньше была скрыта.
TIMESTAMP
не уничтожит
информацию, просто меньшее количество информации будет показываться, когда
значения столбца отображаются.
TIMESTAMP
сохранены в полной точности,
единственная функция, которая функционирует непосредственно на основном
сохраненном значении, это UNIX_TIMESTAMP()
. Другие функции
имеют дело с форматируемым значением. Вы не можете использовать функции типа
HOUR()
или SECOND()
, если релевантная часть
значения TIMESTAMP
не включена в форматируемое значение.
Например, часть HH
столбца TIMESTAMP
не
отображается, если размер отображения меньше 10.Вы можете до некоторой степени назначать значения одного типа даты объекту иного типа даты. Однако, может иметься некоторое изменение значения или потери информации:
DATE
объекту
DATETIME
или TIMESTAMP
, часть времени возникающего
в результате значения будет установлена в 00:00:00
потому, что
значение DATE
не содержит информацию для времени.
DATETIME
или
TIMESTAMP
объекту a DATE
, часть времени
возникающего в результате значения удалена потому, что тип DATE
не сохраняет информацию о времени.
DATETIME
, DATE
и
TIMESTAMP
могут быть определены, используя тот же самый набор
форматов, они имеют разный диапазон значений. Например,
TIMESTAMP
не могут быть ранее, чем 1970
, или позже,
чем 2037
. Это означает, что дата типа 1968-01-01
,
которая вполне нормальна для DATETIME
или DATE
,
недопустима для переменной типа TIMESTAMP
и превратится в
0
.Знайте некоторые ловушки при определении значений даты:
10:11:12
могло
бы напоминать значение времени из-за разделителя :, но если оно
используется в контексте даты будет интерпретироваться как год
2010-11-12
. Значение 10:45:15
будет преобразовано в
0000-00-00
потому, что 45
недопустимый месяц.
00-69
преобразованы в
2000-2069
.
70-99
преобразованы в
1970-1999
.TIME
MySQL получает и отображает значения TIME
в формате
HH:MM:SS
(или HHH:MM:SS
для больших значений
часов). Значения TIME
могут располагаться в диапазоне от
-838:59:59
до 838:59:59
. Причина того, что часть
часов может быть настолько большой в том, что тип TIME
может
использоваться не только, чтобы представить время дня (которое должно быть
меньше, чем 24 часа), но также и прошедшее время или интервал времени между
двумя событиями (который может быть намного больше, чем 24 часа).
Вы можете определять значения TIME
разными способами:
D HH:MM:SS.fraction
. Обратите
внимание, что MySQL все же не сохраняет дробную часть для столбца времени.
Можно также использовать один из следующих ослабленных синтаксисов:
HH:MM:SS.fraction
, HH:MM:SS
, HH:MM
,
D HH:MM:SS
, D HH:MM
, D HH
или
SS
. Здесь под D
понимаются дни в пределах 0-33.
HHMMSS
, при условии,
что это имеет смысл как время. Например, 101112
допустимо и
будет воспринято как 10:11:12
, но 109712
из-за
неправильной минутной части превратится в 00:00:00
.
HHMMSS
, при условии, что это имеет смысл
как время. Например, 101112
допустимо и будет воспринято как
10:11:12
. Следующие альтернативные форматы также будут поняты:
SS
, MMSS
, HHMMSS
,
HHMMSS.fraction
. Обратите внимание, что MySQL все же не
сохраняет дробную часть.
TIME
, например,
CURRENT_TIME
.Для значений TIME
, определенных как строки, которые включают
разделитель частей времени, необязательно задавать две цифры для часов,
минут или секунд, которые меньше 10
. Указание 8:3:2
аналогично 08:03:02
.
Будьте внимательны относительно назначения коротких значений
TIME
. Без точки с запятой MySQL интерпретирует значения,
используя предположение, что крайние справа цифры представляют секунды. MySQL
интерпретирует значения TIME
как прошедшее время, а не время
дня. Например, Вы могли задавать 1112
и 1112
как
11:12:00
, но MySQL поймет это как 00:11:12
. Точно
так же 12
и 12
интерпретируются как
00:00:12
. Значения TIME
с точкой с запятой вместо
этого, всегда обрабатываются как время дня. Так 11:12
будет
означать 11:12:00
, но не 00:11:12
.
Значения, которые находятся вне диапазона TIME
, но допустимы
во всем остальном, будут усечены до соответствующей границы диапазона.
Например, -850:00:00
и 850:00:00
превратятся в
-838:59:59
и 838:59:59
.
Недопустимые значения TIME
превратятся в
00:00:00
. Обратите внимание, что так как 00:00:00
представляет собой допустимое значение TIME
, нет никакого
способа понять по сохраненному в таблице 00:00:00
, было ли
первоначальное значение определено как 00:00:00
или нет.
YEAR
Тип YEAR
представляет собой тип с 1 байтом, используемый для
представления лет.
MySQL получает и отображает значения типа YEAR
в формате
YYYY
. Диапазон: от 1901
до 2155
.
Вы можете определять значения YEAR
в форматах:
1901
до
2155
.
1901
до
2155
.
00
до
99
. Значения в диапазонах от 00
до 69
и от 70
до 99
будут преобразованы в значения
YEAR
в диапазонах от 2000
до 2069
и от
1970
до 1999
.
1
до
99
. Значения в диапазонах от 1
до 69
и
от 70
до 99
будут преобразованы в значения
YEAR
в диапазонах от 2001
до 2069
и от
1970
до 1999
. Обратите внимание, что диапазон для
чисел с двумя цифрами немного иной, чем для строк с двумя цифрами потому, что
Вы не можете определять ноль непосредственно как число. Вы должны
определить это как строку 0
(или 00
), или это будет
интерпретироваться как 0000
.
YEAR
, например, NOW()
.Запрещенные значения YEAR
будут преобразованы в
0000
.
Строковыми считаются типы: CHAR
, VARCHAR
,
BLOB
, TEXT
, ENUM
и SET
.
Этот раздел описывает как работу типов, их требования к памяти и как
использовать их в Ваших запросах. Сразу следует отметить, что к строковым
причислены типы, которые в разных языках программирования таковыми не
являются, например, ENUM
и SET
.
CHAR
и VARCHAR
Типы CHAR
и VARCHAR
подобны, но отличаются
способом их хранения и получения.
Длина столбца CHAR
фиксирована и задается, когда Вы создаете
таблицу. Длина может быть любым значением между 1 и 255. В MySQL Version 3.23
длина CHAR
может быть от 0 до 255. Когда значения
CHAR
сохраняются в таблице, они дополняются справа пробелами до
нужной длины. Когда значения CHAR
получены, конечные пробелы
будут автоматически удалены.
Значения в столбцах VARCHAR
представляют собой строки
переменной длины. Вы можете объявлять, что столбец VARCHAR
будет
любой длины между 1 и 255, точно как для столбцов типа CHAR
.
Однако, в отличие от CHAR
, значения VARCHAR
сохранены, используя ровно столько символов, сколько надо, плюс один байт,
чтобы записать длину (аналог типа String в языке Pascal). Значения не
дополняются, вместо этого конечные пробелы будут удалены, когда значения
сохранены в таблице. Это удаление пробелов отличается от спецификации ANSI
SQL, там они остаются.
Если Вы назначаете значение столбцу CHAR
или
VARCHAR
, которое превышает максимальную длину столбца, значение
будет усечено, чтобы поместиться в столбец.
Таблица ниже иллюстрирует различия между двумя типами столбцов, показывая
результат сохранения различных значений в CHAR(4)
и
VARCHAR(4)
:
Значение | CHAR(4) | Для хранения надо | VARCHAR(4) | Для хранения надо |
'' | ' ' | 4 байта |
'' | 1 байт |
'ab' | 'ab ' | 4 байта | 'ab' | 3 байта |
'abcd' | 'abcd' | 4 байта | 'abcd' | 5 байт |
'abcdefgh' | 'abcd' | 4 байта | 'abcd' | 5 байт |
Значения, полученные из столбцов CHAR(4)
и
VARCHAR(4)
, будут те же самые в каждом случае потому, что
конечные пробелы удалены из столбцов CHAR
после поиска.
Значения в столбцах CHAR
и VARCHAR
сортируются и
сравниваются без учета регистра, если атрибут BINARY
не был
определен, когда таблица была создана. Атрибут BINARY
означает,
что значения столбца сортируются и сравниваются с учетом регистра согласно
порядку символов серверной (не клиентской!) машины MySQL. BINARY
не воздействует на то, как столбец будет сохранен или получен.
Атрибут BINARY
липкий. Это означает, что, если столбец,
отмеченный как BINARY
, используется в выражении, все выражение
сравнивается как значение BINARY
.
MySQL может тихо изменять тип столбца CHAR
или
VARCHAR
при создании таблицы. Подробности в разделе
"7.3.1 Тихие изменения
спецификации столбца".
BLOB
и TEXT
BLOB
представляет собой двоичный большой объект, который
может хранить переменное количество данных. Есть четыре типа
BLOB
'ов: TINYBLOB
, BLOB
,
MEDIUMBLOB
и LONGBLOB
, отличающиеся только по
максимальной длине значений, которые они могут хранить.
Четыре типа TEXT
: TINYTEXT
, TEXT
,
MEDIUMTEXT
и LONGTEXT
соответствуют четырем типам
BLOB
и имеют те же самые максимальные длины и требования к
памяти. Единственное различие между типами BLOB
и
TEXT
в том, что сортировка выполняется с учетом регистра для
значений типа BLOB
и без учета регистра для TEXT
.
Если Вы назначаете значение столбцу BLOB
или
TEXT
, которое превышает максимальную длину для типа столбца,
значение будет усечено, чтобы поместиться.
В большинстве случаев Вы можете расценивать столбец TEXT
как
VARCHAR
, который может быть столь большим, как Вы хотите. Точно
так же Вы можете расценивать столбец BLOB
как VARCHAR
BINARY
. Различия в том, что:
BLOB
и
TEXT
, начиная с MySQL Version 3.23.2 и выше. Старые версии MySQL
не поддерживали это.
BLOB
и
TEXT
, когда значения сохранены, в противоположность
VARCHAR
.
BLOB
и TEXT
не могут иметь значений
DEFAULT
.MyODBC определяет значения BLOB
как
LONGVARBINARY
, а значения типа TEXT
как
LONGVARCHAR
.
Поскольку значения BLOB
и TEXT
могут быть
чрезвычайно длинными, Вы можете столкнуться с ограничениями при использовании:
GROUP BY
или
ORDER BY
на столбце типа BLOB
или TEXT
,
Вы должны преобразовать значение столбца в объект фиксированной длины.
Стандартный способ сделать это: функция SUBSTRING
, например:
mysql> select comment from tbl_name,substring(comment,20) as substr ORDER BY substr;Если Вы не сделаете это, только первые
max_sort_length
байт
столбца используются при сортировке. Значение по умолчанию для
max_sort_length
равно 1024, это значение может быть изменено,
используя опцию -O
при запуске сервера mysqld
. Вы
можете группировать на выражении, включающем значения BLOB
или
TEXT
, определяя позицию столбца или используя псевдоним:
mysql> select id,substring(blob_col,1,100) from tbl_name GROUP BY 2; mysql> select id,substring(blob_col,1,100) as b from tbl_name GROUP BY b;
BLOB
или TEXT
определен типом, но самое большое значение, которое Вы можете фактически
передать между клиентом и сервером, зависит от количества доступной памяти и
размера буферов связей. Вы можете изменять размер буфера сообщения, но Вы
должны сделать это на клиенте и на сервере.Обратите внимание, что каждое значение BLOB
или
TEXT
внутренне представляется отдельно распределенным объектом.
Это отличие от всех других типов столбца, для которых память распределена
один раз на столбец, когда таблица открывается.
ENUM
ENUM
представляет собой строковый объект, чье значение обычно
выбрано из списка допустимых значений, которые перечислены явно в
спецификации столбца при создании таблицы.
Значение может также быть пустой строкой (""
) или
NULL
при некоторых обстоятельствах:
ENUM
(то
есть, строку, которая не указана в перечне допустимых значений), взамен будет
вставлена пустая строка как специальное значение ошибки. Эта строка может
отличаться от нормальной пустой строки тем фактом, что эта имеет числовое
значение 0. Подробнее относительно этого позже...
ENUM
объявлен как NULL
, то
NULL
также допустимое значение для столбца, и значением по
умолчанию как раз и будет именно NULL
. Если ENUM
объявлен как NOT NULL
, значением по умолчанию будет первый
элемент из списка дозволенных значений.Каждое значение перечисления имеет индекс:
SELECT
, чтобы найти строки, в
которых были установлены недопустимые для ENUM
значения:
mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
является само NULL
.Например, столбец, определенный как ENUM("one","two","three")
,
может иметь любое из значений, показанных ниже. Индекс каждого значения также
показывается:
Значение | Индекс |
NULL | NULL |
"" | 0 |
"one" | 1 |
"two" | 2 |
"three" | 3 |
Перечисление может иметь максимум 65535 элементов.
Регистр неважен, когда Вы назначаете значения столбцу ENUM
.
Однако, значения, полученные из столбца позже имеют регистр с соответствием
значений, которые использовались, чтобы определить допустимые значения при
создании данной таблицы.
Если Вы получаете ENUM
в числовом контексте, будет возвращен
индекс значения столбца. Например, Вы можете получать числовые значения из
столбца ENUM
подобно этому:
mysql> SELECT enum_col+0 FROM tbl_name;
Если Вы сохраняете число в ENUM
, он обрабатывается как
индекс, и сохраненное значение представляет собой член перечисления с этим
индексом. Однако, это не будет работать с вызовом LOAD DATA
,
который обрабатывает весь свой ввод как строки.
Значения ENUM
сортируются согласно порядку, в котором члены
перечисления были указаны в спецификации столбца. Другими словами, значения
ENUM
сортируются согласно их индексным числам. Например,
"a"
окажется перед "b"
для
ENUM("a","b")
, но "b"
опередит "a"
для
ENUM("b", "a")
. Пустые строки окажутся перед непустыми строками,
а значения NULL
перед всеми другими значениями перечисления.
Если Вы хотите получать все возможные значения для столбца
ENUM
, Вы должны использовать SHOW COLUMNS FROM table_name
LIKE enum_column_name
и анализировать определение ENUM
во
втором столбце вывода.
SET
SET
представляет собой строковый объект, который может иметь
ноль или большее количество значений, каждое из которых должно быть выбрано
из списка допустимых значений, которые перечислены явно в спецификации
столбца при создании таблицы. Значения столбца SET
, которые
состоят из многих значений набора, определены членами, отделяемыми запятыми
(,). Следствие этого: значения членов SET
не могут
самостоятельно содержать запятые.
Например, столбец, определенный как SET("one","two") NOT
NULL
, может иметь любое из этих значений:
"" "one" "two" "one,two"
SET
может иметь максимум 64 различных членов.
MySQL сохраняет значения SET
в цифровой форме, с битом
младшего разряда сохраненного значения, соответствующего первому члену
набора. Если Вы получаете значение SET
в числовом контексте, оно
имеет набор битов, соответствующий членам набора, которые составляют значение
столбца. Например, Вы можете получить числовые значения из столбца
SET
подобно этому:
mysql> SELECT set_col+0 FROM tbl_name;
Если число сохранено в столбце SET
, биты, которые установлены
в двоичном представлении числа, определяют члены набора в значении столбца.
Предположим, что столбец определен как SET("a","b","c","d")
.
Члены имеют следующие разрядные значения:
SET член множества | Десятичное значение | Двоичное значение |
a | 1 | 0001 |
b | 2 | 0010 |
c | 4 | 0100 |
d | 8 | 1000 |
Если Вы назначаете число 9
этому столбцу (в двоичной системе
это будет 1001
), то первый и четвертый члены значения
SET
(то есть, "a"
и "d"
) будут
выбраны, и возникающим в результате значением будет "a,d"
.
Для значения, содержащего больше, чем один элемент SET
, не
имеет значения порядок элементов, в котором они перечислены, когда Вы
вставляете значение. Также не важно, сколько раз данный элемент перечислен в
значении. Когда значение потом будет получено из таблицы, каждый элемент в
нем появится лишь однажды, причем элементы будут перечислены согласно
порядку, в котором они были определены при создании таблицы. Например, если
столбец определен как SET("a","b","c","d")
, то
"a,d"
, "d,a"
и "d,a,a,d,d"
будут
появляться как "a,d"
при получении данных из таблицы.
Значения SET
сортируются в цифровой форме. NULL
расположится перед другими значениями.
Обычно, Вы выполняете SELECT
на столбце SET
,
применяя оператор LIKE
или функцию FIND_IN_SET()
:
mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%'; mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
Но следующее будет также работать:
mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2'; mysql> SELECT * FROM tbl_name WHERE set_col & 1;
Первая из этих инструкций ищет точное соответствие. Вторая ищет значения, содержащие первый член набора.
Если Вы хотите получать все возможные значения для столбца
SET
, Вы должны использовать: SHOW COLUMNS FROM table_name
LIKE set_column_name
и анализировать второй столбец определения.
Для наиболее эффективного использования памяти, попробуйте использовать
наиболее подходящий тип во всех случаях. Например, если целочисленный столбец
будет использоваться для значений в диапазоне между 1
и
99999
, лучшим является тип MEDIUMINT UNSIGNED
.
Точное представление денежных величин обычно является проблемой. В MySQL
Вы должны использовать тип DECIMAL
. Это сохранено как строка,
так что никакая потеря точности не должна произойти. Если точность не слишком
важна, тип DOUBLE
также может быть достаточен.
Для высокой точности, Вы можете всегда преобразовывать данные в
фиксированный тип BIGINT
. Это позволяет Вам делать все
вычисления с целыми числами и преобразовывать результаты обратно в значения с
плавающей запятой только тогда, когда это необходимо.
Чтобы использовать код, написанный для реализаций SQL от других авторов, MySQL отображает типы столбцов как показано в таблице ниже. Эти отображения делают проще перенос определения таблиц:
Чужой тип | Тип в MySQL |
BINARY(NUM) | CHAR(NUM) BINARY |
CHAR VARYING(NUM) | VARCHAR(NUM) |
FLOAT4 | FLOAT |
FLOAT8 | DOUBLE |
INT1 | TINYINT |
INT2 | SMALLINT |
INT3 | MEDIUMINT |
INT4 | INT |
INT8 | BIGINT |
LONG VARBINARY | MEDIUMBLOB |
LONG VARCHAR | MEDIUMTEXT |
MIDDLEINT | MEDIUMINT |
VARBINARY(NUM) | VARCHAR(NUM) BINARY
|
Отображение типа столбца происходит при создании таблицы. Если Вы создаете
таблицу с типами, используемыми другими авторами, а затем выдаете команду
DESCRIBE tbl_name
, MySQL сообщает структуру таблицы,
использующую эквивалентные типы MySQL.
Требования к памяти для каждого из типов столбцов, поддерживаемых MySQL, перечислены ниже по категориям.
Тип столбца | Для хранения надо |
TINYINT | 1 байт |
SMALLINT | 2 байта |
MEDIUMINT | 3 байта |
INT | 4 байта |
INTEGER | 4 байта |
BIGINT | 8 байта |
FLOAT(X) | 4, если X <= 24, или 8, если 25 <= X <= 53 |
FLOAT | 4 байта |
DOUBLE | 8 байта |
DOUBLE PRECISION | 8 байта |
REAL | 8 байта |
DECIMAL(M,D) | M+2 байт, если D >
0, M+1 байт, если D=0 (D +2, если M < D
) |
NUMERIC(M,D) | M+2 байт, если D >
0, M+1 байт, если D=0 (D +2, если M < D
) |
Тип столбца | Для хранения надо |
DATE | 3 байта |
DATETIME | 8 байта |
TIMESTAMP | 4 байта |
TIME | 3 байта |
YEAR | 1 байт |
Тип столбца | Для хранения надо |
CHAR(M) | M байт, 1 <= M
<= 255 |
VARCHAR(M) | L +1 байт, где
L <= M и 1 <= M <= 255 |
TINYBLOB , TINYTEXT | L +1
байт, где L < 2^8 |
BLOB , TEXT | L +2 байта,
где L < 2^16 |
MEDIUMBLOB , MEDIUMTEXT |
L +3 байта, где L < 2^24 |
LONGBLOB , LONGTEXT | L +4
байта, где L < 2^32 |
ENUM('value1','value2',...) | 1 или 2 байта, в зависимости от количества значений перечисления (максимум 65535 значений) |
SET('value1','value2',...) | 1, 2, 3, 4 или 8 байт, в зависимости от числа членов набора (максимум 64 члена) |
Типы
VARCHAR
, BLOB
и TEXT
представляют
собой типы переменной длины, для которых требования к памяти зависят от
фактической длины значения столбца (представлена как L
в
предшествующей таблице). Например, столбец VARCHAR(10)
может
хранить строку с максимальной длиной в 10 символов. Фактическая требуемая
память равна длине строки (L
) плюс 1 байт, чтобы записать длину
строки. Для строки abcd
, L
равно 4, а требования к
памяти равны 5 байтам.
Типы BLOB
и TEXT
требуют 1, 2, 3 или 4 байта,
чтобы записать длину значения столбца, в зависимости от максимальной
возможной длины типа.
Если таблица включает любые столбцы переменной длины, формат записи будет также переменной длины. Обратите внимание, что, когда таблица создана, MySQL может, при некоторых условиях, изменять столбец с типа переменной длины на тип фиксированной длины. Подробности в разделе "7.3.1 Тихие изменения спецификации столбца".
Размер объекта ENUM
определен числом различных значений
перечисления. Один байт используется для перечислений до 255 возможных
значений. Два байта используются для перечислений до 65535 значений.
Подробности в разделе "5.3.3 Тип ENUM
".
Размер объекта SET
определен числом различных членов набора.
Если размер набора равен N
, то объект занимает
(N+7)/8
байт, округленных до 1, 2, 3, 4 или 8 байт.
SET
может иметь максимум до 64 членов. Подробности приведены в
разделе "5.3.4 Тип SET
".
CREATE
,
DROP
, ALTER
CREATE DATABASE
CREATE DATABASE [IF NOT EXISTS] db_name
CREATE DATABASE
создает базу данных с указанным именем.
Правила для допустимых имен баз данных приведены в разделе
"3.2 Имена баз данных, таблиц, индексов,
столбцов и псевдонимов". Ошибка происходит, если база данных уже
существует, и Вы не определяли IF NOT EXISTS
.
Базы данных в MySQL выполнены как каталоги, содержащие файлы, которые
соответствуют таблицам в базе данных. Поскольку нет никаких таблиц в базе
данных, когда она первоначально создана, инструкция CREATE
DATABASE
только создает каталог под каталогом данных MySQL.
Вы можете также создавать базы данных с помощью
программы mysqladmin
. Подробности в разделе
"12 Клиентские скрипты и утилиты
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 |
Все подкаталоги, имена которых состоят из 2 цифр (каталоги
RAID
), также будут удалены.
В MySQL Version 3.22 или позже Вы можете использовать ключевые слова
IF EXISTS
, чтобы предотвратить ошибку, если база
данных не существует.
Вы можете также удалять базы данных с помощью
команды mysqladmin
. Подробности в разделе
"12 Клиентские скрипты и утилиты
MySQL".
CREATE TABLE
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement] create_definition: col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY KEY] [reference_definition] or PRIMARY KEY (index_col_name,...) or KEY [index_name] (index_col_name,...) or INDEX [index_name] (index_col_name,...) or UNIQUE [INDEX] [index_name] (index_col_name,...) or FULLTEXT [INDEX] [index_name] (index_col_name,...) or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...) [reference_definition] or CHECK (expr) type: TINYINT[(length)] [UNSIGNED] [ZEROFILL] or SMALLINT[(length)] [UNSIGNED] [ZEROFILL] or MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL] or INT[(length)] [UNSIGNED] [ZEROFILL] or INTEGER[(length)] [UNSIGNED] [ZEROFILL] or BIGINT[(length)] [UNSIGNED] [ZEROFILL] or REAL[(length,decimals)] [UNSIGNED] [ZEROFILL] or DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL] or FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL] or DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL] or NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL] or CHAR(length) [BINARY] or VARCHAR(length) [BINARY] or DATE or TIME or TIMESTAMP or DATETIME or TINYBLOB or BLOB or MEDIUMBLOB or LONGBLOB or TINYTEXT or TEXT or MEDIUMTEXT or LONGTEXT or ENUM(value1,value2,value3,...) or 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 | MYISAM } or AUTO_INCREMENT = # or AVG_ROW_LENGTH = # or CHECKSUM = {0 | 1} or COMMENT = "string" or MAX_ROWS = # or MIN_ROWS = # or PACK_KEYS = {0 | 1} or PASSWORD = "string" or DELAY_KEY_WRITE = {0 | 1} or ROW_FORMAT= { default | dynamic | fixed | compressed } or RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=# RAID_CHUNKSIZE=# or UNION = (table_name,[table_name...]) or DATA DIRECTORY="directory" or INDEX DIRECTORY="directory" select_statement: [IGNORE | REPLACE] SELECT ... (Some legal select statement)
CREATE TABLE
создает таблицу с заданным именем в текущей базе
данных. Правила для допустимых имен таблицы даны в разделе
"3.2 Имена баз данных, таблиц, индексов,
столбцов и псевдонимов". Ошибка происходит, если не имеется никакой
текущей базы данных, или если таблица уже существует.
В MySQL Version 3.22 или позже имя таблицы может быть определено как
db_name.tbl_name
. Это работает независимо от того, имеется или
нет текущая база данных.
В MySQL Version 3.23 или позже Вы можете использовать ключевое слово
TEMPORARY
, когда Вы создаете таблицу. Временная таблица будет
автоматически удалена, если подключение завершается. Причем, имя связано с
подключением. Это означает, что два различных подключения могут оба
использовать то же самое имя временной таблицы без того, чтобы войти в
противоречие друг с другом или с существующей таблицей с тем же самым именем.
Существующая таблица будет скрыта, пока временная таблица не удалена.
В MySQL Version 3.23 или позже Вы можете использовать ключевые слова
IF NOT EXISTS
, чтобы ошибка не произошла, если таблица уже
существует. Обратите внимание, что не имеется никакой проверки, что структуры
таблиц идентичны.
Каждая таблица tbl_name
представляется некоторыми файлами в
каталоге баз данных. В случае таблиц MyISAM-типа Вы получите:
Файл | Назначение |
tbl_name.frm | Определение таблицы (форма) |
tbl_name.MYD | Данные таблицы |
tbl_name.MYI | Индекс таблицы |
Для получения большего количества информации относительно свойств различных типов столбцов обратитесь к разделу "5 Типы столбцов":
NULL
или NOT NULL
не определены,
столбец обрабатывается, как если бы был определен NULL
.
AUTO_INCREMENT
. Когда Вы вставляете значение NULL
(рекомендуется) или 0
в столбец с атрибутом
AUTO_INCREMENT
, столбец будет установлен в значение
value+1
, где value
представляет собой самое большое
значение для столбца в настоящее время в данной таблице.
AUTO_INCREMENT
-последовательности начинаются с 1
.
Если Вы удаляете строку, содержащую максимальное значение для столбца
AUTO_INCREMENT
, значение будет многократно использоваться для
таблиц ISAM
или BDB
, но не для таблиц типов
MyISAM
или InnoDB
. Если Вы удаляете все строки в
таблице с помощью вызова DELETE FROM table_name
(без
WHERE
) в режиме AUTOCOMMIT
, последовательность
начинается сначала для всех типов таблицы. ОБРАТИТЕ ВНИМАНИЕ:
может иметься только один столбец AUTO_INCREMENT
на
таблицу, и он должен быть индексирован. MySQL Version 3.23 будет также
работать правильно, только если столбец auto_increment имеет только
положительные значения. Вставка отрицательного числа будет расценена как
вставка очень большого положительного номера. Это выполнено, чтобы избежать
проблем точности, когда числа переходят от положительного к отрицательному и
также гарантировать, что случайно не получается столбец
auto_increment, который содержит 0.
Чтобы сделать MySQL совместимым с
некоторыми прикладными программами ODBC, Вы можете находить последнюю
вставленную строку следующим запросом:
SELECT * FROM tbl_name WHERE auto_col IS NULL
NULL
для столбцов TIMESTAMP
будут
обработаны иначе, чем для других типов столбцов. Вы не можете сохранять
литеральный NULL
в столбце TIMESTAMP
. Установка
столбца в NULL
приведет его к текущей (актуальной) дате и
времени. Поскольку столбцы TIMESTAMP
ведут себя именно так,
атрибуты NULL
и NOT NULL
не применяются нормальным
способом и игнорируются, если Вы определяете их. С другой стороны, чтобы
сделать это проще для MySQL-клиентуры, сервер сообщает, что таким столбцам
могут быть назначены значения NULL
(это и правда так), даже при
том, что TIMESTAMP
никогда фактически не будет содержать
значение NULL
. Вы можете видеть это, когда Вы используете
DESCRIBE tbl_name
, чтобы получить описание Вашей таблицы.
Обратите внимание, что установка столбца TIMESTAMP
в
0
не устанавливает его в NULL
, поскольку
0
имеющее силу значение TIMESTAMP
.
DEFAULT
не определено для столбца,
MySQL автоматически назначает его. Если столбец может брать как значение
NULL
, значением по умолчанию будет именно NULL
.
Если столбец объявлен как NOT NULL
, значение по умолчанию
зависит от типа столбца:
AUTO_INCREMENT
, значение по умолчанию 0
. Для
столбцов AUTO_INCREMENT
значением по умолчанию будет следующее
значение в последовательности.
TIMESTAMP
, значением по
умолчанию будет соответствующее нулевое значение для типа. Для первого в
таблице столбца TIMESTAMP
значением по умолчанию будет текущая
(актуальная) дата и время. Подробности в разделе
"5.2 Типы Date и Time".
ENUM
, значением по умолчанию является
пустая строка. Для типа ENUM
первое значение перечисления.NOW()
или CURRENT_DATE
.
KEY
представляет собой синоним для INDEX
.
UNIQUE
может иметь только различные значения.
Ошибка происходит, если Вы пробуете добавлять новую строку с ключом, который
соответствует существующей строке.
PRIMARY KEY
является уникальным
KEY
, причем все столбцы ключа должны быть определены как
NOT NULL
. В MySQL такой ключ именован как PRIMARY
.
Таблица может иметь только один PRIMARY KEY
. Если Вы не имеете
PRIMARY KEY
, а некоторые прикладные программы просят о
PRIMARY KEY
в Ваших таблицах, MySQL возвратит первый ключ
UNIQUE
, который не имеет столбцов NULL
.
PRIMARY KEY
может быть многостолбцовым индексом. Однако, Вы
не можете создавать такой индекс, использующий атрибут PRIMARY
KEY
в спецификации столбца. Выполнение этого отметит только один
столбец как первичный. Вы должны использовать вызов
PRIMARY KEY(index_col_name, ...)
.
PRIMARY
или UNIQUE
состоят только из
одного столбца, и он имеет тип integer, Вы можете также обратиться к нему как
_rowid
(нововведение в Version 3.23.11).
index_col_name
, с факультативным суффиксом
(_2
, _3
, ...
): чтобы сделать его
уникальным. Вы можете видеть индексные имена для таблицы, используя
SHOW INDEX FROM tbl_name
. Подробности в разделе
"4.5.5 Синтаксис SHOW
".
MyISAM
поддерживает индексы на столбцах,
которые могут иметь значения NULL
. В других случаях Вы должны
объявить такие столбцы как NOT NULL
.
col_name(length)
Вы можете определять
индекс, который использует только часть столбца типа CHAR
или
VARCHAR
. Это может сделать индексный файл намного меньше.
MyISAM
поддерживает
индексы на столбцах типов BLOB
и TEXT
. При
помещении индекса на столбце BLOB
или TEXT
Вы
ДОЛЖНЫ всегда определять длину индекса:
CREATE TABLE test (blob_col BLOB, index(blob_col(10)));
ORDER BY
или GROUP BY
со
столбцом TEXT
или BLOB
, используется только первые
max_sort_length
байт. Подробности в разделе
"5.3.2 Типы BLOB
и TEXT
".
MyISAM
поддерживает индексы
FULLTEXT
. Они могут быть созданы только из столбцов типов
VARCHAR
и TEXT
. Индексация всегда выполняется над
всем столбцом, частичная индексация пока не поддержана. Подробности в разделе
"9.4 Полнотекстовый поиск в MySQL".
FOREIGN KEY
, CHECK
и
REFERENCES
фактически не делают ничего. Синтаксис для них
обеспечивается только для совместимости, чтобы сделать проще портирование
кода из других SQL-серверов и выполнять прикладные программы, которые создают
таблицы со ссылками. Подробности в разделе
"1.4.4 Функциональные возможности,
отсутствующие в MySQL".
NULL
берет один бит, округляя
занятое им место до самого близкого байта.
row length = 1+(sum of column lengths)+ (number of NULL columns+7)/8+ (number of variable-length columns)
table_options
и SELECT
выполнены только в
MySQL Version 3.23 и выше.
Различные типы таблиц:
BDB или Berkeley_db | Транзакционно-безопасные таблицы с блокировкой страниц. |
HEAP | Данные для этих таблиц сохранены только в памяти. |
ISAM | Первоначальный драйвер таблицы. |
InnoDB | Транзакционно-безопасные таблицы с блокировкой строки. |
MERGE | Совокупность таблиц MyISAM, используемых как одна. |
MyISAM | Новый двоично-независимый драйвер таблицы, который заменяет формат ISAM. |
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). |
PASSWORD | Зашифровать файл .frm
паролем. Эта опция не делает ничего в стандартной версии MySQL. |
DELAY_KEY_WRITE | Установите это в 1, если Вы хотите задержать обновление ключей таблицы до ее закрытия (только MyISAM). |
ROW_FORMAT | Определяет, как строки должны быть сохранены. В настоящее время Вы можете использовать только опции DYNAMIC и STATIC для таблиц типа MyISAM. |
MyISAM
, MySQL использует результат
max_rows*avg_row_length
, чтобы решить насколько большой будет
возникающая в результате таблица. Если Вы не определяете любые из
вышеупомянутых параметров, максимальный размер для таблицы будет 4G (или 2G,
если Ваша операционная система поддерживают только таблицы 2G). Причина для
этого: надо уменьшить размеры указателя, чтобы сделать индекс меньше и
быстрее, если Вы действительно не нуждаетесь в больших файлах.
Если Вы не используете PACK_KEYS
, по умолчанию будут упакованы
только строки, но не числа. Если Вы используете PACK_KEYS=1
,
числа будут упакованы также. При упаковке двоичных цифровых ключей MySQL
использует префиксное сжатие. Это означает, что Вы получите большую пользу от
этого только, если Вы имеете много чисел, которые являются теми же самыми.
Префиксное сжатие означает, что каждый ключ нуждается в одном байте
дополнительного пространства, чтобы указать, сколько байтов предыдущего ключа
совпадают с текущим. Обратите внимание, что указатель на строку сохранен в
порядке со старшим первым байтом непосредственно после ключа, чтобы улучшить
сжатие. Это означает, что, если Вы имеете много равных ключей в строке, все
последующие те же самые ключи будет обычно только брать 2 байта (включая
указатель на строку). Сравните это с обычным случаем, где следующие ключи
будут брать storage_size_for_key+pointer_size (обычно 4) байта. С другой
стороны, если все ключи полностью различны, Вы будете терять 1 байт на ключ,
если он не может иметь значения NULL
(в этом случае, упакованная
длина ключа будет сохранена в том же самом байте, который используется, чтобы
отметить, что этот ключ имеет значение NULL
).
SELECT
после инструкции
CREATE
, 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
и значениями по
умолчанию для новых столбцов.
CREATE TABLE ... SELECT
автоматически не будет создавать никаких
индексов для Вас. Это должно быть выполнено преднамеренно, чтобы сделать
команду настолько гибкой, насколько это вообще возможно. Если Вы хотите иметь
индексы в созданной таблице, Вы должны определить их перед инструкцией
SELECT
:
mysql> create table bar (unique (n)) select n from foo;Если происходят ошибки при копировании данных в таблицу, они будут автоматически удалены. Чтобы гарантировать, что файл регистрации модификаций может использоваться, чтобы освежить первоначальные таблицы, MySQL не будет позволять параллельные вставки в течение выполнения
CREATE
TABLE .... SELECT
.
RAID_TYPE
поможет Вам обойти 2G/4G ограничение для
файла данных MyISAM (но не индексного файла) на операционных системах,
которые не поддерживают большие файлы. Вы можете получать также большее
быстродействие, помещая каталоги RAID
на различных физических
дисках. RAID_TYPE
будет работать с любой OS, если Вы
сконфигурировали 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.
Вы должны иметь привилегии SELECT
, UPDATE
и
DELETE
на таблицах, которые Вы отображаете к таблице
MERGE
. Все отображенные таблицы должны быть в той же самой базе
данных, что и таблица MERGE
.
PRIMARY
будет помещен в начало, за
ним расположатся ключи UNIQUE
, а за ними нормальные ключи. Это
помогает оптимизатору MySQL располагать по приоритетам, который ключ
использовать, а также более быстро обнаруживает дублированные ключи
UNIQUE
.
DATA DIRECTORY="directory"
или INDEX
DIRECTORY="directory"
Вы можете определять, где драйвер таблицы должен
поместить файлы таблицы и индекса. Это работает только для таблиц
MyISAM
в MySQL
4.0, когда Вы не используете опцию
--skip-symlink
.В некоторых случаях MySQL тихо изменяет спецификацию столбца, заданную в
инструкции CREATE TABLE
. Это может также происходить с
ALTER TABLE
:
VARCHAR
-столбцы с длиной меньше, чем четыре, будут
изменены на CHAR
.
VARCHAR
, TEXT
или
BLOB
), все столбцы CHAR
длиной более, чем три
символа, будут изменены на VARCHAR
. В MySQL VARCHAR
всего лишь иной способ хранить символы. MySQL выполняет это преобразование
потому, что оно экономит место и делает операции с таблицей быстрее.
TIMESTAMP
должен быть четный и в диапазоне от 2 до 14. Если
Вы определяете 0 или больше, чем 14, размер принудительно выставится в 14.
Нечетно-оцененные размеры в диапазоне от 1 до 13 принудительно выставятся в
следующее более высокое четное число.
NULL
в столбце
TIMESTAMP
. Установка его в NULL
реально
устанавливает его к текущей (актуальной) дате и времени. Потому, что столбцы
TIMESTAMP
ведут себя именно так, атрибуты NULL
и
NOT NULL
не применяются нормальным способом и игнорируются, если
Вы определяете их. DESCRIBE tbl_name
всегда сообщает, что
столбцу TIMESTAMP
может быть назначено значение
NULL
.
Если Вы хотите видеть, использовал или нет MySQL столбец не того типа,
какой Вы определили, выдайте инструкцию DESCRIBE tbl_name
после
создания или изменения Вашей таблицы.
Некоторые другие изменения типа столбца могут
происходить, если Вы сжимаете таблицу, используя myisampack
.
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 MODIFY [COLUMN] create_definition 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
позволяет Вам изменять структуру существующей
таблицы. Например, Вы можете добавлять или удалять столбцы, создавать или
уничтожать индексы, изменять тип существующих столбцов, переименовывать
столбцы или непосредственно таблицу. Вы можете также изменять комментарий для
таблицы и тип таблицы. Подробности в разделе
"7.3 Синтаксис CREATE TABLE
".
Если Вы используете ALTER TABLE
, чтобы изменить спецификацию
столбца, но DESCRIBE tbl_name
указывает, что Ваш столбец не был
изменен, возможно, что MySQL игнорировал Вашу модификацию по одной из причин,
описанных в разделе "7.3.1 Тихие
изменения спецификации столбца". Например, если Вы пробуете изменять
столбец VARCHAR
на CHAR
, MySQL будет все же
использовать именно VARCHAR
, если таблица содержит другие
столбцы переменной длины.
ALTER TABLE
работает, делая временную копию первоначальной
таблицы. Перенастройка выполняется на копии, затем первоначальная таблица
будет удалена, а новая переименована в старую. Это выполнено таким способом,
чтобы все модификации были автоматически переназначены к новой таблице. В то
время, как выполняется ALTER TABLE
, первоначальная таблица
читаема другой клиентурой. Модификации и записи остановлены, пока новая
таблица не будет готова.
Обратите внимание, что, если Вы используете любую другую опцию
ALTER TABLE
, чем RENAME
, MySQL будет всегда
создавать временную таблицу, даже если данные не должны быть строго
скопированы (подобно тому, когда Вы изменяете имя столбца). Авторы планируют
исправить это в будущем, но поскольку ALTER TABLE
вызывается
относительно редко, это не имеет высокого приоритета в TODO.
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 tbl_name RENAME TO new_name
без любых других параметров, MySQL просто переименовывает файлы, которые
соответствуют таблице tbl_name
. Нет никакой потребности
создавать временную таблицу. Подробности в разделе
"7.5 Синтаксис RENAME TABLE
".
ALTER TABLE ... DISABLE KEYS
предписывает
прекратить модифицировать неуникальные индексы для таблиц
MyISAM
. ALTER TABLE ... ENABLE KEYS
затем должен
использоваться, чтобы освежить отсутствующие индексы. MySQL делает это
специальным алгоритмом, который намного быстрее, чем вставка ключей один за
другим, блокировка обработки ключей может давать значительное ускорение
работы системы на оптовых вставках.
create_definition
используют тот же самый
синтаксис для ADD
и CHANGE
, что и CREATE
TABLE
. Обратите внимание, что этот синтаксис включает имя столбца, а
не только тип столбца. Подробности в разделе
"7.3 Синтаксис CREATE TABLE
".
CHANGE old_col_name
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 Version 3.22.16a, Вы можете также использовать
MODIFY
, чтобы изменить тип столбца без переименования:
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
CHANGE
или MODIFY
, чтобы
сократить столбец, для которого индекс существует как часть столбца
(например, если Вы имеете индекс на первых 10 символах столбца
VARCHAR
), Вы не можете делать столбец короче, чем число
символов, которые индексированы.
CHANGE
или
MODIFY
, MySQL пробует преобразовывать данные к новому типу.
FIRST
или ADD ... AFTER col_name
, чтобы добавить
столбец в специфической позиции внутри строки таблиц. Значение по умолчанию
должно добавить столбец в последнюю позицию.
ALTER COLUMN
определяет новое значение
по умолчанию для столбца или удаляет старое значение по умолчанию. Если
старое значение по умолчанию удалено, и столбец может быть NULL
,
новое значение по умолчанию будет NULL
. Если столбец не может
быть NULL
, MySQL назначает значение по умолчанию, как описано в
разделе "7.3 Синтаксис CREATE TABLE
".
DROP INDEX
удаляет индекс. Это
расширение MySQL для ANSI SQL92. Подробности в разделе
"7.8 Синтаксис DROP INDEX
".
DROP PRIMARY KEY
удаляет первичный
индекс. Если такой индекс не существует, это удаляет первый
UNIQUE
-индекс в таблице (MySQL отмечает первый ключ
UNIQUE
как PRIMARY KEY
, если никакой PRIMARY
KEY
не был определен явно).
Если Вы добавляете UNIQUE
INDEX
или PRIMARY KEY
к таблице, он будет сохранен перед
любым не-UNIQUE
индексом так, чтобы MySQL мог обнаружить двойные
ключи как можно раньше.
ORDER BY
позволяет Вам создавать новую
таблицу со строками в специфическом порядке. Обратите внимание, что таблица
не будет оставаться в этом порядке после вставок и удалений. В некоторых
случаях это может сделать сортировку проще для MySQL, если таблица сделана
так, как Вы желаете упорядочить ее позже. Эта опция главным образом полезна,
когда Вы знаете, что Вы обычно собираетесь сделать запрос строк в некотором
порядке. Используя эту опцию после больших изменений для таблицы, Вы можете
получить более высокую эффективность.
ALTER TABLE
на
таблице MyISAM
, все неуникальные индексы будут созданы в
отдельном пакете (подобно тому, как это происходит в REPAIR
).
Это ускорит ALTER TABLE
, когда Вы имеете много индексов.Имеется пример, который показывает, некоторые из способов применения
ALTER TABLE
. Мы начинаем с таблицы t1
, которая
создана как показано ниже:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
Чтобы переименовывать таблицу из t1
в t2
, надо:
mysql> ALTER TABLE t1 RENAME t2;
Чтобы изменить столбец a
с типа 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;
Чтобы добавить новый целочисленный столбец c
с поддержкой
AUTO_INCREMENT
, надо:
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=#
.
С таблицами MyISAM, если Вы не изменяете столбец на
AUTO_INCREMENT
, номер последовательности не будут изменен. Если
Вы удаляете столбец с поддержкой AUTO_INCREMENT
, а затем
добавляете другой с AUTO_INCREMENT
, числа снова начнутся с 1.
Подробности в разделе "11.6.1
Проблемы с ALTER TABLE
".
RENAME TABLE
RENAME TABLE tbl_name TO new_table_name[, tbl_name2 TO new_table_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_database.table_name TO other_database.table_name;
Когда Вы выполняете RENAME
, Вы не можете иметь блокированные
таблицы или активные транзакции. Вы должны также иметь привилегии
ALTER
и DROP
на первоначальной таблице и привилегии
CREATE
и INSERT
на новой таблице.
Если MySQL сталкивается с любыми ошибками в процессе переименования, он будет делать обратное переименование для всех переименованных таблиц, чтобы вернуть все обратно в первоначальное состояние.
DROP TABLE
DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]
DROP TABLE
удаляет одну или большее количество таблиц. Все
данные таблицы и определение таблицы будут удалены, так что будьте
внимательны с этой командой!
В MySQL Version 3.22 или позже Вы можете использовать ключевые слова
IF EXISTS
, чтобы предотвратить ошибку для таблиц, которых нет.
RESTRICT
и CASCADE
ничего не делают и нужны лишь
для совместимости с другими СУБД.
ОБРАТИТЕ ВНИМАНИЕ: DROP TABLE
не
транзакционно-безопасна и автоматически завершает любые активные транзакции.
CREATE INDEX
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON tbl_name (col_name[(length)],... )
Инструкция CREATE INDEX
ничего не делает до Version 3.22. В
Version 3.22 или позже CREATE INDEX
она отображена к инструкции
ALTER TABLE
, чтобы создать индексы. Подробности в разделе
"7.4 Синтаксис ALTER TABLE
".
Обычно Вы создаете все индексы на таблице во время непосредственного
создания таблицы с помощью вызова CREATE TABLE
. Подробности в
разделе "7.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
!
Обратите внимание, что Вы можете добавлять индекс на столбце, который
может иметь значения NULL
, и на столбцах типов
BLOB
и TEXT
только, если Вы используете
MySQL Version 3.23.2 или более новую и применяете тип таблицы
MyISAM
.
Индексы FULLTEXT
могут индексировать только столбцы типов
VARCHAR
и TEXT
в таблицах типа MyISAM
.
Индексы FULLTEXT
доступны в MySQL Version 3.23.23 и более новых.
Подробности в разделе "9.4
Полнотекстовый поиск в MySQL".
DROP INDEX
DROP INDEX index_name ON tbl_name
DROP INDEX
удаляет индекс с именем index_name
из
таблицы tbl_name
. DROP INDEX
ничего не делает до
версии Version 3.22, а начиная с нее, этот вызов перенацелен на
соответствующий вызов ALTER TABLE
для удаления индекса.
Подробности в разделе "7.4
Синтаксис ALTER TABLE
".
SELECT
,
INSERT
, UPDATE
, DELETE
SELECT
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [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] [PROCEDURE procedure_name] [FOR UPDATE|LOCK IN SHARE MODE]]
SELECT
используется, чтобы отыскать строки, выбранные из
одной или большего количества таблиц. select_expression
указывает столбцы, которые Вы хотите получить. SELECT
может
также использоваться, чтобы получить строки, вычисленные независимо от
любой таблицы. Например:
mysql> SELECT 1 + 1; -> 2
Все используемые ключевые слова должны быть даны точно в порядке,
показанном выше. Например, предложение HAVING
должно прийти
после любого предложения GROUP BY
и перед любым предложением
ORDER BY
.
SELECT
может применять псевдоним, используя AS
.
Псевдоним используется при задании в выражении имени столбца и может быть
указан с предложениями ORDER BY
или HAVING
. Пример:
mysql> select concat(last_name,', ',first_name) AS full_name from mytable ORDER BY full_name;
FROM table_references
указывает таблицы, из
которых надо отыскать строки. Если Вы называете больше, чем одну таблицу, Вы
выполняете объединение. Для получения информации относительно синтаксиса
объединения обратитесь к разделу "8.1.1 Синтаксис
JOIN
".
col_name
,
tbl_name.col_name
или db_name.tbl_name.col_name
. Вы
не должны определять префикс tbl_name
или
db_name.tbl_name
для ссылки столбца в инструкции
SELECT
, если ссылка однозначна. Подробности в разделе
"3.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. Подробности в разделе "6 Функции для
использования в предложениях 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 Version 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;
SQL_SMALL_RESULT
, SQL_BIG_RESULT
,
SQL_BUFFER_RESULT
, STRAIGHT_JOIN
и
HIGH_PRIORITY
представляют собой MySQL-расширения ANSI SQL92.
HIGH_PRIORITY
даст SELECT
более высокий
приоритет, чем инструкциям, которые модифицируют таблицу. Вы должны
использовать это только для запросов, которые являются очень быстрыми и
должны быть выполнены сразу. Запрос SELECT HIGH_PRIORITY
выполнится, если таблица блокирована для чтения, даже если имеется инструкция
модификации, которая ждет таблицу.
SQL_BIG_RESULT
может использоваться с GROUP BY
или DISTINCT
, чтобы сообщить оптимизатору, что набор результатов
будет иметь много строк. В этом случае MySQL использует дисковые временные
таблицы если необходимо. MySQL будет также, в этом случае, предпочитать
сортировку временной таблицы с ключом на элементах GROUP BY
.
GROUP BY
, строки
вывода будут сортироваться согласно GROUP BY
, как будто Вы имели
ORDER BY
над всеми полями в GROUP BY
. MySQL
расширил GROUP BY
так, что Вы можете также определять
ASC
и DESC
для GROUP BY
:
SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
GROUP BY
так, чтобы позволить
Вам выбирать поля, которые не упомянуты в предложении GROUP BY
.
Если Вы не получаете те результаты, которых Вы ожидаете от Вашего запроса,
пожалуйста, прочитайте описание на GROUP BY
. Подробности в
разделе "14 Функции для
использования с предложением GROUP BY
".
SQL_BUFFER_RESULT
принудительно поместит результат во
временную таблицу. Это поможет MySQL освободить блокированную таблицу
пораньше и пригодится в случаях, где требуется длительное время, чтобы
послать набор результатов пользователю.
SQL_SMALL_RESULT
опция, специфичная для MySQL, может
использоваться с GROUP BY
или DISTINCT
, чтобы
сообщить оптимизатору, что набор результатов будет маленький. В этом случае
MySQL использует быстрые временные таблицы, чтобы сохранить возникающую в
результате таблицу вместо того, чтобы использовать сортировку.
STRAIGHT_JOIN
заставляет оптимизатор соединять таблицы в том
порядке, в котором они перечислены в предложении FROM
. Вы можете
использовать это, чтобы ускорить запрос, если оптимизатор соединяет таблицы в
неоптимальном порядке.
LIMIT
может использоваться, чтобы ограничить
число строк, возвращенных инструкцией SELECT
. LIMIT
берет один или два числовых параметра. Если два параметра заданы, первый
определяет смещение первой строки, которая будет возвращена, второй
определяет максимальное число строк. Смещение начальной строки 0 (не 1!):
mysql> select * from table LIMIT 5,10; # Вернуть строки 6-15Если один параметр задан, он указывает максимальное число строк:
mysql> select * from table LIMIT 5; # Вернуть первые 5 строкДругими словами,
LIMIT n
эквивалентно LIMIT 0,n
.
SELECT ... INTO OUTFILE
'file_name'
пишет выбранные строки в файл. Он будет создан на сервере
и не может уже существовать (среди других полезных свойств, это защищает от
разрушения некоторыми шутниками файлов типа /etc/passwd). Вы должны
иметь привилегию file на сервере, чтобы использовать эту
форму вызова SELECT
.
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
. Подробности
в разделе "8.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
экранирован, чтобы сделать это проще. Поскольку возникающий в результате файл
не должен соответствовать 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 DUMPFILE
вместо INTO OUTFILE
, MySQL будет только писать одну строку в
файл, без любого выравнивания или экранировки управляющих символов. Это
полезно, если Вы хотите сохранять blob в файле.
INTO OUTFILE
и
INTO DUMPFILE
будет читаемым для всех пользователей! Причина в
том, что сервер MySQL не может создавать файл, который принадлежит кому-либо
другому, а не пользователю, который запустил сервер. Вы не должны никогда
выполнять mysqld
как root!), файл должен быть доступен на чтение
всем желающим, чтобы Вы могли получать из него строки.
FOR UPDATE
с драйвером таблиц,
поддерживающем блокировки страницы/столбца, нужные столбцы будут
заблокированы для записи.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)]
а join_condition
как:
ON conditional_expr | USING (column_list)
Вы никогда не должны иметь никаких условий в части ON
,
которые используются, чтобы ограничить то, какие строки Вы получите в наборе
результатов. Если Вы хотите оговорить то, которые строки должны быть в
результате, Вы должны делать это в предложении WHERE
.
Обратите внимание, что в версиях до Version 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
.
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
с именами всех столбцов, которые существуют в
обеих таблицах.
RIGHT JOIN
работает аналогично LEFT JOIN
. Чтобы
сохранить код переносимым между базами данных, рекомендует использовать
LEFT JOIN
вместо RIGHT JOIN
.
STRAIGHT_JOIN
идентичен JOIN
, за исключением
того, что левая таблица всегда читается перед правой таблицей. Это может
использоваться для тех немногих случаев, когда оптимизатор объединения
помещает таблицы в неправильном порядке.
EXPLAIN
показывает, что MySQL использует
неправильный индекс. Определяя USE INDEX (key_list)
, Вы можете
сообщать, чтобы MySQL использовал только один из определенных индексов, чтобы
найти строки в таблице. Альтернативный синтаксис IGNORE INDEX
(key_list)
может использоваться, чтобы сообщить, чтобы MySQL не
использовал некоторый специфический индекс.Вот некоторые примеры:
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;
UNION
SELECT .... UNION [ALL] SELECT .... [UNION SELECT ...]
UNION
реализован только в версии MySQL 4.0.0 и выше.
UNION
используется, чтобы объединить результаты из многих
инструкций SELECT
в один набор результатов.
Команды SELECT
представляют собой нормальные команды выбора,
но со следующими ограничениями:
SELECT
может иметь INTO
OUTFILE
.
SELECT
может иметь ORDER
BY
.Если Вы не используете ключевое слово ALL
для
UNION
, все возвращенные строки будут уникальны, подобно тому,
как если бы Вы сделали DISTINCT
для общего набора результатов.
Если Вы определяете ALL
, то Вы получите все строки соответствий
из всех используемых инструкций SELECT
.
INSERT
INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] VALUES (expression,...),(...),... INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ... INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=expression, col_name=expression, ...
INSERT
вставляет новые строки в существующую таблицу. Форма
INSERT ... VALUES
вставляет строки, основываясь на явно
определенных значениях. INSERT ... SELECT
вставляет строки,
выбранные из другой таблицы или таблиц. Форма INSERT ... VALUES
с несколькими списками значений поддержана в MySQL Version 3.22.5 или позже.
Синтаксис col_name=expression
введен, начиная с MySQL Version
3.22.10 или выше.
tbl_name
таблица, в которую строки должны быть вставлены.
Список имен столбцов или предложение SET
указывает, для которых
столбцов инструкция определяет значения:
INSERT ...
VALUES
или INSERT ... SELECT
, значения для всех столбцов
нужно обеспечить в списке VALUES()
или через
SELECT
. Если Вы не знаете порядка столбцов в таблице,
используйте DESCRIBE tbl_name
, чтобы выяснить.
CREATE TABLE
".
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
, которая позволяет пользователю продолжать работу сразу же.
Подробности в разделе "8.4 Синтаксис
INSERT DELAYED
". Обратите внимание, что
LOW_PRIORITY
обычно не должен использоваться с таблицами
MyISAM
, поскольку это отключает параллельные вставки.
IGNORE
в
INSERT
со многими строками значений, любые строки, которые
дублируют существующий ключ PRIMARY
или UNIQUE
в
таблице, игнорируются и не будут вставлены. Если Вы не определяете
IGNORE
, вставка будет прервана, если имеется любая строка,
которая дублирует существующее значение ключа. Вы можете определять в функции
C API mysql_info()
, сколько строк были вставлены в таблицу.
DONT_USE_DEFAULT_FIELDS
, инструкции INSERT
генерируют ошибку, если Вы явно не определяете значения для всех столбцов,
которые требуют значения, отличного от NULL
.Если Вы используете 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 ... 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
над той же самой таблицей,
в которую Вы вставляете. Проблема состоит в том, что SELECT
,
возможно, нашел бы записи, которые были вставлены ранее в течение той же
самой операции. При использовании предложений sub-select, ситуация могла бы
очень легко запутаться!
AUTO_INCREMENT
работают как обычной.
mysql_info()
, чтобы
получить информацию относительно запроса. Подробности в разделе
"8.3 Синтаксис INSERT
".
INSERT ... SELECT
.Вы можете, конечно, также использовать REPLACE
вместо
INSERT
, чтобы перезаписать старые строки.
INSERT DELAYED
INSERT DELAYED ...
Опция DELAYED
для инструкции INSERT
специфична
для MySQL и является очень полезной, если Вы имеете клиентуру, которая не
может ждать завершения INSERT
. Это общая проблема, когда Вы
используете MySQL для регистрации и также периодически выполняете инструкции
SELECT
и UPDATE
, которые занимают много времени.
DELAYED
введен в MySQL Version 3.22.15. Это MySQL-расширение для
стандарта ANSI SQL92.
INSERT DELAYED
работает только с таблицами ISAM
и MyISAM
. Обратите внимание, что таблицы MyISAM
поддерживают параллельные SELECT
и INSERT
, если не
имеется никаких свободных блоков в середине файла данных, Вы очень редко
должны использовать INSERT DELAYED
с таблицами типа
MyISAM
.
Когда Вы используете INSERT DELAYED
, клиент получит сообщение
OK сразу, а вот строка будет вставлена, когда таблица не будет использоваться
любым другим потоком.
Другая польза от применения INSERT DELAYED
в том, что вставки
многих клиентов будут связаны вместе и записаны в одном блоке. Это намного
быстрее, чем выполнение многих отдельных вставок.
Обратите внимание, что в настоящее время поставленные в очередь строки
сохранены только в памяти, пока они не вставлены в таблицу. Это означает,
что, если Вы уничтожаете mysqld
крутыми мерами
(kill -9
), или если mysqld
рухнет неожиданно, любые
поставленные в очередь строки, которые не были записаны на диск, потеряются!
Следующее описывает подробно, что случается, когда Вы используете опцию
DELAYED
вместе с командами INSERT
или
REPLACE
. В этом описании "поток" представляет собой поток,
который получил команду INSERT DELAYED
, и "драйвер" обозначает
поток, который обрабатывает все инструкции INSERT DELAYED
для специфической таблицы.
DELAYED
для таблицы,
будет создан драйвер: чтобы обработать все инструкции DELAYED
для этой таблицы, если никакого такого драйвера еще не существует.
DELAYED
. Если нет, он сообщает, чтобы драйвер это сделал.
Блокировка DELAYED
может быть получена, даже если другие потоки
имеют блокировку READ
или WRITE
на таблице. Однако,
драйвер будет ждать ALTER TABLE
или FLUSH TABLES
,
чтобы гарантировать, что текущая структура таблицы современна.
INSERT
, но вместо того, чтобы
записать строку в таблицу, он помещает копию конечной строки в очередь,
которая управляется драйвером. Любые ошибки синтаксиса будут отмечены потоком
и сообщены программе пользователя.
AUTO_INCREMENT
для возникающей в результате строки. Он не может
получить эти данные с сервера, поскольку возвраты INSERT
перед
операцией вставки был завершены.
delayed_insert_limit
строк написаны,
драйвер проверяет, являются или нет любые инструкции SELECT
ждущими своей очереди. Если это так, драйвер позволяет им выполниться перед
продолжением своей работы.
INSERT DELAYED
не появилась в течение последних
delayed_insert_timeout
секунд, драйвер завершается.
delayed_queue_size
строк, ждущих обработки,
уже в специфической очереди драйверов, поток, запрашивающий INSERT
DELAYED
ждет до появления участка памяти в очереди. Это выполнено,
чтобы гарантировать, что сервер mysqld
не использует всю память
для отсроченной очереди.
delayed_insert
в столбце Command
. Это будет
уничтожаться, если Вы выполняете команду FLUSH TABLES
или
уничтожаете поток с помощью KILL thread_id
. Однако, драйвер
сначала сохранит все поставленные в очередь строки в таблицу перед выходом. В
это время система не будет принимать никакие новые команды
INSERT
от других потоков. Если Вы выполняете команду
INSERT DELAYED
после того, как это было выполнено, новый поток
драйвера будет создан.
INSERT
DELAYED
имеют более высокий приоритет, чем нормальные команды
INSERT
, если уже имеется драйвер INSERT DELAYED
!
Другие команды модификации должны будут ждать до опустошения очереди
INSERT DELAYED
, уничтожения драйвера (через KILL
thread_id
) или выполнения 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] [LIMIT #]
UPDATE
модифицирует столбцы в существующих строках таблиц с
новыми значениями. Предложение SET
указывает, какие столбцы
изменять, и значения, которые им должны быть заданы. Предложение
WHERE
, если задано, определяет, какие строки должны
модифицироваться. Иначе модифицируются все строки. Если определено
предложение ORDER BY
, строки будут модифицироваться в том
порядке, который определен.
Если Вы определяете ключевое слово LOW_PRIORITY
, выполнение
UPDATE
будет отсрочено до наступления момента, когда никакие
клиенты не читают из таблицы.
Если Вы определяете ключевое слово IGNORE
, инструкция
модификации не будет прерываться, даже если мы получаем ошибки дублирования
ключа в течение модификации. Строки, которые могли бы вызвать конфликты, не
будут модифицироваться вообще.
Если Вы обращаетесь к столбцу из tbl_name
в выражении,
UPDATE
использует текущее значение столбца. Например, следующая
инструкция устанавливает столбец age
к следующему за его текущим
значением:
mysql> UPDATE persondata SET age=age+1;
Назначения UPDATE
оценены слева направо. Например, следующая
инструкция удваивает столбец age
, затем увеличивает его на 1:
mysql> UPDATE persondata SET age=age*2, age=age+1;
Если Вы устанавливаете столбец к значению, которое он в настоящее время имеет, MySQL не обращает внимания на это и не модифицирует столбец!
UPDATE
возвращает число строк, которые
были фактически изменены. В MySQL Version 3.22 или позже функция C API
mysql_info()
возвращает число строк, которые были согласованы и
модифицировались, и число предупреждений, которые произошли в течение
UPDATE
.
В MySQL Version 3.23 Вы можете использовать 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
удаляет строки, которые удовлетворяют условию,
заданному в where_definition
из таблицы table_name
и возвращает число удаленных записей.
Если Вы выдаете DELETE
без предложения WHERE
,
все строки будут удалены. Если Вы делаете это в режиме
AUTOCOMMIT
, это сработает аналогично TRUNCATE
.
Подробности в разделе "8.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
быстрее. Подробности в разделе
"4.6 Синтаксис OPTIMIZE
TABLE
".
Вы можете удалять строки из многих таблиц в то же самое время, а также иметь дополнительные таблицы, которые используются для поиска.
Символ .*
после имени таблицы появился для совместимости с
Access
:
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
В вышеупомянутом случае мы удаляем строки соответствий только из таблиц
t1
и t2
.
ORDER BY
и использование нескольких таблиц в DELETE
реализовано, начиная с MySQL 4.0.
Если предложение ORDER BY
используется, строки будут удалены
в заданном порядке. Это удобно в сочетании с LIMIT
. Например:
DELETE FROM somelog WHERE user='jcole' ORDER BY timestamp LIMIT 1
Это удалит самую старую запись (по timestamp
), где строка
соответствует предложению WHERE
.
MySQL-специфичная опция LIMIT rows
функции
DELETE
сообщает серверу максимальное число строк, которые будут
удалены прежде, чем управление будет возвращено пользователю. Это может
использоваться, чтобы гарантировать, что специфическая команда
DELETE
не займет слишком много времени. Вы можете просто
повторять команду DELETE
, пока число обрабатываемых строк не
меньше, чем значение LIMIT
.
TRUNCATE
TRUNCATE TABLE table_name
В версии 3.23 TRUNCATE TABLE
отображен на вызов COMMIT;
DELETE FROM table_name
. Подробности в разделе
"8.6 Синтаксис DELETE
".
Разница между TRUNCATE TABLE
и DELETE FROM ..
:
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
, за
исключением того, что, если старая запись в таблице имеет то же самое
значение, что и новая запись на уникальном индексе, старая запись будет
удалена прежде, чем новая запись вставлена в таблицу. Подробности в разделе
"8.3 Синтаксис INSERT
".
Другими словами, Вы не можете обращаться к значениям старой строки из
инструкции REPLACE
. В некоторых старых версиях MySQL могли, но
это было ошибкой, которая исправлена.
При использовании вызова REPLACE
mysql_affected_rows()
возвратит 2, если новая строка заменила
старую. Это потому, что в этом случае одна строка была вставлена, а затем
дубликат был удален.
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 Version 3.22.6
или более поздней.
По соображениям безопасности, при чтении текстовых файлов, размещенных на
сервере, файлы должны находиться в каталоге баз данных или быть читаемыми
всеми. Также, чтобы использовать LOAD DATA INFILE
на файлах
сервера, Вы должны иметь привилегию file. Подробности в
разделе "10.6 Привилегии,
предоставляемые MySQL".
Если Вы определяете ключевое слово LOW_PRIORITY
, выполнение
LOAD DATA
будет отложено до тех пор, пока другая клиентура не
прекратит читать из таблицы.
Если Вы определяете ключевое слово CONCURRENT
с таблицей типа
MyISAM
, то другие потоки могут получать данные из таблицы в то
время, как выполняется LOAD DATA
. Использование этой опции
будет, конечно, воздействовать на эффективность LOAD DATA
, даже
если никакой другой поток не использует таблицу в то же самое время.
Использование LOCAL
будет немного медленнее, чем разрешение
серверу обращаться к файлам непосредственно потому, что содержание файла
должно пропутешествовать с компьютера пользователя на сервер. С другой
стороны, Вы не нуждаетесь в привилегии file, чтобы загрузить
свои локальные файлы.
Если Вы используете MySQL ниже 3.23.24, Вы не можете читать из FIFO с
помощью LOAD DATA INFILE
. Если Вы должны читать из FIFO
(например, вывод из gunzip), используйте вместо этого команду LOAD
DATA LOCAL INFILE
.
Вы можете также загружать файлы данных, используя
полезность mysqlimport
. Она функционирует, посылая команду
LOAD DATA INFILE
на сервер. Опция --local
заставляет mysqlimport
читать файлы данных с компьютера
пользователя. Вы можете определять опцию --compress
, чтобы
получить лучшую эффективность при работе с медленными сетями, если
пользователь и сервер поддерживают сжатый протокол.
При размещении файлов на компьютере сервера, он использует правила:
Обратите внимание, что эти правила означают, что файл, заданный как
./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
. Подробности в разделе
"8.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
действовать следующим образом при чтении ввода:
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 будет иметь
поля, разделяемые запятыми и заключенные в двойные кавычки. Если строки в
файле завершены newlines, команда, показанная ниже, иллюстрирует параметры
обработки, которые Вы использовали бы, чтобы загрузить файл:
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
могут быть больше, чем одним символом. Например, чтобы писать
строки, которые завершены парами carriage return-linefeed, или читать файл,
содержащий такие строки, определите LINES TERMINATED BY '\r\n'
.
Например, чтобы читать файл записей, которые отделяются строкой
%%
, в таблицу 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
управляет цитированием полей.
Для вывода (SELECT ... INTO OUTFILE
), если Вы опускаете слово
OPTIONALLY
, все поля включены символом ENCLOSED BY
.
Пример такого вывода (использование запятой как разделителя поля) ниже:
"1","a string","100.20" "2","a string containing a , comma","102.20" "3","a string containing a \" quote","102.20" "4","a string containing a \", quote and comma","102.20"
Если Вы определяете OPTIONALLY
, символ
ENCLOSED BY
используется только для того, чтобы включить поля
типов CHAR
и 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
.
Например, вывод, показанный выше, появился бы как показано ниже, если бы
символ ESC был пустым. Заметьте, что второе поле в четвертой строке содержит
запятую после кавычки, которая ошибочно появляется и завершает поле:
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a " quote",102.20 4,"a string containing a ", quote and comma",102.20
Для ввода символ ENCLOSED BY
, если он вообще задан, будет
удален с концов значений поля. Это истинно, определен или нет
OPTIONALLY
. OPTIONALLY
не имеет никакого эффекта на
входной интерпретации. Местонахождения символа ENCLOSED BY
,
которому предшествует символ ESCAPED BY
, интерпретируются как
часть текущего значения поля. Кроме того, дублированные символы
ENCLOSED BY
, встречающиеся внутри полей, интерпретируются как
одиночные символы 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
.
0
(что фактически написано после символа ASCII
0
, не нулевой байт).Если символ FIELDS ESCAPED BY
пуст, никакие символы не
экранируются вовсе. Не стоит определять пустой символ ESC, особенно, если
значения полей в Ваших данных содержат любой из символов в списке выше.
Для ввода, если символ FIELDS ESCAPED BY
не пуст,
местонахождения этого символа будут удалены, и следующий символ принимается
буквально как часть значения поля. Исключительные ситуации: 0
или N (например, \0
или \N
, если
символ ESC задан как \). Эти последовательности интерпретируются
как 0
и NULL
соответственно. Ниже изложены правила
для обработки NULL
.
За подробностями относительно синтаксиса экранировки с символом \ отсылаю Вас к разделу "3.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 не может выяснить, как совмещать входные поля со столбцами таблицы.
Если строка имеет слишком мало полей, столбцы, для которых никакого
входного поля не присутствует, будут установлены в значения по умолчанию.
Задание этих значений по умолчанию подробно описано в разделе
"7.3 Синтаксис CREATE TABLE
".
Пустое значение поля интерпретируется не так, как если бы оно отсутствовало вовсе, а именно:
0
.
Обратите внимание, что здесь все происходит точно так же, как если Вы
назначаете пустую стргоку явно как значение соответствующего поля с помощью
вызовов INSERT
или UPDATE
.
Столбцы TIMESTAMP
будут установлены только к текущей дате и
времени, если для столбца имеется значение NULL
, или (только для
первого столбца TIMESTAMP
) если столбец типа
TIMESTAMP
не учтен в списке полей, когда такой список определен.
Если входная строка имеет слишком много полей, лишние поля игнорируются.
LOAD DATA INFILE
расценивает весь ввод как строки, так что Вы
не можете использовать числовые значения для столбцов типов ENUM
или SET
, как Вы можете это делать инструкциями
INSERT
. Все значения ENUM
и SET
должны
быть определены как строки!
Если Вы используете C API, Вы можете получать
информацию относительно запроса, вызывая функцию mysql_info()
когда запрос LOAD DATA INFILE
обработан. Формат информационной
строки показывается ниже:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
Предупреждения происходят при тех же самых обстоятельствах, что и с
командой INSERT
(подробности в разделе
"8.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
.
MySQL имеет очень сложный, но интуитивно понятный интерфейс SQL. Эта глава описывает различные команды, типы и функции, которые Вы должны знать, чтобы использовать MySQL эффективно. Эта глава также может служить справочником по всем функциональным возможностям, включенным в MySQL.
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
. Подробности в разделе
"4.10 Получение информации о базах
данных, таблицах, столбцах и индексах".
DESCRIBE
обеспечивает информацию относительно столбцов
таблицы. col_name
может быть именем столбца или строкой,
содержащей групповые символы SQL `%' и `_'.
Если типы столбцов не те, которые Вы задавали в инструкции CREATE
TABLE
, обратите внимание, что MySQL иногда изменяет типы столбцов.
Подробности в разделе "7.3.1
Тихие изменения спецификации столбца".
Эта инструкция предусмотрена для совместимости с Oracle.
Инструкция SHOW
обеспечивает подобную информацию. Подробности
в разделе "4.10 Синтаксис SHOW
".
BEGIN/COMMIT/ROLLBACK
По умолчанию, MySQL выполняется в режиме autocommit
. Это
означает, что, как только Вы сделаете модификацию, MySQL сохранит ее на диск.
Если Вы используете транзакционно-безопасные таблицы (подобно
BDB
, InnoDB
, Вы можете перевести MySQL в режим
не-autocommit
следующей командой:
SET AUTOCOMMIT=0
После того, как это сделано, Вы должны использовать COMMIT
,
чтобы сохранить Ваши изменения на диске, или ROLLBACK
, если Вы
хотите игнорировать изменения, которые сделали с начала Вашей транзакции.
Если Вы хотите переключать режим AUTOCOMMIT
для одного набора
инструкций, Вы можете использовать команды обрамления BEGIN
или
BEGIN WORK
так:
BEGIN; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summmary=@A WHERE type=1; COMMIT;
Обратите внимание, что, если Вы используете не транзакционно-безопасные
таблицы, изменения будут сохранены сразу, независимо от состояния режима
autocommit
.
Если Вы делаете ROLLBACK
, когда Вы модифицировали не
транзакционно-безопасные таблицы, Вы получите ошибку
(ER_WARNING_NOT_COMPLETE_ROLLBACK
) как предупреждение. Все
транзакционно-безопасные таблицы будут восстановлены, но любая
транзакционно-небезопасная таблица не будет изменяться.
Если Вы используете BEGIN
или SET AUTOCOMMIT=0
,
Вы должны использовать двоичный файл регистрации MySQL для резервирования
вместо старого файла регистрации модификаций. Транзакции сохранены в двоичном
протоколе, запись для COMMIT
может гарантировать, что
транзакции, которые прокручены обратно, не сохранены.
Следующие команды автоматически заканчивают транзакцию (как будто Вы
сделали COMMIT
перед выполнением команды):
ALTER TABLE | BEGIN |
CREATE INDEX |
DROP DATABASE | DROP TABLE |
RENAME TABLE |
TRUNCATE |
Вы можете изменять уровень изоляции для транзакций командой SET
TRANSACTION ISOLATION LEVEL ...
. Подробности в разделе
"9.2.3 Синтаксис SET
TRANSACTION
".
LOCK TABLES/UNLOCK TABLES
LOCK TABLES tbl_name [AS alias] {READ|[READ LOCAL]|[LOW_PRIORITY] WRITE} [, tbl_name {READ | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES
LOCK TABLES
блокирует таблицы для текущего потока.
UNLOCK TABLES
снимает любые блокировки для текущего потока. Все
таблицы, которые блокированы текущим потоком, автоматически разблокируются,
когда поток выдает другую команду LOCK TABLES
, или подключение к
серверу нормально закрывается.
Основные причины использовать LOCK TABLES
: эмуляция
транзакций или получение большего быстродействия при модифицировании таблиц.
Это объясняется более подробно позже.
Если поток получает блокировку 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
работает так:
Эта стратегия гарантирует, что блокировка таблицы свободна от тупиков. Имеются, однако, другие вещи, о которых надо знать:
Если Вы используете блокировку LOW_PRIORITY_WRITE
для
таблицы, это означает, что MySQL будет ждать эту блокировку до тех пор, пока
не останется потока, который просит блокировку READ
. Когда поток
имеет блокировку WRITE
и ждет, чтобы получить блокировку для
следующей таблицы в списке таблиц блокировки, все другие потоки будут ждать
освобождения блокировки WRITE
. Если это становится серьезной
проблемой для Вашей прикладной программы, Вы должны рассмотреть
преобразование некоторых из Ваших таблиц в транзакционно-безопасные.
Вы можете безопасно уничтожать поток, который ждет блокировку таблицы, с
помощью команды KILL
. Подробности в разделе
"4.9 Синтаксис KILL
".
Обратите внимание, что Вы НЕ должны блокировать таблицы,
которые Вы используете с INSERT DELAYED
. Это потому, что в этом
случае INSERT
выполняется отдельным потоком.
Обычно Вы не должны блокировать таблицы, поскольку все одиночные
инструкции UPDATE
атомные: никакой поток не может сталкиваться с
любым другим, в настоящее время выполняющим инструкции SQL. Имеется несколько
случаев, когда стоит блокировать таблицы:
READ
таблицу, и никакой поток не сможет читать блокированную на
WRITE
таблицу. Причина того, что некоторые вещи выполняются
быстрее под LOCK TABLES
в том, что MySQL не будет сбрасывать на
диск кэш ключей для блокированных таблиц до вызова UNLOCK TABLES
(обычно кэш ключей сбрасывается на диск после каждой инструкции SQL). Это
ускоряет вставки, удаления и обновления на таблицах 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()
. Эти блокировки
сохранены в таблице hash на сервере и выполнены через вызовы
pthread_mutex_lock()
и pthread_mutex_unlock()
для
ускорения работы. Подробности в разделе
"6.5.2 Дополнительные функции
".
Вы можете блокировать все таблицы во всех базах данных с блокировками
чтения командой FLUSH TABLES WITH READ LOCK
. Подробности в
разделе "4.8 Синтаксис FLUSH
".
Это очень удобный способ получать резервные копии, если Вы имеете файловую
систему, подобную Veritas, которая может делать кадры состояния.
ОБРАТИТЕ ВНИМАНИЕ: LOCK TABLES
не
транзакционно-безопасна и автоматически завершает любые активные транзакции
перед попыткой блокировать таблицы.
SET TRANSACTION
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
Устанавливает уровень изоляции транзакции глобально, для целого сеанса или следующей транзакции.
Заданное по умолчанию поведение должно установить уровень изоляции для следующей (не начатой) транзакции.
Если Вы устанавливаете привилегию GLOBAL
, это будет
воздействовать на все новые созданные потоки. Вы будете нуждаться в
привилегии PROCESS
, чтобы сделать это.
Установка привилегии SESSION
будет воздействовать на
следующую и на все будущие транзакции.
HANDLER
HANDLER table OPEN [AS alias] HANDLER table READ index {=|>=|<=|<} (value1, value2, ...) [WHERE ...] [LIMIT ...] HANDLER table READ index {FIRST|NEXT|PREV|LAST} [WHERE ...] [LIMIT ...] HANDLER table READ {FIRST|NEXT} [WHERE ...] [LIMIT ...] HANDLER table CLOSE
Команда HANDLER
обеспечивает прямой доступ к интерфейсу
таблиц MySQL, совершая обход SQL-оптимизатора. Таким образом, это работает
быстрее, чем SELECT.
Первая форма инструкции HANDLER
открывает таблицу, делая ее
доступной через следующий вызов HANDLER ... READ
.
Вторая форма выбирает одну (или определенное предложением
LIMIT
число) строку, где определенный индекс соответствует
условию и определение WHERE
выполнено. Если индекс состоит из
нескольких частей (промежутки более, чем в несколько столбцов) значения
должны быть определены в разделяемом запятыми списке.
Третья форма выбирает одну (или определенное предложением
LIMIT
число) строку в индексном порядке, соответствуя условиям
определения WHERE
запроса.
Четвертая форма (без индексной спецификации) выбирает одну (или
определенное предложением LIMIT
число) строку из таблицы в
естественном порядке строк (как они сохранены в файле данных), соответствуя
условиям определения WHERE
запроса. Это быстрее, чем
HANDLER table READ index
, когда нужен полный просмотр таблицы.
Последняя форма закрывает таблицу, открытую с помощью вызова
HANDLER ... OPEN
.
HANDLER
это инструкция низкого уровня, например, она не
обеспечивает непротиворечивость. Вызов HANDLER ... OPEN
НЕ блокирует таблицу. Так что другие потоки могут работать с
таблицей и менять данные.
Начиная с Version 3.23.23, MySQL имеет поддержку для полнотекстовой
индексации и поиска. Полнотекстовые индексы в MySQL представляют собой индекс
типа FULLTEXT
. Индекс FULLTEXT
может быть создан из
столбцов VARCHAR
и TEXT
в вызове CREATE
TABLE
или добавлен позже через инструкции ALTER TABLE
или
CREATE INDEX
. Для больших наборов данных, добавление индекса
FULLTEXT
через ALTER TABLE
(или CREATE
INDEX
) намного быстрее, чем вставка строк в пустую таблицу с индексом.
Поиск выполняется с помощью функции 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 -> (0,'MySQL Tutorial', 'DBMS stands for DataBase Management ...'), -> (0,'How To Use MySQL Efficiently', 'After you went through a ...'), -> (0,'Optimizing MySQL','In this tutorial we will show how to ...'), -> (0,'1001 MySQL Trick','1. Never run mysqld as root. 2. Normalize ...'), -> (0,'MySQL vs. YourSQL', 'In the following database comparison we ...'), -> (0,'MySQL Security', 'When configured properly, MySQL could be ...'); Query OK, 5 rows affected (0.00 sec) Records: 5 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 we ... | | 1 | MySQL Tutorial | DBMS stands for DataBase Management ... | +----+-------------------+---------------------------------------------+ 2 rows in set (0.00 sec)
Функция MATCH
соответствует запросу естественного языка для
текстовой совокупности AGAINST
, которая является просто набором
столбцов, покрытых индексом FULLTEXT
). Для каждой строки в
таблице это возвращает релевантность: меру подобия между текстом в этой
строке (в столбцах, которые являются частью совокупности) и запросом. Когда
это используется в предложении WHERE
(см. пример выше)
возвращенные строки автоматически сортируются с уменьшением релевантности.
Релевантность представлена неотрицательным числом с плавающей запятой.
Нулевая релевантность означает, что нет никакого подобия.
Вышеупомянутое представляет собой базисный пример использования функции
MATCH
. Строки будут возвращены с уменьшением релевантности.
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 | +----+-----------------------------------------+ 5 rows in set (0.00 sec)
Этот пример показывает, как найти релевантность. Поскольку предложения
WHERE
или ORDER BY
не присутствуют в запросе,
возвращенные строки не упорядочиваются.
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. Normalize ... | 1.5055546709332 | | 6 | When configured properly, MySQL could be ... | 1.31140957288 | +----+-----------------------------------------------+-----------------+ 2 rows in set (0.00 sec)
Это более сложный пример: запрос возвращает релевантность и дополнительно
сортирует строки с ее уменьшением. Чтобы достичь этого, нужно определить
MATCH
дважды. Обратите внимание, что это не вызовет никакой
перегрузки, так как оптимизатор MySQL обратит внимание, что эти два обращения
MATCH
идентичны, и вызовут код поиска только однажды.
MySQL использует очень простой синтаксический анализатор, чтобы расчленить текст на слова. Слово является любой последовательностью символов, чисел, знаков ' и _. Любое слово, которое присутствует в списке stopword или слишком короткое (3 символа или меньше), игнорируется.
Каждое правильное слово в совокупности и в запросе взвешивается, согласно значению в запросе или совокупности. Этим путем слово, которое присутствует во многих строках, будет иметь более низкий вес (и может даже иметь нулевой вес) потому, что оно имеет более низкое семантическое значение в этой специфической совокупности. Иначе, если слово редко, оно получит более высокий вес. Веса слов затем будут сложены, чтобы вычислить релевантность.
Такая методика работает лучше всего с большими совокупностями (фактически, это было тщательно настроено на этот путь). Для очень маленьких таблиц распределение слов не отражает адекватно их семантическое значение, и эта модель может производить причудливые результаты.
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL'); Empty set (0.00 sec)
Поиск слова MySQL
не производит никаких результатов в
вышеупомянутом примере. Слово MySQL
присутствует больше, чем в
половине строк, и обрабатывается как stopword (то есть с семантическим
значением, равным нулю).
Слово, которое соответствует половине строк в таблице, менее вероятно определяет релевантные документы. Фактически, наиболее вероятно, что поиск по нему найдет множество несоответствующих документов. Все мы знаем, что это случается очень часто, когда мы пробуем что-то поискать в Internet... Таким строкам были назначены низкие семантические значения в этом специфическом наборе данных.
MATCH
должны быть столбцами из
той же самой таблицы, которая является частью того же самого индекса.
AGAINST
должна быть строка-константа.Обратите внимание, что поиск был тщательно настроен для самой лучшей эффективности. Изменение заданного по умолчанию поведения будет, в большинстве случаев, делать результаты поиска хуже. Не изменяйте исходники MySQL, если Вы не знаете точно, что Вы делаете!
myisam/ftdefs.h
строкой
#define MIN_WORD_LEN 4Измените это на значение, которое Вы предпочитаете, перекомпилируйте MySQL и пересоздайте индексы
FULLTEXT
.
myisam/ft_static.c
.
Поменяйте его по своему вкусу, пересоберите MySQL и пересоздайте индексы
FULLTEXT
.
myisam/ftdefs.h
:
#define GWS_IN_USE GWS_PROBна
#define GWS_IN_USE GWS_FREQПосле этого пересоберите MySQL. Индексы в этом случае пересоздавать не надо.
Этот раздел включает список свойств, которые уже реализованы в версии 4.0. Здесь также описано, что еще планируется сделать.
REPAIR TABLE
и ALTER TABLE
работают с
индексами FULLTEXT
, а OPTIMIZE TABLE
с индексами
FULLTEXT
теперь работает в 100 раз быстрее.
MATCH ... AGAINST
поддерживает следующие
boolean operators:
+
слово означает, что слово должно
присутствовать в каждой возвращенной строке.
-
слово означает, что слово не должно
присутствовать в каждой возвращенной строке.
<
и >
могут использоваться, чтобы
уменьшить и увеличить вес слова в запросе.
~
может использоваться, чтобы назначить
отрицательный вес слову.
*
является оператором усечения.ft_dump
добавлена для индексных операторов низкого
уровня FULLTEXT
(запросы, дампы, статистика).FULLTEXT
.
()
в булевом поиске.
FULLTEXT
(но очень медленно).
MERGE
.
FULLTEXT
в вызов CREATE/ALTER TABLE
).MySQL имеет продвинутую, но ненормативную систему защиты и привилегий. Этот подробно раздел описывает, как она работает.
GRANT
и REVOKE
GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name|*|*.*|db_name.*} TO user_name [IDENTIFIED BY 'password'] [, user_name [IDENTIFIED BY 'password'] ...] [REQUIRE {SSL|X509} [ISSUER issuer] [SUBJECT subject]] [WITH GRANT OPTION] REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name|*| *.*|db_name.*} FROM user_name [, user_name ...]
GRANT
реализован в MySQL Version 3.22.11 или позже. Для более
ранних версий MySQL инструкция GRANT
не делает ничего.
Команды GRANT
и REVOKE
позволяют администраторам
системы создавать пользователей, предоставлять и отменять права на
MySQL-пользователей в четырех уровнях привилегий:
mysql.user
.
mysql.db
и
mysql.host
.
mysql.tables_priv
.
mysql.columns_priv
.Если Вы даете привилегии пользователю, который не существует, он будет автоматически создан.
Для инструкций GRANT
и REVOKE
аргумент
priv_type
может быть определен как любой из следующего списка:
ALL PRIVILEGES FILE RELOAD ALTER INDEX SELECT CREATE INSERT SHUTDOWN DELETE PROCESS UPDATE DROP REFERENCES USAGE
ALL
представляет собой синоним для
ALL PRIVILEGES
. REFERENCES
пока не реализовано.
USAGE
в настоящее время представляет собой синоним для
``no privileges''. Это может быть применено, когда Вы хотите создать
пользователя, который не имеет никаких привилегий.
Чтобы отменять привилегию предоставленную командой grant,
используйте значение priv_type
параметра GRANT
OPTION
:
REVOKE GRANT OPTION ON ... FROM ...;
Значения priv_type
, которые Вы можете определять для таблицы:
SELECT
, INSERT
, UPDATE
,
DELETE
, CREATE
, DROP
,
GRANT
, INDEX
и ALTER
.
Значения priv_type
, которые Вы можете определять для столбца
(то есть, когда Вы используете аргумент column_list
):
SELECT
, INSERT
и UPDATE
.
Вы можете устанавливать глобальные привилегии, используя синтаксис
ON *.*
. Вы можете устанавливать привилегии базы данных,
используя синтаксис ON db_name.*
. Если Вы определяете
ON *
, и Вы имеете текущую базу данных, Вы установите привилегии
именно для этой базы данных. ПРЕДУПРЕЖДЕНИЕ: Если Вы
определяете ON *
, и Вы не имеете текущей базы данных,
Вы будете воздействовать на глобальные привилегии!
Чтобы приспосабливать предоставление прав на пользователей с произвольных
компьютеров, MySQL поддерживает определение значения user_name
в
форме user@host
. Если Вы хотите определять строку
user
или строку host
, содержащую специальные или
групповые символы (например, `-'), Вы можете цитировать имя
пользователя или хоста (например, 'test-user'@'test-hostname'
).
Вы можете определять групповые символы в hostname. Например,
user@"%.joker.botik.ru"
применяется к user
для
любого компьютера в домене joker.botik.ru
, а
user@"144.155.166.%"
будет применено к user
с любой
машины в сети 144.155.166
класса C.
Простая форма user
представляет собой синоним для
user@"%"
. ОБРАТИТЕ ВНИМАНИЕ: Если Вы позволяете
анонимным пользователям соединяться с сервером MySQL (что является значением
по умолчанию), Вы должны также добавить всех локальных пользователей как
user@localhost
потому, что иначе анонимная запись в таблице
mysql.user
будет применяться, когда пользователь попробует
зарегистрироваться на сервере MySQL с локальной машины! Анонимные
пользователи определены вставкой записей с User=''
в таблицу
mysql.user
. Вы можете проверять, применяется ли это у Вас,
выполняя такой запрос:
mysql> SELECT Host,User FROM mysql.user WHERE User='';
В настоящий момент GRANT
поддерживает имена хоста, базы
данных, таблицы и столбца длиной только до 60 символов. Имя пользователя
может быть длиной до 16 символов.
Привилегии для таблицы или столбца сформированы из логического ИЛИ (OR)
привилегий в каждом из четырех уровней привилегии. Например, если таблица
mysql.user
определяет, что пользователь имеет глобальную
привилегию select, это не может быть отменено записью на
других уровнях доступа!
Привилегии для столбца могут быть вычислены следующим образом:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
В большинстве случаев Вы предоставляете права пользователю только в одном из уровней привилегии, так что обычно это просто. Детали проверяющей привилегии процедуры подробно рассмотрены в разделе "10 Общие проблемы защиты и система привилегий доступа MySQL".
Если Вы предоставляете привилегии для комбинации user/hostname, которая не
существует в таблице mysql.user
, запись будет добавлена и
останется там пока ее не удалят командой DELETE
. Другими
словами, GRANT
может создавать записи в таблице
user
, но REVOKE
не будет удалять их. Вы должны
делать это явно, используя вызов DELETE
.
В MySQL Version 3.22.12 или позже, если новый
пользователь создан, или если Вы имеете глобальные привилегии, пароль
пользователя будет установлен в пароль, определенный предложением
IDENTIFIED BY
, если оно задано. Если пользователь уже имел
пароль, он будет заменен новым.
ПРЕДУПРЕЖДЕНИЕ: Если Вы создаете нового пользователя, но
не определяете предложение IDENTIFIED BY
, пользователь не имеет
никакого пароля. Это опасно.
Пароли также могут быть установлены командой SET PASSWORD
.
Подробности в разделе "14.5.6 Синтаксис
SET
".
Если Вы предоставляете привилегии для базы данных, запись в таблице
mysql.db
будет создана, если необходимо. Когда все привилегии
для базы данных будут удалены с помощью REVOKE
, эта запись тоже
будет удалена автоматически.
Если пользователь не имеет привилегий на таблице, данная таблица не
отображается вообще, когда пользователь запрашивает список таблиц (например,
инструкцией SHOW TABLES
).
Предложение WITH GRANT OPTION
дает пользователю способность
передать другим пользователям любые привилегии, которые этот пользователь
имеет в определенном уровне доступа. Вы должны быть внимательным к тому, кому
Вы даете привилегию grant, поскольку два пользователя с
различными привилегиями могут быть способны соединить свои привилегии!
Вы не можете предоставлять другому пользователю привилегию, которую Вы не имеете сами. Привилегия grant позволяет Вам передавать только те привилегии, которыми Вы реально обладаете.
Знайте, что, когда Вы предоставляете пользователю привилегию
grant в специфическом уровне привилегии, любые привилегии,
которые пользователь уже имеет (или получит в будущем!) в этом уровне также
могут передаваться этим пользователем кому угодно. Предположите, что Вы
предоставляете пользователю привилегию insert на базе
данных. Если Вы затем предоставляете привилегию select на
базе данных и определяете WITH GRANT OPTION
, пользователь сможет
передавать не только привилегию select, но и
insert! Если Вы затем предоставляете ему еще и привилегию
update на базе данных, этот пользователь сможет передавать
insert, select и update.
Вы не должны предоставлять привилегию alter нормальному пользователю. Если Вы это сделаете, пользователь может попробовать разрушить систему привилегии, переименовывая таблицы!
Обратите внимание, что, если Вы используете привилегии столбца или таблицы даже для одного пользователя, сервер исследует привилегии столбца и таблицы для всех пользователей, и это замедлит немного MySQL.
Когда mysqld
запускается, все привилегии читаются в память.
Привилегии, связанные с базами данных, таблицами и столбцами начинают
действовать сразу же, а связанные с пользователями сработают, когда
пользователь соединится с сервером в следующий раз. Модификации к таблицам
предоставления, которые Вы выполняете, используя GRANT
или
REVOKE
воспринимаются сервером немедленно. Если Вы изменяете
таблицы предоставления вручную (используя INSERT
,
UPDATE
и т.д.), Вы должны выполнить инструкцию
FLUSH PRIVILEGES
или запустить команду
mysqladmin flush-privileges
, чтобы сервер перезагрузил все
таблицы предоставления привилегий.
Самые большие различия между ANSI SQL и MySQL
версиями оператора GRANT
:
TRIGGER
, EXECUTE
и
UNDER
из ANSI SQL.
INSERT
только на части
столбцов в таблице, Вы можете выполнять инструкции INSERT
относительно таблицы: столбцы, для которых Вы не имеете привилегию
INSERT
будут установлены к их значениям по умолчанию. ANSI SQL
требует, чтобы Вы имели привилегию INSERT
на всех столбцах.
REVOKE
или правкой таблиц предоставления привилегий MySQL.Имеются несколько различий между использованием имен и паролей MySQL и Unix или Windows:
-u
или --user
. Это означает, что Вы не можете
делать базу данных безопасной всегда, если все имена пользователей MySQL не
имеют паролей. Любой может пытаться соединиться с сервером, используя любое
имя, и это получиться, если использовано имя, которое не имеет пароля.
PASSWORD()
и ENCRYPT()
в разделе
"6.5 Прочие функции".
Обратите внимание, что, даже если пароль сохранен в зашифрованном виде,
знания именно зашифрованного пароля вполне достаточно, чтобы соединиться с
сервером MySQL!Пользователи MySQL и их привилегии обычно создаются командой
GRANT
. Подробности в разделе "10.1
Синтаксис GRANT
и REVOKE
".
Когда Вы входите в систему на сервере MySQL с помощью клиента командной
строки, Вы должны определить пароль с помощью опции
--password=your-password
. Подробности изложены в разделе
"10.7 Связь с сервером MySQL":
mysql --user=monty --password=guess database_name
Если Вы хотите, чтобы Вас запросили относительно пароля, Вы должны
использовать аргумент --password
:
mysql --user=monty --password database_name
Или в кратком виде:
mysql -u monty -p database_name
Обратите внимание, что в последнем примере пароль НЕ database_name.
Если Вы хотите использовать опцию -p
, чтобы задать пароль,
сделайте это так:
mysql -u monty -pguess database_name
На некоторых системах библиотечный вызов, который MySQL использует для запроса пароля, автоматически урежет пароль до длины в 8 символов. Внутренне MySQL не имеет ограничений на длину пароля.
Любой, использующий MySQL на компьютере, связанном с Internet, должен прочитать этот раздел, чтобы избежать наиболее общих ошибок защиты. Данный раздел включен сюда, главным образом, по той причине, что предоставлять привилегии может (а в ряде случаев и должен) не только администратор, но и некоторые доверенные пользователи, например, начальник проекта должен предоставить исполнителю необходимые для выполнения задачи привилегии.
Очень важно уделить внимание проблемам безопасности всего сервера (а не только MySQL) и защите от всех типов атак.
MySQL использует защиту, основанную на списках управления доступом (Access Control Lists ACL) для всех подключений, запросов и других операций, которые пользователь может пытаться выполнять. Имеется также поддержка для соединений, зашифрованных SSL между клиентами и сервером MySQL. Многие из понятий, обсуждаемых здесь, не специфические для MySQL: те же самые общие идеи применимы вообще почти ко всем прикладным программам.
При запуске MySQL следуйте этим руководящим принципам:
user
В БАЗЕ ДАННЫХ mysql
!
GRANT
и
REVOKE
используются для управления доступом к MySQL. Не
предоставляйте большие привилегии, чем необходимо. Никогда не предоставляйте
привилегии всем хостам.
Контрольный список:
mysql -u root
. Если Вы способны соединиться
успешно с сервером без запроса о пароле, Вы имеете проблемы. Любой может
соединяться с Вашим сервером MySQL как MySQL пользователь root
с полными привилегиями! Поставьте пароль пользователя.
SHOW GRANTS
и проверьте, кто имеет
доступ к какой базе данных. Удалите те привилегии, которые не являются
необходимыми, с помощью команды REVOKE
.MD5()
или другую одностороннюю хеш-функцию.
nmap
. MySQL по умолчанию использует порт 3306. Этот порт
должен быть недоступен кому попало. Другой простой способ проверить, является
или нет Ваш порт MySQL открытым, состоит в том, чтобы попробовать следующую
команду с некоторой удаленной машины, где server_host
задает
имя хоста Вашего сервера MySQL:
shell> telnet server_host 3306Если Вы получаете подключение и некоторые символы, порт открыт, и должен быть закрыт на Вашем firewall или маршрутизаторе, если Вы не имеете причин хранить его открытым. Если
telnet
только висит или от подключения
отказываются, все ХОРОШО; порт блокирован.; DROP DATABASE mysql;
''.
Также не забудьте проверять числовые данные. Иногда помогает заключить все
числовые значения в апострофы. Например: SELECT * FROM table WHERE
ID='234'
вместо SELECT * FROM table WHERE ID=234
.
MySQL автоматически преобразует эту строку в число и удаляет нечисловые
символы из нее. Контрольный список:
%22
(`"'), %23
(`#') и %27
(`'').
addslashes()
. Начиная с PHP 4.0.3,
появилась функция mysql_escape_string()
, которая основана на
одноименной функции в MySQL C API.mysql_escape_string()
.escape
и quote
для потоков запроса.quote()
.PreparedStatement
.tcpdump
и
strings
. Для большинства случаев Вы можете проверять, шифрованы
или нет потоки данных MySQL, выдавая команду:
shell> tcpdump -l -i eth0 -w - src or dst port 3306|stringsЭто работает под Linux и должно работать с маленькими модификациями под другими системами. Если Вы не видите данные, это не всегда означает, что они фактически зашифрованы. Если Вы нуждаетесь в хорошей защите, Вы должны проконсультироваться с экспертом защиты.
Когда Вы соединяетесь с сервером MySQL, Вы обычно должны использовать пароль. Он не передается открытым текстом, однако, алгоритм шифрования не очень силен, и с некоторым усилием умный нападаюший может расколоть пароль, если может перехватить трафик. Если подключение между пользователем и сервером проходит недоверенную сеть, Вы должны использовать SSH-туннель, чтобы шифровать связь. Увы, хакеры сделали шифрование совершенно мирной связи обычным делом. А думали ли мы все, что через три года будем совершенно спокойно воспринимать шифрование данных не в военных системах, а дома?
Вся другая информация будет перемещена как текст, который может читаться
любым, кто способен наблюдать подключение. Если Вы обеспокоены относительно
этого, Вы можете использовать сжатый протокол (в MySQL версии 3.22 и выше),
чтобы делать такое чтение намного тяжелее. Чтобы сделать связь более
безопасной, Вы должны использовать ssh
. Вы можете скачать
исходные тексты клиентской части ssh
с
http://www.openssh.org, коммерческая
версия клиента ssh
доступна на
http://www.ssh.com. Теперь Вы можете
получить шифрованное TCP/IP подключение к серверу MySQL.
Чтобы сделать систему MySQL безопасной, Вы должны внимательно рассмотреть следующие предложения:
mysql -u other_user db_name
, если этот самый
other_user
не имеет никакого пароля. Это общее поведение при
работе с прикладными программами клиент/сервер, где клиент может определять
любое имя пользователя.
root
.
Это очень опасно, потому что любой пользователь с привилегиями
FILE
будет способен создать файлы как root
(например, ~root/.bashrc
). Чтобы предотвращать это,
mysqld
откажется выполняться как root
, если это не
определено, непосредственно используя опцию --user=root
.
mysqld
может быть выполнен как обычный непривилегированный
пользователь. Вы можете также создать нового Unix-пользователя
mysql
, чтобы сделать все даже более безопасным. Если Вы
выполняете mysqld
как другой Unix-пользователь, Вы не должны
изменять имя пользователя root
в таблице user
потому, что имена MySQL-пользователей не имеют никакого отношения к именам
пользователей Unix. Чтобы запустить mysqld
как другой
пользователь Unix, добавьте строку user
, которая определяет имя
пользователя к группе [mysqld]
в файле /etc/my.cnf
или в файле my.cnf в каталоге данных сервера. Например:
[mysqld] user=mysqlЭто заставит сервер запускаться как обозначенный пользователь, неважно запускаете ли Вы его вручную, используя
safe_mysqld
или
mysql.server
. Подробности в разделе
"11.3.2 Как выполнить MySQL
как нормальный пользователь"..
--skip-symlink
). Это особенно важно, если Вы выполняете
mysqld
как root, так как любой пользователь, который имеет
доступ для записи к каталогам данных, может удалить любой файл в системе!
mysqld
является единственным, кому позволено чтение-запись в
каталогах баз данных.
mysqladmin processlist
показывает текст в настоящее время
выполняющихся запросов, так что любой пользователь, которому дозволено эту
команду выдавать, мигом увидит, что кто-то выдает запрос типа
UPDATE user SET password=PASSWORD('Ваш_надежный_пароль')
. Я
понимаю, что не все приходит в голову, но много систем взломали именно из-за
таких неочевидных дыр в защите. mysqld
резервирует подключение
для пользователей, которые имеют привилегию process, чтобы
MySQL-пользователь root
мог войти и работать, даже если все
нормальные подключения уже находятся в использовании.
mysqld
daemon! Чтобы сделать это
немного более безопасным, все файлы, сгенерированные
SELECT ... INTO OUTFILE
читаются кем угодно, и Вы не можете
записывать поверх существующих файлов.
Привилегия file может также
использоваться, чтобы читать любой файл, доступный для Unix-пользователя, от
имени которого выполняется сервер. Это может быть злоупотреблено, например,
используя LOAD DATA
, чтобы загрузить /etc/passwd в
таблицу, которая может затем читаться с помощью SELECT
.
max_user_connections
в mysqld
.mysqld
, связанные с защитойСледующие параметры mysqld
воздействуют на защиту:
--safe-show-database
SHOW DATABASES
возвращает только те базы
данных, для которых пользователь имеет некоторую привилегию.
--safe-user-create
GRANT
, если он не имеет права INSERT
на
таблице mysql.user
. Если Вы хотите давать пользователю доступ к
созданию новых пользователей с теми привилегиями, которые он имеет право
предоставить, Вы должны дать ему следующую привилегию:
GRANT INSERT(user) on mysql.user to 'user''hostname';Это гарантирует, что пользователь не может изменять любые столбцы привилегий непосредственно, а должен использовать команду
GRANT
, чтобы дать
привилегии другим пользователям.
--skip-grant-tables
mysqladmin flush-privileges
или mysqladmin reload
.
--skip-name-resolve
Host
в
таблицах предоставления привилегий должны быть IP-адресами или
localhost
.
--skip-networking
mysqld
должно быть выполнено через сокеты Unix. Эта опция очень
рекомендуется на системах, где позволяются только локальные запросы. Эта
опция не подходит для систем, которые используют MIT-PTHREADS потому, что
пакет MIT-PTHREADS не поддерживает Unix-сокеты.
--skip-show-database
SHOW DATABASES
не будет возвращать ничего.Первичная функция системы привилегий MySQL состоит в том, что она должна опознать пользователя, соединяющегося с данного компьютера, и сопоставить этого пользователя с привилегиями на базе данных типа select, insert, update и delete.
Дополнительные функциональные возможности включают способность иметь
анонимного пользователя и предоставлять привилегии для MySQL-функций, типа
LOAD DATA INFILE
, и административных операций.
Система привилегий MySQL гарантирует, что все пользователи могут делать точно те дела, которые им будут позволены. Когда Вы соединяетесь с сервером MySQL, Вы будете идентифицированы не только по логину, который ввели, но и по адресу хоста, с которого зашли в сеть.
MySQL позволяет Вам отличить пользователей с различных компьютеров, которые, случается, имеют то же самое имя, Вы можете предоставлять один набор привилегий для подключений с одной системы, и совсем другой для того же имени, но с другой машины.
Управление доступом MySQL включает две стадии:
Сервер использует таблицы user
, db
и
host
в базе данных mysql
на обеих стадиях
управления доступа. Поля в этих таблицах показаны ниже:
Имя таблицы | user |
db | host |
Поля контекста | Host |
Host | Host |
User | Db |
Db | |
Password | User | ||
Поля привилегий | Select_priv
| Select_priv | Select_priv |
Insert_priv | Insert_priv
| Insert_priv | |
Update_priv | Update_priv
| Update_priv | |
Delete_priv | Delete_priv
| Delete_priv | |
Index_priv | Index_priv |
Index_priv | |
Alter_priv | Alter_priv |
Alter_priv | |
Create_priv | Create_priv
| Create_priv | |
Drop_priv | Drop_priv |
Drop_priv | |
Grant_priv | Grant_priv |
Grant_priv | |
References_priv | |||
Reload_priv | |||
Shutdown_priv | |||
Process_priv | |||
File_priv |
Для второй стадии управления доступом (проверка запроса) сервер может,
если запрос включает таблицы, дополнительно консультироваться с таблицами
tables_priv
и columns_priv
. Поля этих таблиц:
Имя таблицы | tables_priv |
columns_priv |
Поля контекста | Host |
Host |
Db | Db | |
User | User
| |
Table_name | Table_name |
|
Column_name | ||
Поля привилегий | Table_priv
| Column_priv |
Column_priv | ||
Прочие поля | Timestamp |
Timestamp |
Grantor |
Каждая таблица содержит поля области (контекста) и поля привилегий.
Поля контекста определяют область (контекст) каждой записи в таблицах, то
есть тот контекст, в котором применяется данная запись. Например, запись в
таблице user
со значениями Host
и User
'thomas.joker.botik.ru'
и 'bob'
соответственно
использовалась бы для подтверждения подключений, сделанных на сервер
пользователем bob
с компьютера thomas.joker.botik.ru
.
Точно так же запись таблицы db
с полями Host
,
User
и Db
, выставленными соответственно в
thomas.joker.botik.ru
, bob
и reports
,
использовалась бы, когда bob
соединяется с компьютера
thomas.joker.botik.ru
, чтобы обратиться к базе данных отчетов
(reports
). Таблицы tables_priv
и
columns_priv
хранят поля области (контекста), указывающие
таблицы или комбинации таблицы/столбца, к которым применяется каждая запись.
Для целей проверки доступа значения Host
нечувствительны к регистру. Зато User
, Password
,
Db
и значения Table_name
еще как чувствительны!
Column_name
нечувствительны в MySQL версии 3.22.12 или позже.
Поля привилегий указывают привилегии, предоставленные записью таблицы, то есть какие операции могут выполняться. Сервер объединяет информацию из различных таблиц предоставления привилегий, чтобы сформировать полное описание прав данного пользователя. Правила, используемые, чтобы это сделать, подробно описаны в разделе "10.9 Контроль доступа, стадия 2: Проверка запросов".
Поля контекста представляют собой строки, объявленные как показано ниже. Значение по умолчанию для каждой: пустая строка:
Имя поля | Тип | |
Host | CHAR(60) | |
User | CHAR(16) | |
Password | CHAR(16) | |
Db | CHAR(64) |
(CHAR(60) для таблиц tables_priv и
columns_priv ) |
Table_name | CHAR(60) | |
Column_name | CHAR(60) |
В таблицах user
, db
и host
все поля
привилегий объявлены как ENUM('N','Y')
: каждое может иметь
значение 'N'
или 'Y'
, значение по умолчанию
'N'
.
В таблицах tables_priv
и columns_priv
поля
привилегий объявлены как поля SET
:
Имя таблицы | Имя поля | Возможные элементы набора |
tables_priv | Table_priv |
'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant',
'References', 'Index', 'Alter' |
tables_priv | Column_priv |
'Select', 'Insert', 'Update', 'References' |
columns_priv | Column_priv |
'Select', 'Insert', 'Update', 'References' |
Сервер использует таблицы предоставления подобно этому алгоритму:
user
определяют,
позволять или отклонить входящие подключения. Для позволенных подключений
любые привилегии, предоставленные в таблице user
, указывают
глобальные привилегии пользователя. Эти привилегии обращаются ко всем
базам данных на сервере.
db
и host
используются вместе:
db
определяют, которые
пользователи к каким базам данных с каких компьютеров могут обращаться. Поля
привилегий определяют, какие операции позволяются.
host
используется как расширение таблицы
db
, когда Вы хотите использовать запись из таблицы
db
, чтобы обратиться к нескольким компьютерам. Например, если Вы
хотите, чтобы пользователь мог работать с базой данных с нескольких
компьютеров в Вашей сети, оставьте значение Host
пустым в записи
пользователя таблицы db
, затем заполните таблицу
host
, создав в ней запись для каждого из компьютеров. Этот
механизм описан более подробно в разделе
"10.9 Контроль доступа,
стадия 2: Проверка запросов".tables_priv
и columns_priv
подобны
таблице db
, но более точны: они применяются в уровнях столбца и
таблицы, а не на уровне всей базы данных.Обратите внимание, что административные привилегии
(reload, shutdown и т.д.) определены только
в таблице user
. Это потому, что административные операции
выполняются непосредственно на сервере и не специфические для базы данных,
так что нет никакой причины внести в список такие привилегии в других
таблицах. Фактически, только таблица user
должна использоваться,
чтобы определить, можете ли Вы выполнять административную операцию или нет.
Привилегия file также определена только в таблице
user
. Это не административная привилегия, но ведь и Ваша
способность читать или писать файлы на компьютере сервера также независима от
базы данных, к которой Вы обращаетесь!
Сервер mysqld
читает содержание таблиц только один раз, при
своем запуске. Изменения для таблиц предоставления привилегий вступают в
силу как сказано в разделе "10.11
Когда изменения привилегий вступают в силу".
Когда Вы изменяете содержание таблиц предоставления, стоит удостовериться,
что Ваши изменения установили привилегии так, как Вы хотите. Для справки в
диагностировании проблем обратитесь в раздел
"10.10 Причины ошибки Access
denied
. Проблемы с защитой подробно рассмотрены в разделе
"10.2 Как защитить MySQL от хакеров".
Полезный диагностический инструмент: скрипт mysqlaccess
,
который Yves Carlier предоставил для дистрибутива MySQL. Вызовите
mysqlaccess
с опцией --help
, чтобы выяснить, как
это работает. Обратите внимание, что mysqlaccess
проверяет
доступ, используя только таблицы user
, db
и
host
. Это не проверяет привилегии уровня столбца или таблицы.
Информация относительно привилегий пользователя сохранена в таблицах
user
, db
, host
,
tables_priv
и columns_priv
в базе данных
mysql
. Сервер MySQL читает содержание этих таблиц при запуске
и при обстоятельствах, перечисленных в разделе
"10.11 Когда изменения
привилегий вступают в силу".
Имена, используемые в этом руководстве, чтобы обратиться к привилегиям, обеспеченным MySQL, показываются ниже, наряду с именем столбца таблицы, связанным с каждой привилегией в таблицах предоставления привилегий и контекста, в котором данная привилегия применяется:
Привилегия | Столбец | Контекст (поле) действия |
select | Select_priv | таблицы |
insert | Insert_priv | таблицы |
update | Update_priv | таблицы |
delete | Delete_priv | таблицы |
index | Index_priv | таблицы |
alter | Alter_priv | таблицы |
create | Create_priv | базы данных, таблицы или индексы |
drop | Drop_priv | базы данных или таблицы |
grant | Grant_priv | базы данных или таблицы |
references | References_priv |
базы данных или таблицы |
reload | Reload_priv | серверное администрирование |
shutdown | Shutdown_priv | серверное администрирование |
process | Process_priv | серверное администрирование |
file | File_priv | доступ к файлам на сервере |
Привилегии select, insert, update и delete позволяют Вам выполнять операции на строках в существующих таблицах в базе данных.
Инструкции SELECT
требуют привилегии select
только, если они фактически восстанавливают строки из таблицы. Вы можете
выполнять некоторые инструкции SELECT
даже без разрешения
обратиться к любой из баз данных на сервере. Например, Вы могли бы
использовать клиента mysql
как простой калькулятор:
mysql> SELECT 1+1; mysql> SELECT PI()*2;
Привилегия index позволяет создавать или удалять индексы.
Привилегия alter позволяет использовать ALTER
TABLE
.
Привилегии create и drop позволяют создавать новые базы данных и таблицы или удалять существующие.
Обратите внимание, что, если Вы предоставляете привилегию
drop для базы данных mysql
пользователю, он
сможет удалить всю базу данных, в которой сохранены привилегии доступа MySQL!
Привилегия grant позволяет Вам давать другим пользователям те привилегии, которыми Вы непосредственно обладаете.
Привилегия file дает Вам разрешение читать и писать файлы
на сервере, используя инструкции LOAD DATA INFILE
и SELECT
... INTO OUTFILE
. Любой пользователь, кому эта привилегия
предоставляется, может читать или писать любой файл, который доступен на
чтение или запись серверу MySQL.
Оставшиеся привилегии используются для административных операций, которые
выполняются, используя программу mysqladmin
. Таблица ниже
показывает, какие команды mysqladmin
соответствуют привилегиям:
Привилегия | Команды, разрешенные держателям данной привилегии |
reload | reload ,
refresh , flush-privileges ,
flush-hosts , flush-logs и
flush-tables |
shutdown | shutdown |
process | processlist ,
kill |
Команда reload
сообщает, что сервер должен заново прочитать
таблицы предоставления привилегий. Команда refresh
сбрасывает на
диск все таблицы, закрывает и заново открывает журналы. Привилегия
flush-privileges
является синонимом для reload
.
Другие команды flush-*
выполняют функции, подобные
refresh
, но в более ограниченном контексте, и могут быть
предпочтительны в некоторых ситуациях. Например, если Вы хотите только
сбросить на диск журналы, команда flush-logs
представляет собой
лучший выбор, чем refresh
.
Команда shutdown
выключает сервер.
Команда processlist
отображает информацию относительно
процессов, выполняющихся внутри сервера. Команда kill
уничтожает
потоки сервера. Вы всегда можете отображать или уничтожать Ваши собственные
процессы, но Вы нуждаетесь в привилегии process, чтобы
отображать или уничтожать процессы,
инициализированные другими пользователями.
Некоторые предосторожности при предоставлении привилегий:
SELECT
.
Это включает содержание всех баз данных на сервере!
mysql
могут использоваться, чтобы
изменить пароли и другую информацию привилегий доступа. Пароли сохранены
зашифрованными, так что злонамеренный пользователь не сможет просто читать
их, чтобы узнать простой текстовый пароль. Если пользователь может обращаться
к столбцу пароля в mysql.user
, он может использовать это, чтобы
зарегистрировать нового пользователя на сервере MySQL.Имеются некоторые вещи, которые Вы не можете делать с системой привилегий MySQL:
Клиент MySQL требует, чтобы Вы определили параметры подключения, когда Вы
хотите обратиться к серверу MySQL: компьютер, с которым надо связаться, Ваше
имя пользователя и пароль. Например, клиент mysql
может быть
запущен примерно так (факультативные параметры заключены в `[' и
`]'):
shell> mysql [-h host_name] [-u user_name] [-pyour_pass]
Альтернативные формы параметров -h
, -u
и
-p
: --host=host_name
,
--user=user_name
и --password=your_pass
. Обратите
внимание, что не должно быть никаких пробелов вообще между
-p
или --password=
и паролем.
ОБРАТИТЕ ВНИМАНИЕ: Определение пароля в командной строке
далеко не безопасно! Любой пользователь в Вашей системе может выяснить Ваш
пароль командой, наподобие ps auxww
.
mysql
использует значения по умолчанию для параметров
подключения, которые отсутствуют в командной строке:
localhost
.
-p
.Таким образом, для Unix-пользователя joe
эквивалентно:
shell> mysql -h localhost -u joe shell> mysql -h localhost shell> mysql -u joe shell> mysql
Другая MySQL-клиентура ведет себя аналогично.
На Unix-системах Вы можете определять различные значения по умолчанию, которые нужно использовать, когда Вы делаете подключение, так, чтобы не надо было вводить их в командную строку, каждый раз, когда Вы вызываете программу. Это может быть выполнено двумя разными способами:
[client]
файла конфигурации .my.cnf в Вашем
основном (домашнем) каталоге системы. Релевантный раздел файла мог бы
выглядеть следующим образом:
[client] host=host_name user=user_name password=your_pass
mysql
в переменной
MYSQL_HOST
. Имя пользователя MySQL может быть определено,
используя USER
(это только для Windows). Пароль может быть
определен, используя MYSQL_PWD
(но это опасно! Подробности по
этому вопросу чуть ниже).
Когда Вы пытаетесь соединиться с сервером MySQL, он принимает или отклоняет подключение, исходя из Вашей идентификации и того, можете ли Вы подтвердить ее паролем. Если нет, сервер отвергает доступ полностью. Иначе сервер принимает подключение, затем вводит Стадию 2 и ждет запросы.
Идентификация основана на двух частях информации:
Проверка выполняется, используя три поля области (контекста) таблицы
user
(Host
, User
и
Password
). Сервер принимает подключение только, если запись
таблицы user
соответствует Вашему hostname и имени пользователя,
и Вы вводите правильный пароль.
Значения в полях области (контекста) таблицы user
могут быть
определены следующим образом:
Host
может быть hostname, IP-адресом или
localhost
, чтобы указать локальный компьютер.
Host
.
'%'
поля Host
соответствует любому
имени хоста (hostname).
Host
означает, что привилегия должна быть
получена методом операции логического AND с записью в таблице
host
, которая соответствует данному имени. Вы можете найти
большее количество информации относительно этого в следующей главе.
Host
, определенных как IP, Вы можете определять netmask,
указывая, сколько бит адреса использовать для сетевого адреса. Например:
GRANT ALL PRIVILEGES on db.* to david@'192.58.197.0/255.255.255.0';Это позволит каждому желающему соединяться с IP, где следующее истинно:
user_ip & netmask = host_ip.В вышеупомянутом примере все IP в интервале 192.58.197.0-192.58.197.255 могут соединяться с сервером MySQL.
User
, но Вы можете определять пустое значение, которое
соответствует любому имени. Если запись таблицы user
, которое
соответствует входящему подключению, имеет пустое имя пользователя, такой
пользователь является анонимным (то есть, пользователем без имени), а не тем
пользователем, имя которого по умолчанию указывает клиент. Это означает, что
пустое имя пользователя применяется для всей дальнейшей проверки доступа (то
есть в течение Стадии 2).
Password
может быть пусто. Это не означает, что любой
пароль подойдет, это означает, что пользователь должен соединиться без того,
чтобы определить пароль.Непустые значения Password
представляют
зашифрованные пароли. MySQL не сохраняет пароли в форме открытого текста.
Пароли шифруются функцией PASSWORD()
. Зашифрованный пароль затем
используется, когда клиент/сервер проверяет, является ли пароль правильным
(это будет выполнено без передачи зашифрованного пароля по сети). Обращаю
внимание, что с точки зрения MySQL зашифрованный пароль представляет собой
РЕАЛЬНЫЙ пароль, так что Вы не должны давать доступ к нему кому попало! В
частности, не давайте нормальный доступ для чтения пользователям к таблицам
в базе данных mysql
!
Примеры ниже показывают, как различные комбинации значений
Host
и User
в записях таблицы user
обращаются к входящим подключениям:
Host значение | User
значение | Подключения, согласованные записью |
'thomas.joker.botik.ru' | 'lnz' |
lnz , связавшийся с машины thomas.joker.botik.ru |
'thomas.joker.botik.ru' | '' | Любой
пользователь, связавшийся с машины thomas.joker.botik.ru |
'%' | 'lnz' |
lnz , связавшийся с любой машины |
'%' | '' | Любой пользователь, связавшийся с любой машины |
'%.joker.botik.ru' | 'lnz' |
lnz , связавшийся с любой машины в домене joker.botik.ru |
'x.y.%' | 'lnz' | lnz
, связавшийся с x.y.net , x.y.com ,
x.y.edu и т.д. |
'144.155.166.177' | 'lnz' |
lnz , связавшийся с машины с IP-адресом
144.155.166.177 |
'144.155.166.%' | 'lnz' |
lnz , связавшийся с любой машины в сети 144.155.166
коасса C |
'144.155.166.0/255.255.255.0' | 'lnz'
| Аналогично предыдущему примеру |
Поскольку Вы можете использовать символы подстановки в IP-адресах в поле
Host
(например, 144.155.166.%
, чтобы
соответствовать каждому компьютеру в подсети), есть возможность, что кто-то
может попробовать эксплуатировать это свойство, именуя свой компьютер
144.155.166.somewhere.com
. Чтобы мешать таким попыткам, MySQL
отвергает соответствие имен хостов, которые начинаются с цифр и точки. Таким
образом, если Вы имеете компьютер с именем наподобие
3.6.foo.com
, его имя никогда не будет соответствовать столбцу
Host
таблиц. Только IP-адрес может соответствовать символам
подстановки в IP-адресе.
Входящее подключение может быть согласовано более, чем с одной записью в
таблице user
. Например, подключение пользователя
lnz
с машины thomas.joker.botik.ru
согласовано
несколькими записями, показанными выше. Как сервер выбирает, которую запись
использовать в данной ситуации? Он решает этот вопрос, сортируя таблицу
user
после ее чтения при запуске. Затем записи просматриваются в
отсортированном порядке. Используется первое совпадение.
Сортировка таблицы user
работает следующим образом.
Предположим, что таблица user
выглядит следующим образом:
+-----------+---------+- | Host | User | ... +-----------+---------+- | % | root | ... | % | alexmv | ... | localhost | root | ... | localhost | | ... +-----------+---------+-
Когда сервер читает таблицу, он располагает записи с наиболее
специфическими значениями Host
вначале ('%'
в
столбце Host
означает любой компьютер, а, стало быть, наименее
специфический). Записи с одинаковыми значениями Host
упорядочиваются с наиболее специфическими значениями User
(пустое значение User
означает любого пользователя, и наименее
специфическое). Возникающая в результате сортировки таблица user
выглядит следующим образом:
+-----------+---------+- | Host | User | ... +-----------+---------+- | localhost | root | ... | localhost | | ... | % | alexmv | ... | % | root | ... +-----------+---------+-
Когда
предпринято подключение, сервер просматривает отсортированные записи и
использует первое найденное соответствие. Для подключения пользователя
alexmv
с машины localhost
записи со значением
localhost
в столбце Host
окажутся первыми. Из них
подходит запись с пустым именем пользователя. Запись
'%'/alexmv
тоже подходит, но она не первая.
Имеется другой пример. Предположите, что таблица user
выглядит следующим образом:
+-----------------------+---------+- | Host | User | ... +-----------------------+---------+- | % | alexmv | ... | thomas.joker.botik.ru | | ... +-----------------------+---------+-
Отсортированная таблица будет выглядеть так:
+-----------------------+---------+- | Host | User | ... +-----------------------+---------+- | thomas.joker.botik.ru | | ... | % | alexmv | ... +-----------------------+---------+-
Подключение пользователя alexmv
с машины
thomas.joker.botik.ru
согласовано первой записью в то время, как
подключение alexmv
с машины rustex.botik.ru
соответствует второй записи.
Общее неправильное мнение состоит в том, что первыми будут использованы записи, в которых имя пользователя указано явно. Это не так! Только что было показано, что запись, использованная первой, имени пользователя в явном виде не имела вовсе.
Если Вы имеете проблемы при соединении с сервером, распечатайте таблицу
user
и отсортируйте ее вручную, чтобы видеть, где первое
соответствие будет сделано.
Как только Вы устанавливаете подключение, сервер вводит Стадию 2. Для
каждого запроса, который входит на подключении, сервер проверяет, имеете ли
Вы достаточные привилегии, чтобы выполнить его, основываясь на типе операции.
Эти привилегии могут исходить из любой из таблиц: user
,
db
, host
, tables_priv
или
columns_priv
. Таблицы предоставления привилегий управляются с
помощью команд GRANT
и REVOKE
. Подробности в
разделе "10.1 Синтаксис GRANT
и
REVOKE
".
Таблица user
предоставляет привилегии, которые назначены Вам
на глобальном основании, и это применяется независимо от того, какова текущая
база данных. Например, если таблица user
предоставляет Вам
привилегию delete, Вы можете удалять строки из любой базы
данных на сервере! Другими словами, привилегии таблицы user
являются глобальными. Мудро предоставить привилегии в таблице
user
только суперпользователям типа администраторов базы данных
или сервера в целом. Для других пользователей Вы должны оставить привилегии в
таблице user
в значении 'N'
и давать их только при
использовании таблиц db
и host
.
Таблицы
db
и host
предоставляют специфические для базы
данных привилегии. Значения в полях области могут быть определены так:
Host
и Db
любой таблицы.
'%'
в поле Host
таблицы
db
означает любой компьютер. Пустое значение Host
в таблице db
предписывает брать информацию из таблицы
host
.
'%'
или пустое значение Host
в таблице
host
означает любой компьютер.
'%'
или пустое значение Db
в любой таблице
означает любую базу данных.
User
в любой таблице
соответствует анонимному пользователю.
Таблицы db
и host
читаются и
сортируются при запуске сервера по тем же правилам, что и таблица
user
.
Таблицы tables_priv
и columns_priv
предоставляют специфические для таблицы и столбца
привилегии. Значения в полях области (контекста) могут быть определены так:
Host
любой таблицы.
'%'
или пустое значение Host
в любой таблице
означает любой компьютер.
Db
, Table_name
и Column_name
не могут содержать групповые символы или быть пустыми в любой таблице.Таблицы tables_priv
и columns_priv
сортируются
по полям Host
, Db
и User
. Это подобно
сортировке таблицы db
, хотя сортировка более простая потому, что
только поле Host
может содержать групповые символы.
Процесс проверки запроса описан ниже.
Для административных запросов (shutdown,
reload и т.д.), сервер проверяет только запись таблицы
user
потому, что это единственная таблица, которая определяет
административные привилегии. Доступ предоставляется, если запись позволяет
запрошенную операцию. Например, если Вы хотите выполнить mysqladmin
shutdown
, но Ваша запись в таблице user
не предоставляет
Вам привилегию shutdown, доступ будет отклонен без всякой
проверки таблиц db
или host
.
Для связанных с базой данных запросов (insert,
update и т.д.), сервер сначала проверит глобальные
привилегии (суперпользователя) по записям в таблице user
. Если
запись позволяет запрошенную операцию, доступ предоставляется. Если
глобальные привилегии в таблице user
недостаточны, сервер
определяет специфические для базы данных привилегии пользователя, проверяя
таблицы db
и host
:
db
соответствия полей
Host
, Db
и User
. Поля
Host
и User
должны соответствовать hostname
соединяющегося клиентского компьютера и MySQL-имени пользователя. Поле
Db
должно соответствовать базе данных, к которой пользователь
хочет обращаться. Если не имеется никакой записи для Host
и
User
, доступ будет отклонен.
db
и ее поле
Host
не пустое, то данная запись определяет специфические для
базы данных привилегии пользователя.
db
поле
Host
является пустым, это выражает, что таблица
host
перечисляет, какие именно компьютеры имеют доступ к базе
данных. В этом случае дальнейшая поисковая работа ведется в таблице
host
, чтобы найти соответствие полей Host
и
Db
. Если соответствий в таблице host
нет, доступ
будет отклонен. Если имеется соответствие, специфические для базы данных
привилегии пользователя будут вычислены как пересечение (но не
объединение!) привилегий в таблицах db
и host
,
то есть, привилегий, которые являются 'Y'
, в обеих записях.После определения специфических для базы данных привилегий,
предоставленных записями таблиц db
и host
, сервер
добавляет их к глобальным привилегиям, предоставленным таблицей
user
. Если результат позволяет запрошенную операцию, доступ
предоставляется. Иначе сервер проверяет пользовательские привилегии таблицы и
столбца в таблицах tables_priv
и columns_priv
соответственно, добавляя их к привилегиям пользователя.
Выражаясь в терминах двоичной логики, предшествующее описание того, как привилегии пользователя будут вычислены, может быть получено так:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
Не очень ясно, почему, если первоначально найдены глобальные привилегии
пользователя в таблице user
, недостаточные для запрошенной
операции, сервер добавляет их к привилегиям для базы данных, таблицы и
специфического столбца. Причина в том, что запрос может требовать больше, чем
один тип привилегии. Например, если Вы выполняете инструкцию
INSERT ... SELECT
, Вы нуждаетесь в привилегиях
insert и select. Ваши привилегии могут быть
такими, что запись таблицы user
предоставляет одну из них, а
запись таблицы db
разрешает другую. В этом случае Вы имеете
необходимые привилегии, чтобы выполнить запрос, но сервер должен просмотреть
все таблицы, чтобы разобраться в ситуации: привилегии, предоставленные
записями в обеих таблицах, должны быть объединены вместе.
Таблица host
может использоваться, чтобы поддерживать список
безопасных машин и серверов.
В TcX таблица host
хранит список всех машин в локальной сети.
Им предоставляют все привилегии.
Вы можете также использовать таблицу host
, чтобы указать
компьютеры, которые не безопасны. Предположите, что Вы имеете машину
public.your.domain
, которая размещена в общем домене, который Вы
не рассматриваете как безопасный. Вы можете позволять доступ всем компьютерам
в Вашей сети за исключением этой системы, используя записи в таблице
host
:
+--------------------+----+- | Host | Db | ... +--------------------+----+- | public.your.domain | % | ... (все привилегии установлены в 'N') | %.your.domain | % | ... (все привилегии установлены в 'Y') +--------------------+----+-
Естественно, Вы должны всегда проверять Ваши записи в таблицах
предоставления привилегий (например, используя mysqlaccess
),
чтобы удостовериться, что Ваши привилегии доступа фактически установлены так,
как Вы ожидаете.
Access denied
Если Вы сталкиваетесь с ошибкой Access denied
, когда пробуете
соединиться с сервером MySQL, посмотрите список ниже. Там приведены наиболее
часто встречающиеся проблемы. Большинство проблем тоносится к администратору,
и их решение находится вне прав доступа обычного пользователя. Так что, если
описанное ниже не помогает, обратитесь к администратору сервера.
shell> mysqladmin -u username -pxxxx ver Access denied for user: 'username@localhost' (Using password: YES)Это означает, что Вы используете неправильный пароль. Подробности в разделе "10.12 Установка паролей". Если Вы получаете вышеупомянутую ошибку, даже если Вы не определили пароль, это означает, что есть неправильный пароль в файле
my.ini
.
Вы можете отказаться от использования файлов опций с помощью параметра
командной строки --no-defaults
:
shell> mysqladmin --no-defaults -u username ver
PASSWORD()
, если Вы устанавливаете
пароль инструкцией INSERT
, UPDATE
или SET
PASSWORD
. Функция PASSWORD()
не нужна, если Вы
определяете пароль, используя инструкцию GRANT ... INDENTIFIED
BY
или вызов команды mysqladmin password
. Подробности в
разделе "10.12 Установка паролей".
localhost
представляет собой синоним для Вашего локального
hostname, а также заданный по умолчанию компьютер, с которым клиент пробует
соединяться, если Вы не определяете никакого компьютер явно. Однако,
подключения с localhost
не работают, если Вы работаете на
системе, которая использует MIT-pthreads (подключения localhost
сделаны, используя Unix-сокеты, которые не поддержаны MIT-pthreads). Чтобы
избежать этой проблемы на таких системах, Вы должны использовать опцию
--host
, чтобы назвать компьютер сервера явно. Это будет делать
TCP/IP-подключение (не через сокеты!) к серверу mysqld
. В этом
случае Вы должны иметь Ваш реальный hostname в записях таблицы
user
на компьютере сервера (даже если Вы запускаете клиент и
сервер на одной физической машине).
Access denied
при попытке
соединиться с базой данных с помощью вызова
mysql -u user_name db_name
, Вы можете иметь проблему с таблицей
user
. Обратитесь к администратору.
user
, которая
точно соответствует hostname и имени пользователя, которые были даны в
сообщении об ошибках. Например, если Вы получаете сообщение об ошибках,
которое содержит строку Using password: NO
, это означает, что Вы
пробовали войти в систему без пароля.
shell> mysqladmin -u root -pxxxx -h some-hostname ver Access denied for user: 'root' (Using password: YES)Это означает, что MySQL получил некоторую ошибку при попытке преобразования между IP и hostname. Если Ваш клиент и сервер исполняются на одной машине, свяжитесь с
localhost
.
mysql -u user_name test
корректно работает, а вот
mysql -u user_name other_db_name
работать и не думает, Вы не
имеете записи для other_db_name
, перечисленной в таблице
db
, обратитесь к администратору.
mysql -u user_name db_name
корректно работает, когда
выполнена на машине сервера, но
mysql -u host_name -u user_name db_name
не работает, когда
выполнена на другой машине, Вы имеете машину пользователя, не перечисленную в
таблицах user
или db
.
db
или host
:
Access to database deniedЕсли запись из таблицы
db
имеет пустое значение в столбце
Host
удостоверьтесь, что имеется одна или большее количество
соответствующих записей в таблице host
, определяющих, к которым
компьютерам применяется запись таблицы db
. Если Вы получаете
ошибку при использование команд SQL SELECT ... INTO OUTFILE
или
LOAD DATA INFILE
, Ваша запись в таблице user
,
вероятно, не имеет привилегию file.
Access denied
, когда Вы выполняете клиента без
параметров вообще, удостоверьтесь, что Вы не определили старый пароль в любом
из файлов опций!
mysql -u user_name db_name
или
mysql -u user_name -pyour_pass db_name
. Если Вы способны
подключить использование mysql
, имеется проблема с Вашей
программой, а не с привилегиями доступа. Обратите внимание, что нет пробелов
между -p
и паролем. Вы можете также использовать синтаксис
--password=your_pass
, чтобы определить пароль. Если Вы
используете единственную опцию -p
, MySQL запросит Вас
относительно ввода пароля.
mysqldump mysql
.
Как всегда регистрируйте Вашу проблему при помощи скрипта
mysqlbug
. Подробности в разделе
"Как сообщать о сбоях и проблемах".При запуске mysqld
все содержание таблиц предоставления
привилегий читается в память и становится действующим.
Модификации к таблицам предоставления, которые Вы выполняете используя
GRANT
, REVOKE
или SET PASSWORD
вступают в силу немедленно.
Если Вы изменяете таблицы предоставления вручную (используя операторы
INSERT
, UPDATE
), Вы должны выполнить инструкцию
FLUSH PRIVILEGES
или запустить
mysqladmin flush-privileges
, или mysqladmin reload
,
чтобы сообщить, что сервер должен перезагрузил таблицы предоставления. Иначе
Ваши изменения не будут иметь никакого эффекта, пока Вы не перезапустите
сервер. Если Вы изменяете таблицы предоставления вручную, но забываете
перезагружать привилегии, Вы будете часто задаваться вопросом, почему Ваши
изменения не делают вообще ничего!
Когда сервер обращает внимания, что таблицы предоставления были изменены, на существующие подключения пользователей это воздействуют следующим образом:
USE db_name
.Изменения глобальных привилегий и пароля воздействуют, когда пользователь соединится в следующий раз.
В большинстве случаев Вы должны использовать GRANT
, чтобы
установить Ваших пользователей и их пароли, так что следующее касается только
пользоваателей профессионального уровня.
Примеры в предшествующих разделах иллюстрируют важный принцип: когда Вы
сохраняете непустой пароль, используя инструкции INSERT
или
UPDATE
, Вы должны использовать функцию PASSWORD()
для его шифрования. Это потому, что таблица user
хранит пароли в
зашифрованной форме, а не как открытый текст. Если Вы забываете этот факт,
Вы, вероятно, будет пытаться устанавливать пароли подобно этому примеру:
shell> mysql -u root mysql mysql> INSERT INTO user (Host,User,Password) VALUES('%','alexmv','biscuit'); mysql> FLUSH PRIVILEGES;
Результат: открытый текст 'biscuit'
будет сохранен как пароль
в таблице user
. Когда пользователь alexmv
попытается подключиться к серверу, клиент mysql
шифрует его
пароль с помощью вызова функции PASSWORD()
, генерирует вектор
аутентификации, основанный на зашифрованном пароле и
произвольном числе, полученном с сервера, и посылает результат сервера. Он
использует значение password
в таблице user
(а там не зашифрованное значение biscuit
!),
чтобы выполнить те же самые вычисления, и сравнивает результаты. Разумеется,
они отличаются, и сервер отклоняет подключение (а Вы долго пытаетесь понять,
почему ничего не работает):
shell> mysql -u alexmv -pbiscuit test Access denied
Пароли должны быть зашифрованы, когда они вставлены в таблицу
user
, так что инструкция INSERT
должна быть
определена подобно этому:
mysql> INSERT INTO user (Host,User,Password) VALUES('%','alexmv',PASSWORD('biscuit'));
Вы должны также использовать функцию PASSWORD()
, когда Вы
применяете инструкции SET PASSWORD
:
mysql> SET PASSWORD FOR alexmv@"%" = PASSWORD('biscuit');
Если Вы устанавливаете пароли, используя инструкции
GRANT ... IDENTIFIED BY
или вызов команды mysqladmin
password
, функция PASSWORD()
уже не нужна: там она
вызывается автоматически, так что Вы должны определить пароль
biscuit
примерно так (вот что мешало не путать людей, а сделать
единую процедуру настройки?!):
mysql> GRANT USAGE ON *.* TO alexmv@"%" IDENTIFIED BY 'biscuit';
или примерно так:
shell> mysqladmin -u alexmv password biscuit
ОБРАТИТЕ ВНИМАНИЕ: PASSWORD()
не выполняет
шифрование пароля так, как это делается в Unix.
Нецелесообразно определять Ваш пароль так, что его могут увидеть другие пользователи. Методы, которые Вы можете использовать, чтобы определить Ваш пароль, когда Вы выполняете программы-клиенты, перечислены ниже, наряду с оценкой рисков каждого метода:
mysql.user
. Знание зашифрованного пароля для пользователя делает
возможным вход в систему под именем этого пользователя.
-pyour_pass
или
--password=your_pass
в командной строке. Это удобно, но опасно
потому, что Ваш пароль становится видимым программам состояния системы
(например, ps
), которые могут вызываться другими пользователями,
чтобы отобразить командные строки. Клиенты MySQL обнуляют командные строки,
чтобы их не было видно в процессе выполнения, но имеется краткий интервал, в
течение которого значение является видимым.
-p
или --password
(без
определенного значения your_pass
). В этом случае
программа-клиент запросит пароль с терминала:
shell> mysql -u user_name -p Enter password: ********Символы * представляют Ваш пароль. Это более безопасно, чем определить пароль прямо в командной строке потому, что это не видно другим пользователям. Однако, этот метод ввода пароля подходит только для программ, которые Вы выполняете в интерактивном режиме. Если Вы хотите вызывать клиента из скрипта, который выполняется не в интерактивном режиме, не имеется никакой возможности ввести пароль с терминала. На некоторых системах Вы можете даже обнаружить, что первая строка Вашего скрипта читается и неправильно интерпретируется как Ваш пароль!
[client]
файла
.my.cnf в Вашем основном каталоге:
[client] password=your_passЕсли Вы сохраняете Ваш пароль в файле .my.cnf, не должен быть доступен на чтение (тем более на запись) никому, кроме Вас. Удостоверьтесь, что режим доступа файла
400
или 600
.
MYSQL_PWD
, но этот метод должен рассматриваться как чрезвычайно
опасный и не должен использоваться. Некоторые версии ps
включают
опцию, чтобы отобразить среду управления процессами. Ваш пароль будет видим
всем желающим использовать такую команду. Даже на системах без такой версии
ps
неблагоразумно считать, что не имеется никакого другого
метода наблюдать среды процесса.В целом, самые безопасные методы состоят в том, чтобы иметь запрос программы-клиента для пароля или определять пароль в правильно защищенном файле личных настроек .my.cnf.
Эта глава описывает некоторые общие проблемы и сообщения об ошибках, с которыми пользователи столкнулись. Вы узнаете, как точно определить происходящее, и что делать, чтобы решить возникшую проблему. Вы также найдете здесь соответствующие решения для некоторых общих проблем.
Когда Вы сталкиваетесь с проблемами, первое, что Вы должны сделать, это однозначно выяснить, которая программа или часть оборудования вызывает данные проблемы.
kbd_mode -a
.
top
, ps
, taskmanager
или некоторую
подобную программу, чтобы установить, которая программа занимает весь CPU
или блокирует машину.
top
, df
или подобной
программы, не исчерпана ли память, место на диске или иной критический ресурс.
Если после того, как Вы исследовали все другие возможности и заключили, что проблема заключается в клиенте или сервере MySQL, самое время сделать отчет об ошибке для списка рассылки или группы поддержки. В отчете ошибки попробуйте дать очень детальное описание того, как система ведет себя, и что с ней случается. Вы должны также установить, почему Вы думаете, что это вызвано именно MySQL. Учтите все ситуации в этой главе. Установите любые проблемы точно, как они появляются, когда Вы исследуете вашу систему. Используйте метод "вырезать и вставить" для любого вывода, сообщений об ошибках из программ и журналов.
Если сбоит программа, всегда полезно знать следующее:
top
. Позвольте программе поработать некоторое время, она может
оценивать что-то тяжелое.
mysqld
вызывает проблемы, Вы можете сделать
mysqladmin -u root ping
или mysqladmin -u root
processlist
?
mysql
), когда Вы пробуете соединяться с сервером MySQL? Клиент
зависает? Вы получаете любой вывод из программы?При посылке отчета об ошибке Вы должны обязательно следовать правилам, описанным в этом руководстве.
Этот раздел перечисляет некоторые ошибки, с которыми пользователи часто сталкиваются. Здесь Вы найдете описания ошибок, и как решить проблему.
Access denied
Обратитесь к разделам
"10.5 Как работает система привилегий" и
особенно "10.10 Причины ошибки
Access denied
".
MySQL server has gone away
Наиболее общая причина для ошибки MySQL server has gone away
состоит в том, что у сервера кончилось время ожидания, и он закрыл
подключение. По умолчанию сервер закрывает подключение после 8 часов
отсутствия активности. Вы можете изменять срок, устанавливая переменную
wait_timeout
, когда Вы запускаете mysqld
Другая общая причина получения такой ошибки состоит в том, что Вы закрыли соединение, а теперь пробуете выполнить запрос на закрытом подключении.
Вы можете проверять, что MySQL работает, выполняя mysqladmin
version
и исследуя uptime.
Если Вы имеете скрипт, Вы только должны снова выдать запрос клиенту, чтобы сделать автоматическое переподключение.
Вы обычно можете получать следующие коды ошибки в этом случае:
CR_SERVER_GONE_ERROR | Клиент не может послать запрос на сервер. |
CR_SERVER_LOST | Клиент не получал ошибку при записи на сервер, но и не получил полный ответ (или любой ответ) на запрос. |
Вы можете также получать эти ошибки, если Вы посылаете неправильной или
слишком большой запрос серверу. Если mysqld
получает пакет,
который является слишком большим или вне правил, он считает, что что-то
пошло неправильно с клиентом и закрывает подключение. Если Вы нуждаетесь в
больших запросах (например, если Вы работаете с большими столбцами
BLOB
), Вы можете увеличить ограничение запроса, запуская
mysqld
с опцией -O max_allowed_packet=#
(по
умолчанию 1M). Память дополнительного пространства распределена по
требованию, так что mysqld
использует большее количество памяти
только, когда Вы выдаете большой запрос, или когда mysqld
должен
возвратить большую строку результатов!
Can't connect
to [local] MySQL server
Клиент MySQL под ОС Unix может соединяться с сервером mysqld
двумя различными способами: Unix-сокеты, которые подключают через файл в
файловой системе (значение по умолчанию /tmp/mysqld.sock) или по
протоколу TCP/IP, который соединяется через номер порта. Unix-сокеты быстрее,
чем TCP/IP, но могут использоваться только при соединении с сервером на том
же самом компьютере. Они применяются, если Вы не определяете hostname, или
если Вы определяете специальное имя localhost
.
Под Windows Вы можете соединяться только через TCP/IP, если сервер
mysqld
запущен под Win95/Win98. Если же использована NT, Вы
можете также соединяться с именованными каналами. Имя такого именованного
канала MySQL. Если Вы не задаете hostname при соединении с сервером, клиент
сначала попробует соединяться с именованным каналом, и если это не работает,
то соединится с TCP/IP портом. Вы можете заставить использовать именованный
канал под Windows, указав точку (.
) как hostname.
Сообщение error (2002) Can't connect to ...
обычно означает,
что не имеется сервера MySQL на системе, что Вы используете неправильный файл
сокета или не тот TCP/IP порт при попытке соединиться с mysqld
.
Начните с проверки (ps
или через администратор задач под
Windows), что вообще имеется процесс, управляющий mysqld
на
Вашем сервере! Если не имеется никакого процесса mysqld
, Вы
должны обратиться к администратору и попросить его запустить сервер.
Если процесс mysqld
работает, Вы можете проверять сервер,
пробуя различные подключения (номер порта и имя пути сокета):
shell> mysqladmin version shell> mysqladmin variables shell> mysqladmin -h `hostname` version variables shell> mysqladmin -h `hostname` --port=3306 version shell> mysqladmin -h 'ip for your host' version shell> mysqladmin --socket=/tmp/mysql.sock version
Обратите внимание на использование апострофов вместо кавычек с командой
hostname
: они заставляют вывод hostname
(то есть,
текущий hostname) вставиться в mysqladmin
.
Имеются некоторые причины, по которым может происходить ошибка Can't
connect to local MySQL server
:
mysqld
не запущен.
mysqld
использует пакет MIT-pthreads. Однако, все версии
MIT-pthreads не поддерживают Unix-сокеты. На системе без поддержки сокетов Вы
должны всегда определять hostname явно при соединении с сервером. Попробуйте
использовать эту команду, чтобы Ваше проверить подключение:
shell> mysqladmin -h `hostname` version
mysqld
, (по
умолчанию это /tmp/mysqld.sock). Вы могли бы иметь задачу для
планировщика cron
, которая удаляет старые файлы из каталога
/tmp, и сокет вместе с ними). Вы можете всегда выполнять
mysqladmin version
и проверять, что каталог сокета в самом деле
существует. Подробности в разделе
"11.4.5 Как защитить или
сменить файл сокета MySQL /tmp/mysql.sock".
mysqld
с опцией
--socket=/path/to/socket
. Если Вы изменяете имя пути сокета для
сервера, не забудьте поставить об этом в известность клиентов. Вы можете
сделать это, обеспечивая путь к сокету как параметр клиента. Подробности в
разделе "11.4.5 Как защитить
файл сокета MySQL /tmp/mysql.sock".
mysqld
(например, скриптом
mysql_zap
прежде, чем Вы сможете запустить новый сервер MySQL).
mysqld
так, чтобы он использовал каталог, к
которому Вы можете обращаться.Если Вы получаете сообщение об ошибке Can't connect to MySQL server
on some_hostname
, Вы можете попробовать следующие вещи, чтобы
выяснить, какова проблема:
telnet
your-host-name tcp-ip-port-number
с двойным нажатием
RETURN
. Если имеется сервер MySQL, слушающий на этом порте, Вы
должны получить ответ, который включает номер версии. Если Вы получаете
ошибку подобно telnet: Unable to connect to remote host: Connection
refused
, стало быть там не имеется никакого сервера. Куда он делся?
Это уже другой вопрос, ищите...
mysqld
на локальной машине и
проверить TCP/IP порт, на который mysqld
сконфигурирован
(переменная port
) с помощью mysqladmin variables
.
mysqld
не запущен с параметром
--skip-networking
.Host '...' is blocked
Если Вы получаете сообщение об ошибке:
Host 'hostname' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'
Это означает, что mysqld
получил много
(max_connect_errors
) запросов подключения с компьютера
hostname
, которые были прерваны в середине. После
max_connect_errors
потерпевших неудачу запросов
mysqld
считает, что что-то неправильно (подобно нападению
хакеров) и блокирует дальнейшие соединения с этой машины, пока кто-то не
выполняет команду mysqladmin flush-hosts
.
По умолчанию mysqld
блокирует компьютер после 10 ошибок
подключения. Вы можете легко корректировать это, запуская сервер так:
shell> safe_mysqld -O max_connect_errors=10000 &
Обратите внимание, что, если Вы получаете это сообщение об ошибках для
данного компьютера, Вы должны сначала проверить, что не имеется чего-нибудь
неправильного с TCP/IP подключениями. Если Ваши TCP/IP подключения не
работают, увеличение переменной max_connect_errors
не поможет!
Too many connections
Если Вы получаете ошибку Too many connections
, когда Вы
пробуете соединиться с MySQL, это означает, что уже имеется
max_connections
клиентов, работающих с сервером.
Если Вы нуждаетесь в большем количестве подключений, чем значение по
умолчанию (100), то перезапустите mysqld
с большим значением для
переменной max_connections
.
Обратите внимание, что mysqld
фактически позволяет
(max_connections
+1) подключений. Последнее подключение
зарезервировано для пользователя с привилегией process.
Не давая эту привилегию нормальным пользователям (они не должны нуждаться в
ней), администратор с этой привилегией может войти и использовать
SHOW PROCESSLIST
, чтобы выяснить то, что могло бы быть
неправильно. Подробности приведены в разделе "
4.10 Синтаксис команды SHOW
".
Максимальное количество подключений зависит от того, как хороша библиотека потоков на данной платформе. Linux или Solaris могут поддерживать 500-1000 одновременных подключений в зависимости от того, сколько RAM Вы имеете, и что Ваша клиентура делает.
Some non-transactional changed tables couldn't be rolled back
Если Вы получаете ошибку Warning: Some non-transactional changed
tables couldn't be rolled back
при попытке сделать
ROLLBACK
, это означает, что некоторые из таблиц, которые Вы
использовали, не поддерживали транзакции. На эти таблицы не будет
воздействовать инструкция ROLLBACK
.
Наиболее типичный случай, когда это случается: когда Вы пробовали
создавать таблицу типа, который не поддержан Вашей версией
mysqld
. Если mysqld
не поддерживает тип таблицы
(или если тип таблицы заблокирован опцией запуска), он взамен создаст таблицу
такого типа, который больше всего подходит к тому, который Вы запросили,
вероятно, это будет MyISAM
.
Вы можете проверять тип таблицы:
SHOW TABLE STATUS LIKE 'table_name'.Подробности в разделе "4.10.2
SHOW TABLE STATUS
".
Вы можете проверять, какие расширения поддерживает Ваша версия
mysqld
следующей командой:
show variables like 'have_%'
. Подробности в разделе
"4.10.4 SHOW VARIABLES
".
Out of memory
Если Вы выдаете запрос и получаете нечто вроде следующей ошибки:
mysql: Out of memory at line 42, 'malloc.c' mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k) ERROR 2008: MySQL client ran out of memory
Обратите внимание, что ошибка относится к клиенту mysql
.
Причина для этой ошибки: клиент не имеет достаточно памяти, чтобы сохранить
целиком полученный результат.
Чтобы выправить проблему, сначала проверьте, что Ваш запрос правилен.
Является ли приемлемым, чтобы он возвратил так много строк? Если да, Вы
можете использовать mysql --quick
, который использует
mysql_use_result()
, чтобы получить набор результатов. Это
помещает меньшее количество нагрузки на клиента (но больше на сервер).
Packet too large
Когда клиент MySQL или сервер mysqld
получает пакет больше,
чем max_allowed_packet
байт, он выдает ошибку Packet too
large
и закрывает подключение.
Если Вы используете клиента mysql
, Вы можете определять
больший буфер, запуская клиента командой
mysql --set-variable=max_allowed_packet=8M
.
Если Вы используете другую клиентуру, которая не позволяет Вам определять
максимальный размер пакета (типа DBI
), Вы должны установить
размер пакета, когда Вы запускаете сервер. Вы используете опцию командной
строки для mysqld
, чтобы установить
max_allowed_packet
к большему размеру. Например, если Вы
ожидаете сохранять полную длину BLOB
в таблицу, Вы будете должны
запустить сервер с опцией --set-variable=max_allowed_packet=16M
.
Вы можете также получать странные проблемы с большими пакетами, если Вы
используете большие blob'ы, но не дали mysqld
доступ к
достаточной памяти, чтобы обработать запрос. Если Вы подозреваете, что дело
обстоит именно так, попробуйте добавить ulimit -d 256000
к
скрипту safe_mysqld
и перезапустить mysqld
.
Начиная с MySQL 3.23.40
Вы получаете только ошибку
Aborted connection
при запуске mysqld
с опцией
--warnings
.
Если Вы находите ошибки, подобные следующей, в Вашем файле регистрации:
010301 14:38:23 Aborted connection 854 to db: 'users' user: 'josh'
Это означает, что что-то из следующего случилось:
mysql_close()
перед
выходом.
wait_timeout
или
interactive_timeout
без того, чтобы делать любые запросы.
Когда вышеупомянутое случается, переменная сервера
Aborted_clients
будет увеличена.
Переменная сервера Aborted_connects
растет:
connect_timeout
секунд, чтобы
получить подключенный пакет.Обратите внимание, что вышеупомянутое может указывать, что кто-то пробует врываться в Вашу базу данных!
Другие причины для проблем с клиентами и прерванными подключениями.
max_allowed_packet
слишком маленький, или запросы требуют
большее количество памяти, чем Вы имеете для mysqld
.The table is full
Эта ошибка происходит в старых версиях MySQL, когда расположенная в памяти
временная таблица становится больше, чем tmp_table_size
байт.
Чтобы избежать этой проблемы, Вы можете использовать опцию -O
tmp_table_size=#
, чтобы увеличить размер временной таблицы или
использовать опцию SQL_BIG_TABLES
прежде, чем Вы выдаете
проблематичный запрос.
Вы можете также запустить mysqld
с опцией
--big-tables
. Это действует точно также, как использование для
всех запросов SQL_BIG_TABLES
.
В MySQL Version 3.23 временная таблица в памяти будет автоматически
преобразована в дисковую MyISAM
после того, как размер таблицы
станет больше, чем tmp_table_size
.
Can't create/write to file
Если для некоторых запросов Вы получаете ошибку типа:
Can't create/write to file '\\sqla3fe_0.ism'.
Это означает, что MySQL не может создать временный файл для набора
результатов в заданном временном каталоге. Для исправления запустите
mysqld
с опцией --tmpdir=path
или добавьте к файлу
опцией сервера следующее:
[mysqld] tmpdir=C:/temp
Считается, что каталог c:\temp существует.
Проверьте также код ошибки, который Вы получаете через
perror
. Причиной может быть также полный диск;
shell> perror 28 Error code 28: No space left on device
Commands out of sync
Если Вы получаете Commands out of sync; You can't run this command
now
в Вашем коде пользователя, стало быть Вы вызываете функции
пользователя в неправильном порядке!
Это может случаться, например, если Вы используете
mysql_use_result()
и пробуете выполнять новый запрос прежде, чем
Вы вызвали mysql_free_result()
. Это может также случаться, если
Вы пробуете выполнять два запроса, которые возвращают данные, без
обязательного вызова функции mysql_use_result()
или
mysql_store_result()
между ними.
Ignoring user
Если Вы получаете следующую ошибку:
Found wrong password for user: 'some_user@some_host'; Ignoring user
Это означает, что, когда mysqld
запустился или перезагрузил
таблицы привилегий, он нашел запись в таблице user
с
недопустимым паролем. В результате запись просто игнорируется системой.
Возможные причины для этой проблемы:
mysqld
со старой
таблицей user
. Вы можете проверить это, выполняя mysqlshow
mysql user
, чтобы видеть, является ли поле пароля короче, чем 16
символов. Если это так, Вы можете исправлять это дело запуском скрипта
scripts/add_long_password
.
mysqld
с опцией --old-protocol
. Модифицируйте
пользователя в таблице user
с новым паролем или перезапустите
mysqld
с опцией --old-protocol
.
user
без того, чтобы использовать функцию PASSWORD()
. Примените
mysql
, чтобы модифицировать пользователя в таблице
user
с новым паролем. Удостоверьтесь, что вызвана функция
PASSWORD()
:
mysql> update user set password=PASSWORD('your password') where user='XXX';
Table 'xxx' doesn't exist
Если Вы получаете ошибку Table 'xxx' doesn't exist
или
Can't find file: 'xxx' (errno: 2)
, это означает, что таблица с
именем xxx
не существует в текущей (актуальной) базе данных.
Обратите внимание, что MySQL использует каталоги и файлы, чтобы сохранить базы данных и таблицы, так что имена баз данных и таблиц чувствительны к регистру! В Windows это не так, но все ссылки к данной таблице внутри запроса должны использовать тот же самый регистр.
Вы можете проверить, какие таблицы Вы имеете в текущей базе данных, через
SHOW TABLES
. Подробности в разделе "
4.10 Синтаксис SHOW
".
Can't initialize character set xxx
Если Вы получаете ошибку подобно:
MySQL Connection Failed: Can't initialize character set xxx
Это означает одно из следующего:
--with-charset=xxx
или --with-extra-charsets=xxx
.
Все стандартные двоичные файлы MySQL компилируются с
--with-extra-character-sets=complex
, что допускает поддержку для
всех многобайтных наборов символов.
mysqld
, и файлы определения набора символов не в том месте, где
клиент ожидает находить их. В этом случае Вы должны:
--character-sets-dir=path-to-charset-dir
.
Если Вы получаете ERROR '...' not found (errno: 23)
,
Can't open file: ... (errno: 24)
или любую другую ошибку с
errno 23
или errno 24
из MySQL, это означает, что
Вы не распределили достаточно описателей файла для MySQL. Вы можете
использовать утилитку perror
, чтобы получить описание того, что
код ошибки означает:
shell> perror 23 File table overflow shell> perror 24 Too many open files shell> perror 11 Resource temporarily unavailable
Проблема здесь состоит в том, что mysqld
пробует хранить
открытыми слишком много файлов одновременно. Вы можете сообщать, чтобы
mysqld
не открывал так много файлов сразу, или увеличить число
описателей файла, доступных для mysqld
.
Чтобы сообщать, чтобы mysqld
хранил открытым меньшее
количество файлов одновременно, Вы можете сделать кэш таблицы меньшим,
используя опцию -O table_cache=32
при вызове
safe_mysqld
(значение по умолчанию 64). Уменьшение значения
max_connections
также уменьшит число открытых файлов (значение
по умолчанию: 90).
Чтобы изменять число описателей файла, доступных
mysqld
, Вы можете использовать опцию
--open-files-limit=#
при вызове safe_mysqld
или
-O open-files-limit=#
при запуске mysqld
. Самый
простой способ сделать это состоит в том, чтобы добавить опцию к Вашему
файлу опции. Если Вы имеете старую версию mysqld
, которая не
поддерживает это, Вы можете отредактировать скрипт safe_mysqld
.
Имеется прокомментированная строка ulimit -n 256
в скрипте. Вы
можете удалять символ #
, чтобы раскомментировать строку и
изменить число 256, чтобы воздействовать на число описателей файла.
ulimit
(и open-files-limit
) может увеличивать
число описателей файла, но только до ограничения, наложенного операционной
системой. Имеется также жесткое ограничение, которое может быть перекрыто
только, если Вы запускаете safe_mysqld
или mysqld
как root (только не забудьте, что Вы должны также использовать опцию
--user=..
в этом случае). Если Вы должны увеличить ограничение
OS на число описателей файла, доступных каждому процессу, консультируйтесь с
документацией для Вашей операционной системы.
Обратите внимание, что, если Вы выполняете оболочку tcsh
,
ulimit
не будет работать! tcsh
также сообщит
неправильные значения, когда Вы спросите о текущих ограничениях. В этом
случае Вы должны запустить safe_mysqld
из sh
.
Если Вы компонуете Вашу программу и получаете ошибки для невызванных
символов, которые начинаются с mysql_
, подобно следующему:
/tmp/ccFKsdPa.o: In function `main': /tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init' /tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect' /tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect' /tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error' /tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'
Вы должны быть способны решить это, добавляя
-Lpath-to-the-mysql-library -lmysqlclient
В САМОМ КОНЦЕ
строки для компоновщика.
Если Вы получаете ошибки undefined reference
для функций
uncompress
или compress
, добавьте -lz
В САМОМ КОНЦЕ строки для компоновщика.
Если Вы получаете ошибки undefined reference
для функций,
которые должны существовать в Вашей системе, подобно connect
,
проверьте man-страницу для рассматриваемой функции, чтобы выяснить, какую
библиотеку Вы должны добавить.
Если Вы получаете ошибки undefined reference
для функций,
которые не существуют в Вашей системе, подобно следующему:
mf_format.o(.text+0x201): undefined reference to `__lxstat'
Это обычно означает, что библиотека компилируется на системе, которая не на 100%, совместима с Вашей. В этом случае Вы должны загрузить последний исходник MySQL и откомпилировать библиотеку непосредственно.
Если Вы пробуете выполнять программу и получаете ошибки для невызванных
символов, которые начинаются с mysql_
, или о том, что библиотека
mysqlclient
не может быть найдена, это означает, что Ваша
система не может найти общую библиотеку libmysqlclient.so
.
libmysqlclient.so
, к системной переменной
LD_LIBRARY_PATH
.
libmysqlclient.so
, к системной переменной
LD_LIBRARY
.
libmysqlclient.so
в место, где система ищет общие
библиотеки, например, /lib, и модифицируйте общедоступную
библиотечную информацию, выполняя ldconfig
.Другой способ решать эту проблему состоит в том, чтобы скомпоновать Вашу
программу статически с опцией -static
или удалить динамические
библиотеки MySQL перед компоновкой Вашего кода. Во втором случае Вы должны
убедиться, что никакие другие программы не используют динамические библиотеки!
MySQL-сервер mysqld
может быть запущен и выполняться любым
пользователем. Чтобы mysqld
работал как Unix-пользователь
user_name
, Вы должны сделать следующие шаги:
mysqladmin shutdown
).
user_name
имел права на чтение и запись:
shell> chown -R user_name /path/to/mysql/datadirЕсли каталоги или файлы внутри каталога данных MySQL представляют собой символические ссылки, Вы будете также должны следовать за теми связями и изменять каталоги и файлы, на которые они указывают. Увы,
chown -R
не может следовать за ссылками для Вас.
user_name
или, если Вы
используете MySQL Version 3.22 или позже, как Unix-пользователь
root
с опцией --user=user_name
.
mysqld
переключится на Unix-пользователя user_name
перед принятием любых подключений.
user
, которая определяет имя
пользователя, к группе [mysqld]
файла /etc/my.cnf (или
my.cnf) в каталоге данных сервера. Например:
[mysqld] user=user_name
Обратите внимание, что доступ к MySQL как root
указанием
-u root
в командной строке, не имеет никакого отношения
к запуску MySQL как root
. Права доступа и имена пользователей
MySQL полностью независимы от имен в Unix. Единственное подключение с именем
пользователя Unix происходит, если Вы не указали опцию -u
, когда
Вы вызываете программу пользователя. Клиент пробует подключиться, используя
Ваше Unix-имя входа в систему как имя пользователя MySQL.
Если Вы имеете проблемы с правами доступа к файлам, например, если
mysql
выдает такое сообщение об ошибке, когда создаете таблицу:
ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)
То системная переменная
UMASK
может быть установлена неправильно, когда запускается
mysqld
. Значение по умолчанию для umask: 0660
.
Вы можете изменять это поведение, запуская safe_mysqld
так:
shell> UMASK=384 # = 600 in octal shell> export UMASK shell> /path/to/safe_mysqld &
По умолчанию MySQL создаст
базу данных и каталоги RAID
с правами доступа 0700. Вы можете
изменять это поведение, устанавливая переменную UMASK_DIR
.
Если Вы устанавливаете ее, новые каталоги будут созданы с объединением
UMASK
и UMASK_DIR
. Например, если Вы хотите давать
группе доступ ко всем новым каталогам, Вы можете сделать:
shell> UMASK_DIR=504 # =770 в аосьмеричном формате. shell> export UMASK_DIR shell> /path/to/safe_mysqld &
В MySQL Version 3.23.25 и выше MySQL считает, что значения
UMASK
и UMASK_DIR
заданы в восьмеричном формате,
если они начинаются с ноля.
Все версии MySQL проверены на многих платформах прежде, чем они выпущены. Это не означает, что не имеется любых ошибок в MySQL, но это означает, что их там очень мало.
Сначала Вы должны пробовать выяснять, состоит ли проблема в том, что
mysqld
падает, или ее корень надо искать на клиенте. Вы можете
проверять время работы сервера mysqld
командой mysqladmin
version
. Если mysqld
свалился, Вы можете находить причину
этого в файле mysql-data-directory/hostname.err.
Много сбоев MySQL вызваны разрушенным индексом или файлами данных. MySQL
модифицирует данные относительно диска через системный вызов
write()
после каждой инструкции SQL, но прежде, чем пользователю
сообщают относительно результата. Это не так, если Вы работаете с опцией
delayed_key_writes
, когда только данные будут записаны. Это
означает, что данные в безопасности, даже если сбоит mysqld
,
если ОС гарантируют, что данные будут сброшены из кэша на диск. Вы можете
заставить MySQL сбрасывать кэш принудительно после каждой команды SQL,
запуская mysqld
с опцией --flush
.
Вышеупомянутое означает, что обычно Вы не должны получить разрушенные таблицы и файлы, если:
mysqld
в середине модификации.
mysqld
, которая разрушила его
в середине модификации.
mysqld
на тех же
самых данных в системе, которая не поддерживает хорошие блокировки файловой
системы (обычно обрабатываемые сервером lockd
), или была указана
опция --skip-locking
при запуске сервера.
mysqld
запутался.
ALTER TABLE
на
восстановленной копии таблицы.Поскольку очень трудно узнать, почему что-то терпит крах, сначала попробуйте проверить следующее:
mysqld
с помощью mysqladmin
shutdown
, запустите myisamchk --silent --force */*.MYI
на
всех таблицах и перезапустите сервер mysqld
. Это гарантирует,
что Вы запустились с чистого состояния.
mysqld --log
и попробуйте определить из
информации в файле регистрации, уничтожает или нет некоторый специфический
запрос сервер. Приблизительно 95% всех ошибок связаны со специфическим
запросом! Обычно это один из последних запросов в журнале. Если Вы можете
повторить процесс уничтожения MySQL одним из запросов даже, когда Вы проверили
все таблицы перед выполнением запроса, то ошибка локализована. Готовьте отчет
об ошибке. Подробности в разделе "Приложение
3. Как сообщать о проблемах и сбоях".
fork_test.pl
и
fork2_test.pl
.
--skip-locking
для mysqld
.
На некоторых системах администратор блокировок lockd
не работает
правильно. Опция --skip-locking
сообщает, чтобы
mysqld
не использовал внешнюю блокировку. Это означает, что Вы
не сможете выполнять несколько серверов mysqld
на тех же самых
данных, и что Вы должны быть внимательны, если Вы используете
myisamchk
, но может быть поучительно опробовать опцию как тест.
mysqladmin -u root processlist
, когда
mysqld
работает, но не отвечает? Иногда mysqld
не
завис даже при том, что Вы могли бы думать именно так. Проблема может
состоять в том, что все подключения находятся в использовании, или может
иметься некоторая внутренняя проблема блокировки. Вызов mysqladmin
processlist
обычно будет способен делать подключение даже в этих
случаях и может обеспечивать полезную информацию относительно текущего числа
подключений и их состояния.
mysqladmin -i 5 status
или
mysqladmin -i 5 -r status
, чтобы произвести статистику в то
время, как Вы выполняете другие Ваши запросы.
BLOB/TEXT
(только VARCHAR
),
Вы можете пробовать изменять все VARCHAR
на CHAR
с
помощью команды ALTER TABLE
. Это вынудит MySQL использовать
строки фиксированных размеров. Они берут небольшое дополнительное
пространство, но намного более терпимы к искажению! Текущий динамический код
строки был в использовании в MySQL AB по крайней мере 3 года без всяких
проблем, но строки динамической длины вообще более склонны к ошибкам, так что
посмотрите, что получится.Если Вы забыли пароль пользователя root
для MySQL, Вы можете
восстанавливать его следующей процедурой:
mysqld
отправкой ему команды
kill
(но не kill -9
!). Идентификатор процесса будет
сохранен в .pid
-файле, который обычно хранится в каталоге для
баз данных MySQL:
kill `cat /mysql-data-directory/hostname.pid`Вы должны быть Unix-пользователем
root
или тем пользователем, от
имени которого выполняется сервер.
mysqld
с опцией
--skip-grant-tables
.
mysqld
командой mysql -h hostname
mysql
и смените пароль командой GRANT
. Подробности в
разделе "10.1 Синтаксис GRANT
и
REVOKE
". Вы можете также делать это с помощью команды
mysqladmin -h hostname -u user password new_password
.
mysqladmin -h hostname
flush-privileges
или командой SQL FLUSH PRIVILEGES
.Обратите внимание, что после того, как Вы запустили mysqld
с
опцией --skip-grant-tables
, любое использование команды
GRANT
даст Вам ошибку Unknown command
, пока Вы не
выполните FLUSH PRIVILEGES
.
Когда диск полностью заполнится, MySQL делает следующее:
Чтобы облегчить проблему, Вы можете предпринять следующие действия:
mysqladmin kill
потоку. Он
будет прерван, когда в следующий раз проверит диск (через минуту).
Исключительные ситуации: Вы используете REPAIR
или
OPTIMIZE
, индексы созданы в пакете после LOAD DATA
INFILE
, или выполнена инструкция ALTER TABLE
.
Все вышеприведенные команды могут использовать большие временные файлы,
которые остались после них на диске, что вызовет большие проблемы для
остальной части системы. Если MySQL переполняет диск при выполнении любой из
вышеупомянутых операций, он удалит большие временные файлы и отметит таблицу
как поврежденную (исключение: ALTER TABLE
, в этом случае старая
таблица будет оставлена неизменной).
MySQL использует значение системной переменной TMPDIR
как имя
пути каталога, чтобы сохранить временные файлы. Если Вы не имеете
TMPDIR
, MySQL использует системное значение по умолчанию,
которое является обычно /tmp или /usr/tmp. Если файловая
система, содержащая Ваш временный каталог слишком маленькая, Вы должны
отредактировать скрипт safe_mysqld
, чтобы установить
TMPDIR
так, чтобы указать на каталог в файловой системе, где Вы
имеете достаточно места. Вы можете также устанавливать временный каталог,
используя опцию --tmpdir
при вызове mysqld
.
MySQLсоздает все временные файлы как скрытые. Это гарантирует, что
временные файлы будут удалены, если mysqld
завершен. Недостаток
использования скрытых файлов в том, что Вы не будете видеть большой временный
файл, заполняющий файловую систему, в которой размещен временный каталог.
При сортировке (ORDER BY
или GROUP BY
) MySQL
обычно использует один или два временных файла. Максимальное дисковое
пространство, необходимое для сортировки:
(Длина сортируемых данных+sizeof(database pointer))* число совпадающих строк*2
Здесь sizeof(database pointer)
обычно 4, но может расти в
будущем для действительно больших таблиц.
Для некоторого запроса SELECT
MySQL также создает временные
SQL-таблицы. Они не скрыты и имеют имена формы SQL_*.
ALTER TABLE
создает временную таблицу в том же самом
каталоге, где находится и первоначальная таблица.
Если Вы имеете проблемы с тем фактом, что любой может удалять сокет
MySQL /tmp/mysql.sock, Вы можете, на большинстве версий Unix,
защитить Вашу файловую систему /tmp, устанавливая липкий бит на ней.
Зайдите в систему как root
и скомандуйте:
shell> chmod +t /tmp
Это защитит Вашу файловую систему /tmp так, чтобы файлы могли
быть удалены только их владельцами или суперпользователем (root
).
Вы можете проверять, установлен ли липкий бит, выполняя
ls -ld /tmp
. Если последний бит прав доступа равен
t
, липкий бит установлен.
Вы можете изменять место, где MySQL помещают файл сокета, так:
/etc/my.cnf
:
[client] socket=path-for-socket-file [mysqld] socket=path-for-socket-file
safe_mysqld
и для
большинства клиентов опцией --socket=path-for-socket-file
.
MYSQL_UNIX_PORT
.Вы можете проверять, что сокет работает, с помощью команды:
shell> mysqladmin --socket=/path/to/socket version
Если Вы имеете проблему с SELECT NOW()
, возвращающим значения
в GMT, а не по Вашему местному времени, Вы должны установить системную
переменную TZ
к Вашему текущему часовому поясу. Это должно быть
выполнено для среды, в которой выполняется сервер, например, в скрипте
safe_mysqld
или в mysql.server
.
По умолчанию поиск в MySQL нечувствителен к регистру (хотя имеются
некоторые наборы символов, которые всегда чувствительны, например,
czech
). Это означает, что, если Вы ищете col_name LIKE
'a%'
, Вы получите все значения столбца, которые начинаются с
A
или a
. Если Вы хотите сделать этот поиск с учетом
регистра, используйте нечто подобное INSTR(col_name, "A")=1
,
чтобы проверить префикс. Или используйте STRCMP(col_name,"A")=0
,
если значение столбца было точно "A"
.
Простые операции сравнения (>=, >, =, < ,<=
,
сортировка и группировка) основаны на значении сорта каждого символа. Символы
с тем же самым значением сорта обрабатываются как тот же самый символ.
В старых версиях MySQL LIKE
выполнялся по значениям,
приведенным к верхнему регистру. В более новых версиях MySQL
LIKE
работает точно так же, как другие операторы сравнения.
Если Вы хотите, чтобы столбец всегда обработался в режиме чувствительности
к регистру, объявите его как BINARY
. Подробности в разделе
"7.3 Синтаксис CREATE TABLE
".
Если Вы используете китайские данные в так называемом кодировании big5, Вы
должны сделать все символьные столбцы BINARY
. Это работает
потому, что порядок сортировки символов кодирования big5 основан на
порядке ASCII кодов.
DATE
Формат значения DATE
всегда YYYY-MM-DD
. Согласно
ANSI SQL, никакой другой формат не позволяется. Вы должны использовать этот
формат в выражениях UPDATE
и в предложении WHERE инструкций
SELECT
. Например:
mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';
Как дополнительное удобство MySQL автоматически преобразовывает дату в
число, если дата используется в числовом контексте (и наоборот). Также
достаточно интеллектуально обрабатывается ослабленная форма строки при
модифицировании и в предложении WHERE
, которое сравнивает дату
со столбцом TIMESTAMP
, DATE
или
DATETIME
. Ослабленная форма означает, что любой символ
пунктуации может использоваться как разделитель между частями. Например,
1998-08-15
и 1998#08#15
являются эквивалентными.
MySQL может также преобразовывать строку не содержащую никаких разделителей
(типа 19980815
), если она имеет смысл как дата.
Специальная дата 0000-00-00
может быть сохранена и получена
как 0000-00-00
. При использовании даты 0000-00-00
через MyODBC, это будет автоматически преобразовано в
NULL
в MyODBC Version 2.50.12 и выше потому,
что ODBC не может обрабатывать этот вид даты.
Потому, что MySQL выполняет преобразования, описанные выше, следующие инструкции всегда работают:
mysql> INSERT INTO tbl_name (idate) VALUES (19970505); mysql> INSERT INTO tbl_name (idate) VALUES ('19970505'); mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05'); mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05'); mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05'); mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00'); mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05'; mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505; mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505; mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';
Однако, следующее работать не будет:
mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;
STRCMP()
представляет собой строковую функцию, так что это
преобразовывает idate
в строку и выполняет сравнение строк. Но
она не конвертирует 19970505
в дату и не сравнивает даты.
Обратите внимание, что MySQL не делает никакой проверки, является или нет
дата правильной. Если Вы сохраняете неправильную дату, типа
1998-2-31
, неправильная дата будет сохранена. Если дата не может
быть преобразована в любое приемлемое значение, 0
будет сохранен
в поле DATE
. Это главным образом проблема быстродействия.
NULL
Концепция значения NULL
представляет собой общий источник
беспорядка для новичков в SQL, которые часто думают, что NULL
та же самая вещь, что и пустая строка ''
. Дело обстоит не так!
Например, следующие инструкции полностью различны:
mysql> INSERT INTO my_table (phone) VALUES (NULL); mysql> INSERT INTO my_table (phone) VALUES ("");
Обе инструкции вставляют значение в столбец phone
, но первые
вставят значение NULL
, а вторая вставляет пустую строку.
Значение первой может быть расценено как "номер телефона неизвестен", а
значение второй как "не имеет никакого телефона".
В SQL значение NULL
всегда неправильно в сравнении с любым
другим значением. Выражение, которое содержит NULL
, всегда
производит значение NULL
, если иное не обозначено в документации
для операторов и функций, включаемых в выражение. Все столбцы в следующем
примере возвращают именно NULL
:
mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);
Если Вы хотите искать значения столбца, которые являются
NULL
, Вы не можете использовать тест =NULL
.
Следующая инструкция не возвращает никаких строк потому, что
expr=NULL
всегда равно FALSE для любого выражения:
mysql> SELECT * FROM my_table WHERE phone = NULL;
Чтобы искать значения NULL
, Вы должны использовать тест
IS NULL
. Следующее показывает, как найти номер телефона
NULL
и пустой номер телефона:
mysql> SELECT * FROM my_table WHERE phone IS NULL; mysql> SELECT * FROM my_table WHERE phone = "";
В MySQL как и во многих других SQL-серверах, Вы не можете индексировать
столбцы, которые могут иметь значения NULL
. Вы должны объявить
столбцы для индекса как NOT NULL
. Наоборот, Вы не можете
вставлять NULL
в индексированный столбец.
При чтении данных через LOAD DATA
INFILE
, пустые столбцы модифицируются с ''
. Если Вы
хотите иметь в столбце значение NULL
, Вы должны использовать
\N
в текстовом файле. Литеральное слово 'NULL'
может также с успехом использоваться при некоторых обстоятельствах.
Подробности есть в разделе "8.9 Синтаксис
LOAD DATA INFILE
".
При использовании ORDER BY
значения NULL
будут
представлены первыми. Если Вы сортируете в порядке по убыванию, используя
DESC
, значения NULL
, понятно, окажутся в хвосте.
При использовании GROUP BY
, все значения NULL
будут
расценены как равные.
Чтобы помочь СУБД с обработкой NULL
, Вы можете использовать
операторы IS NULL
и IS NOT NULL
, а также функцию
IFNULL()
. Производительность улучшится.
Для некоторых типов столбцов значения NULL
обработаны особо. Если Вы вставляете NULL
в первый столбец типа
TIMESTAMP
в таблице, реально будут вставлены текущая дата и
время. Если Вы вставляете NULL
в столбец с поддержкой
AUTO_INCREMENT
, вставится следующее число в последовательности.
alias
Вы можете использовать псевдоним, чтобы обратиться к столбцу в
GROUP BY
, ORDER BY
или в части HAVING
.
Псевдонимы могут также использоваться, чтобы дать столбцам лучшие имена:
SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0; SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0; SELECT id AS "Customer identity" FROM table_name;
Обратите внимание, что ANSI SQL не позволяет Вам обращаться к псевдониму в
предложении WHERE
. Это потому, что, когда код WHERE
выполнен, значение столбца не может быть определено. Например, следующий
запрос строго запрещен:
SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
Инструкция WHERE
выполнена, чтобы определить, которые строки
должны быть включены в часть GROUP BY
в то время, как
HAVING
используется, чтобы решить, которые строки из набора
результатов должны использоваться.
Поскольку MySQL не поддерживает подвыборы или использование больше, чем
одной таблицы в инструкции DELETE
, Вы должны использовать
следующий подход, чтобы удалить строки из двух связанных таблиц:
SELECT
строки, основываясь на некотором условии
WHERE
в основной таблице.
DELETE
строки в основной таблице, основываясь на том
же самом условии.
DELETE FROM связанная_таблица WHERE связанные_столбцы
IN (выбранные_строки)
.Если общее количество символов в запросе со связанными столбцами
(related_column
) больше, чем 1048576 (значение по умолчанию
для max_allowed_packet
), Вы должны расчленить его на меньшие
части и выполнить много инструкций DELETE
. Вы, вероятно,
достигнете пика производительности при удалении 100-1000
related_column
на запрос, если related_column
является индексом. В противном случае быстродействие независимо от числа
параметров в предложении IN
.
Если Вы имеете сложный запрос, который имеет много таблиц, а он не возвращает никаких строк, Вы должны использовать следующую процедуру, чтобы выяснить, что неправильно с Вашим запросом:
EXPLAIN
и выправьте его, если
Вы можете найти что-то такое, что является очевидно неправильным. Подробности
в разделе "14.2.1 Синтаксис
EXPLAIN
(получение информации о SELECT
)".
WHERE
.
LIMIT 10
.
SELECT
для столбца, который должен был
соответствовать в таблице, которая была последней удалена из запроса.
FLOAT
или DOUBLE
с
числовыми столбцами, которые имеют десятичные числа, Вы не можете
использовать =
. Эта проблема общая в большинстве компьютерных
языков потому, что значения с плавающей запятой не точные значения:
mysql> SELECT * FROM table_name WHERE float_column=3.5; -> mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;В большинстве случаев замена
FLOAT
на DOUBLE
исправит это дело.
mysql test <
query.sql
, который показывает Ваши проблемы. Вы можете создавать файл
теста с помощью mysqldump --quick database tables >
query.sql
. Откройте файл в редакторе, удалите некоторые строки и
добавьте Вашу инструкцию выбора в конце файла. Проверьте, что Вы все еще
имеете Вашу проблему:
shell> mysqladmin create test2 shell> mysql test2 < query.sqlОтправьте файл теста, используя
mysqlbug
на
mysql@lists.mysql.com.ALTER TABLE
ALTER TABLE
изменяет таблицу на текущий набор символов. Если
Вы в течение ALTER TABLE
получаете ошибку дублирования ключа, то
причиной является то, что новые наборы символов отображают разные ключи к
тому же самому значению, или что таблица разрушена, тогда Вы должны выполнить
REPAIR TABLE
на таблице.
Если ALTER TABLE
падает с ошибкой подобно этой:
Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)
Проблема может состоять в том, что MySQL потерпел крах в предыдущем
ALTER TABLE
, и имеется старая таблица с именем A-что-то
или B-что-то. В этом случае идите в каталог данных MySQL, и удалите
там все файлы, которые имеют имена, начинающиеся с A-
или
B-
. Вы можете перемещать их в другое место вместо того, чтобы
удалить их сразу.
ALTER TABLE
работает следующим образом:
Если что-то идет неправильно с операцией переименования, MySQL пробует отменить изменения. Если что-то идет совсем уж неправильно (этого не должно случиться, конечно), MySQL может оставить старую таблицу как B-xxx, поскольку простое переименование на уровне системы должно вернуть Ваши данные обратно в целости и сохранности.
Вы должны всегда определять порядок, в котором Вы желаете получить данные:
SELECT col_name1, col_name2, col_name3 FROM tbl_name;
Возвратит столбцы в порядке col_name1
, col_name2
,
col_name3
в то время, как:
SELECT col_name1, col_name3, col_name2 FROM tbl_name;
Возвратит столбцы в порядке col_name1
,
col_name3
, col_name2
.
Вы не должны в прикладной программе использовать
SELECT *
и получать столбцы, основываясь на их позиции потому,
что порядок, в котором столбцы возвращены, НЕЛЬЗЯ
ГАРАНТИРОВАТЬ через какое-то время. Простое изменение Вашей базы
данных может заставить Вашу прикладную программу развалиться полностью.
Если по какой-то причине Вы все же хотите изменять порядок столбцов, Вы можете сделать это следующим образом:
INSERT INTO new_table SELECT fields-in-new_table-order
FROM old_table
.
old_table
.
ALTER TABLE new_table RENAME old_table
.Следующее представляет собой список всех ограничений, действительных для
временных таблиц (TEMPORARY TABLES
).
HEAP
,
ISAM
или MyISAM
.
select * from temporary_table, temporary_table as t2;Это планируется исправить в версии 4.0.
RENAME
для таблиц
TEMPORARY
. Обратите внимание, что ALTER TABLE org_name
RENAME new_name
тем не менее работает вполне корректно! Это
планируется исправить в версии 4.0.MySQL предоставляет поддержку интерфейса ODBC с помощью пакета MyODBC. Эта глава научит Вас, как установить и использовать MyODBC. Здесь Вы также найдете список общих программ, которые, как известно, работают с MyODBC.
MyODBC представляет собой 32-bit ODBC (2.50) level 0 (с возможностями level 1 и level 2) драйвер для соединения ODBC-приложений с СУБД MySQL. MyODBC работает под Windows95, Windows98, NT и на некоторых Unix-системах.
MyODBC публично доступен, и Вы можете спокойно скачать его новейшую версию с http://www.mysql.com/downloads/api-myodbc.html.
Если Вы имеете проблему с MyODBC, и Ваша программа также работает с OLEDB, Вы должны попробовать драйвер для OLEDB, который Вы можете найти в разделе Contrib.
Обычно Вы должны установить MyODBC только на системах с Windows. Под Unix MyODBC Вам понадобится только, если Вы имеете программу подобную ColdFusion, которая выполняется на Unix-машине и использует ODBC, чтобы соединиться с базами данных.
Если Вы хотите устанавливать MyODBC под Unix, Вы будете также нуждаться в диспетчере ODBC. MyODBC, как известно, работает с большинством Unix ODBC-диспетчеров. Вы можете найти список ODBC-секции ссылок на страничке MySQL. Подробности в разделе "1.2.3 Хорошие ссылки по MySQL ".
Чтобы установить MyODBC в Windows, Вы должны загрузить
соответствующий файл MyODBC .zip (для Windows9x или
NT/Win2000), распаковывать его с помощью WINZIP
или другой
подобной программы и выполнить файл SETUP.EXE
.
В Windows NT Вы можете получать следующую ошибку при попытке установить MyODBC:
An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart Windows and try installing again (before running any applications which use ODBC)
Проблема в этом случае состоит в том, что некоторая другая программа
использует ODBC, а также из-за того, как неудобно устроена Windows, Вы не
можете в этом случае установить новые ODBC-драйверы программой установки
Microsoft ODBC setup. В большинстве случаев Вы можете продолжать установку,
нажав кнопку Ignore
, чтобы копировать остальную часть файлов
MyODBC. Если это не работает, решение состоит в том, чтобы перезагрузить Ваш
компьютер в safe mode (выберите это, нажимая F8 перед запуском Windows после
перезагрузки), установить MyODBC и перезагрузиться назад в
нормальный режим работы.
GRANT
. Подробности в разделе "10.1
Синтаксис GRANT
и REVOKE
".
Обратите внимание, что имеются другие опции конфигурации на экране MySQL (trace, don't prompt on connect, etc), которые Вы можете опробовать, если сталкиваетесь с проблемами.
Имеются три возможности для определения имени сервера в Windows95:
ip hostnameНапример:
194.216.84.21 my_hostname
Пример того, как заполнить поля в ODBC setup
:
Windows DSN name: test Description: This is my test database MySql Database: test Server: 194.216.84.21 User: monty Password: my_password Port:
Значение для поля Windows DSN name
: любое имя, которое
является уникальным в Вашей Windows ODBC-установке.
Вы не должны определить значения для полей Server
,
User
, Password
или Port
на экране
установки ODBC. Однако, если Вы это сделаете, значения будут использоваться
как значения по умолчанию позже, когда Вы попытаетесь сделать соединение.
Тогда их можно поменять.
Если номер порта явно не задан, используется заданный по умолчанию порт (3306).
Если Вы определяете опцию Read options from C:\my.cnf
, группы
client
и odbc
будут читаться из файла
C:\my.cnf.
Можно определять следующие параметры для MyODBC в разделе
[Servername]
файла ODBC.INI
или через аргумент
InConnectionString
в вызове SQLDriverConnect()
.
Параметр | Значение по умолчанию | Комментарий |
user | ODBC (в Windows) | username используемый, чтобы соединиться с MySQL. |
server | localhost | Имя хоста сервера MySQL. |
database | Заданная по умолчанию база данных | |
option | 0 | Целое число, которым Вы можете определять, как MyODBC должен работать. Подробности ниже. |
port | 3306 | Порт TCP/IP, чтобы использовать, если
server не localhost . |
stmt | Команда, которая будет выполнена при
установлении соединения с MySQL . | |
password | Пароль для комбинации параметров
server и user . | |
socket | Сокет или именованный канал Windows. |
Параметр option используется, чтобы сообщить MyODBC, что клиент не на 100% ODBC-совместим. В Windows обычно устанавливаются опции на экране соединения, но можно также устанавливать это в параметре option. Следующие опции перечислены в том же самом порядке, в каком они появляются на экране соединения MyODBC:
Bit | Назначение |
1 | Клиент не может обрабатывать возвращаемую MyODBC реальную ширину столбца. |
2 | Клиент не может обрабатывать возвращаемое MySQL истинное значение числа обрабатываемых строк. Если этот флажок установлен MySQL возвращает найденные строки. Нужно иметь MySQL 3.21.14 или более новый, чтобы получить такую поддержку. |
4 | Создает файл регистрации отладки c:\myodbc.log. Это
аналогично указанию MYSQL_DEBUG=d:t:O,c::\myodbc.log в
AUTOEXEC.BAT. |
8 | Не устанавливать ограничение пакета для результатов и параметров. |
16 | Не запрашивать ничего, даже если драйвер хотел бы что-то запросить. |
32 | Моделировать драйвер ODBC 1.0 в некотором контексте. |
64 | Игнорировать использование имени базы данных в 'database.table.column'. |
128 | Принудительно использовать курсоры менеджера ODBC. |
256 | Отключить использование расширенной выборки. |
512 | Приводить поля CHAR к полной длине столбца. |
1024 | SQLDescribeCol() возвратит полное имя столбца. |
2048 | Использовать сжатый протокол сервера/клиента. |
4096 | Сообщает, чтобы сервер игнорировал пробел после имени
функции и перед '(' (необходимо для работы с PowerBuilder). Эта
опция сделает все имена функций ключевыми словами! |
8192 | Соединяться с именованными конвейерами с сервером
mysqld под NT. |
16384 | Изменить столбцы LONGLONG на INT (некоторые приложения не могут обрабатывать LONGLONG). |
32768 | Вернуть 'user' как Table_qualifier и Table_owner из вызова SQLTables (экспериментально). |
65536 | Читать параметры из групп client и
odbc файла настроек my.cnf. |
131072 | Добавляет некоторые дополнительные проверки безопасности (обычно не надо, но...). |
Если Вы хотите иметь много опций, Вы должны сложить вышеупомянутые флажки. Например, установка option в 12 (4+8) дает Вам отладку без ограничений пакета.
По умолчанию MYODBC.DLL компилируется для оптимальной
эффективности. Если Вы хотите отладить MyODBC (например,
чтобы включить трассировку), Вы должны взамен использовать
MYODBCD.DLL
. Чтобы установить этот файл, скопируйте
MYODBCD.DLL взамен установленной библиотеки MYODBC.DLL
.
MyODBC был проверен с Access, Admndemo.exe, C++-Builder, Borland Builder 4, Centura Team Developer (прежде это был пакет Gupta SQL/Windows), ColdFusion (на Solaris и NT с svc pack 5), Crystal Reports, DataJunction, Delphi, ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes 4.5/4.6, SBSS, Perl DBD-ODBC, Paradox, Powerbuilder, Powerdesigner 32 bit, VC++ и Visual Basic.
Если Вы знаете о любых других приложениях, которые работают с MyODBC, пожалуйста, напишите об этом на myodbc@lists.mysql.com!
С некоторыми программами Вы можете получать ошибку подобно:
Another user has modifies the record that you have modified
.
В большинстве случаев это может быть решено следующим образом:
Большинство программ должны работать с MyODBC, но для каждой из тех, что перечислены ниже, это было проверено.
Microsoft
Data Access Components
) с адреса
http://www.microsoft.com/data.
Это устранит следующую ошибку в Access: когда Вы экспортируете данные в
MySQL, таблица и названия столбцов не определены. Другой способ обхода этой
ошибки в том, чтобы обновить MyODBC до Version 2.50.33 и MySQL до Version
3.23.x, они вместе обеспечивают обход для этой проблемы!
Вы должны также получить и применить Microsoft Jet 4.0 Service Pack 5 (SP5),
который можно найти на
http://support.microsoft.com/support/kb/articles/Q 239/1/14.ASP. Это
устранит некоторые случаи, где столбцы отмечены как
#deleted#
в пакете Access.
Обратите внимание, что, если Вы используете MySQL Version 3.22, Вы должны
применить заплату MDAC и использовать MyODBC 2.50.32 или 2.50.34.
#Deleted#
.
TIMESTAMP(14)
или простой TIMESTAMP
вместо других
вариантов на тему TIMESTAMP(X)
.
#Deleted#
, или Вы не можете находить строки модификаций.
Another user has changed your
data
после добавления столбца TIMESTAMP
, следующий прием
может помочь Вам:
Не используйте просмотр листа данных table
. Создайте взамен
форму с полями, которые Вы хотите обрабатывать, и используйте эту форму для
просмотра в формате form
. Вы должны установить реквизит
DefaultValue
для столбца TIMESTAMP
в значение
NOW()
. Неплохо скрыть столбец TIMESTAMP
, чтобы не
запутывать Ваших пользователей.
BLOB
-столбцы как OLE
OBJECTS
. Если Вы хотите взамен иметь столбцы MEMO
, Вы
должны изменить столбец на TEXT
через ALTER TABLE
.
DATE
.
Если Вы имеете проблему с этим, измените столбцы на DATETIME
.
"Query|SQLSpecific|Pass-Through"
из меню Access.
TINYINT
вместо TINYINT
UNSIGNED
. Это задаст Вам проблем, если Вы имеете значения > 127!
Return matching rows
.
Return matching rows
и Simulate ODBC 1.0
.CursorLocation Property
как adUseServer
возвратит
для RecordCount Property
результат -1. Сомневаюсь, что это
входит в Ваши планы... Чтобы иметь правильное значение, Вы должны установить
реквизит adUseClient
так, как показано в коде на VB ниже:
Dim myconn As New ADODB.Connection Dim myrs As New Recordset Dim mySQL As String Dim myrows As Long myconn.Open "DSN=MyODBCsample" mySQL = "SELECT * from user" myrs.Source = mySQL Set myrs.ActiveConnection = myconn myrs.CursorLocation = adUseClient myrs.Open myrows = myrs.RecordCount myrs.Close myconn.CloseДругой вариант: использовать
SELECT COUNT(*)
для подобного
запроса, чтобы получить правильное число строк.
Return matching rows
.
Don't optimize column widths
и
Return matching rows
.
Active
или метод Open
. Обратите внимание, что
Active
при запуске автоматически выдает запрос SELECT *
FROM ...
, который не может быть хорошим, если Ваши таблицы большие!
VARCHAR
вместо
ENUM
, поскольку пакет экспортирует последнее способом, который
вызывает разрушение MySQL.
CONCAT()
. Например:
select CONCAT(rise_time), CONCAT(set_time) from sunrise_sunset;Значения, найденные как строки, этим способом должны быть правильно распознаны как значения времени Excel97. Цель
CONCAT()
в этом примере состоит в том, чтобы ввести в
заблуждение ODBC, чтобы тот принял столбец за строковый. Без
CONCAT()
ODBC знает, что столбец имеет тип времени, а Excel
этого не понимает.
Обратите внимание, что это ошибка в Excel. Она происходит потому, что он
автоматически преобразовывает строку во время. Это хорошо, если источником
был текстовый файл, но просто глупо, когда источником является
ODBC-соединение, которое сообщает точные типы для каждого столбца.MyODBC
и Add-in Microsoft Query help.
Например, создайте базу данных с таблицей, содержащей 2 столбца текста:
mysql
.
fReg:= TRegistry.Create; fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True); fReg.WriteString('Database', 'Documents'); fReg.WriteString('Description', ' '); fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll'); fReg.WriteString('Flag', '1'); fReg.WriteString('Password', ''); fReg.WriteString('Port', ' '); fReg.WriteString('Server', 'xmark'); fReg.WriteString('User', 'winuser'); fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True); fReg.WriteString('DocumentsFab', 'MySQL'); fReg.CloseKey; fReg.Free; Memo1.Lines.Add('DATABASE NAME='); Memo1.Lines.Add('USER NAME='); Memo1.Lines.Add('ODBC DSN=DocumentsFab'); Memo1.Lines.Add('OPEN MODE=READ/WRITE'); Memo1.Lines.Add('BATCH COUNT=200'); Memo1.Lines.Add('LANGDRIVER='); Memo1.Lines.Add('MAX ROWS=-1'); Memo1.Lines.Add('SCHEMA CACHE DIR='); Memo1.Lines.Add('SCHEMA CACHE SIZE=8'); Memo1.Lines.Add('SCHEMA CACHE TIME=-1'); Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT'); Memo1.Lines.Add('SQLQRYMODE='); Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE'); Memo1.Lines.Add('ENABLE BCD=FALSE'); Memo1.Lines.Add('ROWSET SIZE=20'); Memo1.Lines.Add('BLOBS TO CACHE=64'); Memo1.Lines.Add('BLOB SIZE=32'); AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
Return matching rows
.
SHOW PROCESSLIST
,
не будут работать правильно. Устраняется это указанием опции
OPTION=16834
в строке соединения ODBC или опции Change
BIGINT columns to INT
на экране соединения MyODBC. Вы можете также
устанавливать Return matching rows
.
[Microsoft][ODBC Driver Manager] Driver
does not support this parameter
, причина может быть в том, что Вы
имеете BIGINT
в Вашем результате. Попробуйте устанавливать опцию
Change BIGINT columns to INT
на экране соединения MyODBC.
Don't optimize column widths
.AUTO_INCREMENT
в ODBCОбщая проблема: как получить значение автоматически сгенерированный ID из
INSERT
. С ODBC Вы можете делать что-нибудь вроде этого
(считается, что auto
является полем с
AUTO_INCREMENT
):
INSERT INTO foo (auto,text) VALUES(NULL,'text'); SELECT LAST_INSERT_ID();
Или, если Вы только собираетесь вставлять ID в другую таблицу, Вы можете сделать так:
INSERT INTO foo (auto,text) VALUES(NULL,'text'); INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');
Для пользы некоторых ODBC-приложений (по крайней мере Delphi и Access), следующий запрос может использоваться, чтобы найти недавно вставленную строку:
SELECT * FROM tbl_name WHERE auto IS NULL;
Если Вы сталкиваетесь с трудностями с MyODBC, Вы должны сделать файл протокола менеджера ODBC (файл регистрации, который Вы получаете при запросе файлов регистрации из ODBCADMIN) и протокол из MyODBC.
Чтобы получить протокол из MyODBC, Вы должны сделать:
myodbcd.dll
, а не
myodbc.dll
. Самый простой способ делать это состоит в том, чтобы
получить myodbcd.dll
из дистрибутива MyODBC и скопировать на
место myodbc.dll
, которая, вероятно, находится в Вашем каталоге
C:\windows\system32
или C:\winnt\system32
.
Обратите внимание, что Вы, вероятно, захотите восстановить старый файл
myodbc.dll, когда закончите тестирование, поскольку он куда быстрее
myodbcd.dll
.
myodbcd.dll
.
Проверьте MyODBC trace file
, чтобы выяснить, что именно могло
пойти не так. Вы должны быть способны выяснить выданные запросы, ища после
строки >mysql_real_query
в файле myodbc.log.
Вы должны также попробовать дублировать запросы в mysql
monitor или admndemo
, чтобы выяснить, ошибка это
MyODBC или MySQL.
Если Вы выясняете, что что-то пошло неправильно, пожалуйста, пошлите только релевантные строки (максимум 36 строк) на адрес myodbc@lists.mysql.com. Пожалуйста, никогда не посылайте целый файл протокола ODBC или MyODBC!
Если Вы неспособны выяснить, что неправильно, последняя опция должна сделать архив (tar или zip), который содержит файл трассировки MyODBC, файл протокола ODBC и файл README, который объясняет проблему. Вы можете посылать это на ftp://support.mysql.com/pub/mysql/secret. Только в MySQL AB имеют доступ к файлам, которые Вы загружаете, и там будут очень аккуратны с данными!
Если Вы можете создать программу, которая также показывает эту проблему, пожалуйста, загрузите ее туда же.
Если программа работает с некоторым другим SQL сервером, Вы должны сделать файл протокола ODBC с описанием действий, когда Вы делаете точно ту же самую вещь на другом SQL-сервере.
Не забудьте, что подробная информация, которую Вы можете обеспечить авторам, повышает вероятность того, что они смогут решить проблему!
Оптимизация представляет собой сложную задачу потому, что в конечном счете требуется понимание целой системы. В то время, как можно сделать некоторую локальную оптимизацию с небольшими знаниями относительно Вашей системы или прикладной программы, серьезная оптимизация требует значительных знаний.
Эта глава пробует объяснить и дать некоторые примеры различных способов оптимизировать MySQL. Помните, однако, что всегда имеются некоторые дополнительные способы сделать Вашу систему еще чуть быстрее.
Наиболее важная часть для получения быстрой системы: базисный проект. Вы также должны знать то, какие дела Ваша система будет делать, каковы Ваши узкие места на этом пути.
Наиболее общие узкие места:
Поскольку MySQL использует чрезвычайно быструю блокировку таблицы (много чтений и одна запись), самая большая остающаяся проблема: смесь устойчивого потока вставок и медленного выбора данных в той же самой таблице.
Считается, что для огромного числа систем чрезвычайно быстрая эффективность в других случаях делает этот выбор правильным. Этот случай обычно также решаем при наличии нескольких копий таблицы, но требуется большее количество усилий и аппаратных средств.
Авторы также работают над некоторыми расширениями, чтобы решить эту проблему для некоторых общих ниш прикладных программ.
Потому, что все серверы SQL выполняют различные части SQL, требуется немалая работа, чтобы писать переносные прикладные программы SQL. Для очень простых выборов и вставок это очень просто, но чем дальше, тем труднее становится нормальное программирование.
Чтобы делать сложную прикладную программу переносной, Вы должны выбрать ряд серверов SQL, с которыми она должна работать.
Вы можете использовать MySQL программу crash-me/web-page http://www.mysql.com/information/crash-me.php, чтобы найти функции, типы и ограничения, которые Вы можете использовать с выбором сервера базы данных. Crash-me проверяет далеко не все возможное, но тест выполнен для 450 задач.
Например, Вы не должны иметь имена столбцов более длинными, чем 18 символов, если Вы хотите использовать Informix или DB2.
Тесты и программа MySQL crash-me являются очень независимыми от базы данных. Изучение этих программ может помочь Вам в написании своих прикладных программ, независимых от базы данных. Эталонные тесты могут быть найдены в каталоге sql-bench дерева исходников MySQL. Они написаны на Perl с интерфейсом базы данных DBI (который решает проблемы доступа).
Результаты тестов есть на http://www.mysql.com/information/benchmarks.html.
Как Вы можете видеть в этих результатах, все базы данных имеют некоторые слабые пункты. То есть они имеют различные компромиссы проекта, которые ведут к различному поведению.
Если Вы боретесь за независимость базы данных, Вы должны получить данные по проблемным зонам каждого сервера SQL. MySQL ОЧЕНЬ быстр в поиске и модифицировании, но будет иметь проблему при смешивании медленных чтений и записей на той же самой таблице. Oracle, с другой стороны, имеет большую проблему, когда Вы пробуете обращаться к строкам, которые Вы недавно модифицировали (пока их не сбросят на диск). Базы данных с транзакциями вообще не очень хороши при производстве итоговых таблиц из таблиц файла регистрации, поскольку в этом случае блокировка строки почти бесполезна.
Чтобы сделать Вашу прикладную программу по-настоящему независимой от базы данных, Вы должны определить простой интерфейс, через который Вы управляете вашими данными. Поскольку C++ доступен на большинстве систем, имеет смысл использовать интерфейс классов C++ к базам данных.
Если Вы используете некоторое специфическое свойство для некоторой базы
данных (подобно команде REPLACE
в MySQL), Вы должны
предусмотреть метод для других серверов SQL, чтобы выполнить то же самое
свойство (но медленнее). С MySQL Вы можете использовать синтаксис
/*! */
, чтобы добавить MySQL-специфические ключевые слова к
запросу. Код внутри /**/
будет обрабатываться как комментарий
большинством других серверов SQL.
Если высокая эффективность более важна, чем точность, как в некоторых прикладных программах для интернета, можно создать уровень прикладной программы, который кэширует все результаты, чтобы дать Вам даже более высокую эффективность. Позволяя старым результатам выдыхаться через некоторое время, Вы можете хранить кэш, приемлемо свежим. Это совершенно хорошо в случае чрезвычайно высокой загрузки, когда Вы можете динамически увеличивать кэш и повышать время ожидания, пока ситуация не вернется к норме.
В этом случае информация для создания новой таблицы должна содержать еще и информацию относительно начального размера кэша и то, как часто таблица обычно должна обновиться.
Вот что пишут авторы пакета о том, как создавалась эта СУБД:
В ходе начальной разработки, свойства MySQL были сделаны такими, чтобы удовлетворить нашего самого большого заказчика. Он обрабатывает данные для самых больших розничных продавцов в Швеции.
Из всех магазинов мы получаем еженедельно резюме всех транзакций по картам скидок и призов. Требуется обеспечить полезную информацию для владельцев магазинов, чтобы помочь им понять, как их рекламные кампании воздействуют на их заказчиков.
Данные огромны (приблизительно 7 миллионов итоговых транзакций в месяц), и мы имеем данные за последние 4-10 лет, которые должны представить пользователям. Мы получили еженедельно запросы от заказчиков, что они хотят иметь мгновенный доступ к новым отчетам из этих данных.
Мы решили это, сохраняя всю информацию за месяц в сжатых таблицах. Мы имеем набор простых макрокоманд (скриптов), который генерирует итоговые таблицы, сгруппированные в соответствии с различными критериями (product group, customer id, store, ...) из таблиц транзакции. Отчеты представляют собой Web-страницы, которые динамически генерируются маленьким скриптом на Perl, который анализирует Web-страницу, выполняет инструкции SQL и вставляет результаты. Мы использовали бы взамен PHP или mod_perl, но они не были доступны в то время.
Для графических данных мы написали на C
простой инструмент,
который может производить GIF-файлы, основываясь на результате запроса SQL (с
некоторой обработкой результата). Это также динамически выполняется из
скрипта на Perl, который анализирует HTML-файлы.
В большинстве случаев новый отчет может быть выполнен, просто копируя существующий скрипт и изменяя запрос SQL в нем. В некоторых случаях мы будем должны добавить большее количество полей к существующей таблице или сгенерировать новую, но это также просто, поскольку мы храним все таблицы транзакций на диске. В настоящее время мы имеем по крайней мере 50G таблиц транзакций и порядка 200G других данных заказчика.
Мы также позволяем нашим заказчикам обращаться к итоговым таблицам непосредственно через ODBC так, чтобы продвинутые пользователи могли самостоятельно экспериментировать с данными.
Мы не имели проблем с обработкой данных на Sun Ultra SPARCstation (2x200 Mhz). Недавно был проведен апгрейд до 2 CPU 400 Mhz UltraSPARC, и мы теперь планируем запускать транзакции обработки на уровне изделия товара, что означает десятикратное увеличение данных.
Мы также экспериментируем с Intel-Linux, чтобы быть способными получить большее количество более дешевой мощности CPU. Теперь, когда мы имеем двоичный переносимый формат базы данных (введен в Version 3.23), мы начнем использовать это для некоторых частей прикладной программы.
Этот раздел должен содержать техническое описание эталонного набора тестов
MySQL и теста crash-me
, но пока подробное руководство еще никем
не написано (в том числе и авторами пакета). Так что говорить о нем рано. В
настоящее время Вы можете получить хорошую помощь относительно эталонного
теста, рассматривая код и результаты в каталоге sql-bench
дистрибутива исходников MySQL.
Этот эталонный набор, как предполагается, является эталонным тестом, который сообщит любому пользователю, что именно данная реализация SQL выполняет хорошо или плохо.
Обратите внимание, что этот эталонный тест однопоточный, так что он измеряет минимальное время для операций. В будущем планируется добавление поддержки многопоточной обработки.
Например, (запуск на машине с NT 4.0):
Чтение 2000000 строк по индексу | Секунд |
mysql | 367 |
mysql_odbc | 464 |
db2_odbc | 1206 |
informix_odbc | 121126 |
ms-sql_odbc | 1634 |
oracle_odbc | 20800 |
solid_odbc | 877 |
sybase_odbc | 17614 |
Вставка 350768 строк | Секунд |
mysql | 381 |
mysql_odbc | 619 |
db2_odbc | 3460 |
informix_odbc | 2692 |
ms-sql_odbc | 4012 |
oracle_odbc | 11291 |
solid_odbc | 1801 |
sybase_odbc | 4802 |
В вышеупомянутом тесте MySQL был выполнен с 8M индексным кэшем.
Мы имеем несколько больше эталонных результатов на http://www.mysql.com/information/benchmarks.html.
Обратите внимание, что Oracle не включен потому, что компания-разработчик потребовала удалить эти данные. Причины такого отношения к независимым измерениям производительности могут быть вызваны лишь откровенным завышением характеристик сервера компанией Oracle.
Чтобы выполнить эталонный набор, Вы должны загрузить исходники MySQL, установить драйвер perl DBI для базы данных, которую Вы хотите проверить, и затем отдать команды:
cd sql-bench perl run-all-tests --server=#
Здесь # задает один из поддержанных серверов. Вы можете получить список
всех параметров и поддержанных серверов командой run-all-tests --help
.
Тест crash-me
может определить, какие
свойства база данных поддерживает, и перечень фактических возможностей и
ограничений. Например, это определяет:
VARCHAR
Результаты теста crash-me для большого набора разных баз данных можно найти на http://www.mysql.com/information/crash-me.php.
Вы должны использовать эталонный тест, чтобы выяснять, где находятся узкие места. Исправляя это (или заменяя узкое место фиктивным модулем), Вы можете затем легко идентифицировать следующее узкое место и так далее. Даже если полная эффективность для Вашей прикладной программы достаточна, Вы должны по крайней мере сделать план каждого узкого места и решить, как его расширить, если возникнет такая потребность.
Для примера переносных эталонных программ рассмотрите эталонный набор MySQL. Подробности в разделе "14.1.4 Набор тестов MySQL Benchmark Suite". Вы можете брать любую программу из этого набора и изменять ее для Ваших потребностей. Делая это, Вы можете опробовать различные решения Вашей проблемы и теста, который в самом деле является самым быстрым решением для Вас.
Некоторые проблемы происходят только тогда, когда система очень тяжело загружена. В каждом из этих случаев это обычно проблема с базисным проектом (просмотр таблицы НЕ хорош при высокой загрузке) или есть трудности с OS/Library. Большинство этих случаев было бы НАМНОГО проще исправить, если система еще не запущена в работу.
Чтобы избежать подобных проблем, Вы должны тестировать прикладную программу при самой плохой возможной загрузке! Вы можете использовать для этого Super Smack, который доступен по адресу http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz.
SELECT
и разных запросовСначала, одна вещь, которая воздействует на все запросы: более сложная установка систем разрешений, которую Вы имеете, усложняет и замедляет работу. В настройках не должно быть ничего лишнего. Все дополнительные довески и добавки замедляют работу системы (порой неожиданно сильно!). Как говорил один из моих преподавателей в университете, на парте должны быть только бумага, ручка и Ваши мозги.
Если Вы не имеете никаких выполненных инструкций GRANT
, MySQL
оптимизирует проверку разрешений.
Если Ваша проблема связана с некоторой явной функцией MySQL, Вы можете всегда сделать это в пользователе MySQL:
mysql> select benchmark(1000000,1+1); +------------------------+ | benchmark(1000000,1+1) | +------------------------+ | 0 | +------------------------+ 1 row in set (0.32 sec)
Этот пример показывает, что MySQL может выполнять 1000000 операций
сложения (+
) за 0.32 секунды на PentiumII 400MHz
.
Все функции MySQL должны быть очень хорошо оптимизированы, но могут
иметься некоторые исключительные ситуации, и вызов
benchmark(loop_count,expression)
представляет собой хороший
инструмент, чтобы выяснить, связана ли эта проблема с Вашим запросом.
EXPLAIN
(получение информации о SELECT
)
EXPLAIN tbl_name or EXPLAIN SELECT select_options
EXPLAIN tbl_name
представляет собой синоним для
DESCRIBE tbl_name
или SHOW COLUMNS FROM tbl_name
.
Когда Вы перед SELECT
задаете ключевое слово
EXPLAIN
, MySQL объясняет, как он обработал бы
SELECT
, обеспечивая информацию относительно того, как таблицы
будут соединены, и в каком порядке.
С помощью EXPLAIN
Вы можете видеть, когда Вы должны добавить
индексы к таблицам, чтобы получить более быстрый SELECT
, который
использует индексы, чтобы найти записи. Вы можете также видеть, соединяет ли
оптимизатор таблицы в оптимальном порядке. Чтобы вынуждать оптимизатор
использовать специфический порядок объединения для инструкции
SELECT
, добавьте предложение STRAIGHT_JOIN
.
Для непростых объединений EXPLAIN
возвратит строку информации
для каждой таблицы, используемой в инструкции SELECT
. Таблицы
перечислены в том порядке, в каком они читались бы. MySQL читает строку из
первой таблицы, затем находит строку соответствий во второй таблице, затем в
третьей таблице и так далее. Когда все таблицы обработаны, MySQL выводит
выбранные столбцы и возвращается через список таблицы, пока не будет найдена
таблица, для которой там больше соответствующих строк. Следующая строка
читается из этой таблицы, и процесс продолжается со следующей таблицей.
Вывод из EXPLAIN
включает в себя следующие столбцы:
table
type
possible_keys
possible_keys
указывает, какие индексы MySQL мог бы
использовать, чтобы найти строки в этой таблице. Обратите внимание, что этот
столбец полностью не зависит от порядка таблиц. Это означает, что некоторые
из ключей в possible_keys не могут быть пригодны для использования
практически со сгенерированным порядком таблицы. Если этот столбец пуст, не
имеется никаких релевантных индексов. В этом случае, Вы можете улучшить
эффективность Вашего запроса, исследуя предложение WHERE
, чтобы
увидеть, обращается ли оно к некоторому столбцу или столбцам, которые были бы
подходящими для индексации. Если так, создайте соответствующий индекс, и
проверьте запрос с помощью EXPLAIN
снова. Подробности в разделе
"7.4 Синтаксис ALTER TABLE
". Чтобы увидеть, какие индексы таблица имеет, вызовите SHOW INDEX
FROM tbl_name
.
key
key
указывает ключ, который MySQL фактически решил
использовать. Если индекс не выбран, здесь будет NULL
. Если
MySQL выбирает неправильный индекс, Вы можете вынуждать MySQL использовать
другой индекс, используя myisamchk --analyze
. Можно применить и
USE INDEX/IGNORE INDEX
, подробности в разделе
"8.1.1 Синтаксис JOIN
".
key_len
key_len
указывает длину ключа, который MySQL решил
использовать. Длина равна NULL
, если key
равен
NULL
. Обратите внимание, что это сообщает нам, сколько частей
составного ключа фактически использует MySQL.
ref
ref
показывает, которые столбцы или константы
используются с key
, чтобы выбрать строки из таблицы.
rows
rows
указывает число строк, которые MySQL должен
исследовать, чтобы выполнить запрос.
Extra
Distinct
Not exists
LEFT JOIN
на запросе и
не будет исследовать большее количество строк в этой таблице для предыдущей
комбинации строк после того, как найдет одну строку, которая соответствует
критериям LEFT JOIN
. Имеется пример этого:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;Считается, что
t2.id
определен как NOT NULL
.
В этом случае MySQL просмотрит t1
и будет искать строки в
t2
через t1.id
. Если MySQL находит строку
соответствий в t2
, он знает, что t2.id
никогда не
может быть NULL
, и не будет просматривать остальную часть строк
в t2
, которые имеют тот же самый идентификатор id
.
Другими словами, для каждой строки в t1
MySQL должен делать
только одиночную поисковую таблицу в t2
независимо от того,
сколько соответствий строк находится в t2
.
range checked for each record (index map: #)
Using filesort
join type
) и сохраняя ключ
сортировки+указатель на строку для всех строк, которые соответствуют
WHERE
. Затем ключи сортируются. В заключение строки будут
получены в сортируемом порядке.
Using index
Using temporary
ORDER BY
на наборе столбцов, отличном от того, который
был задан в предложении GROUP BY
.
Where used
WHERE
будет использоваться, чтобы ограничить то,
которые строки будут согласованы для следующей таблицы или посланы
пользователю. Если Вы не имеете эту информацию, и таблица имеет тип
ALL
или index
, Вы можете иметь что-то неправильное
в Вашем запросе (если Вы не предполагаете выбирать/исследовать все строки из
таблицы). Если Вы хотите получать ответы на Ваши запросы с такой скоростью, с
какой только возможно, Вы должны рассмотреть применение Using
filesort
и Using temporary
.Различные типы объединения перечислены ниже в порядке от лучших к худшим:
system
const
.
const
const
очень быстры, поскольку они доступны
для чтения только однажды!
eq_ref
const
. Это используется, когда все части индекса применяются
объединением, и индекс UNIQUE
или PRIMARY KEY
.
ref
ref
используется, если объединение использует только крайний
левый префикс ключа, или если ключ не UNIQUE
или PRIMARY
KEY
(другими словами, если объединение не может выбирать одиночную
строку, основанную на значении ключа).
range
key
указывает,
который индекс используется. Столбец key_len
содержит самую
длинную часть ключа, которая использовалась. Столбец ref
для этого типа будет NULL.
index
ALL
, за исключением того, что только индексное
дерево будет просмотрено. Это обычно быстрее, чем ALL
, поскольку
индексный файл обычно меньше, чем файл данных.
ALL
const
, и обычно
очень плохо во всех других случаях. Вы обычно можете
избежать ALL
, добавляя большее количество индексов, так, чтобы
строка могла быть найдена, основываясь на постоянных значениях или значениях
столбца более ранних таблиц.Вы можете получать хорошую индикацию относительно того, насколько хорошим
является объединение, умножая все значения в столбце rows
вывода
EXPLAIN
. Это должно сообщить Вам грубо, сколько строк MySQL
должен исследовать, чтобы выполнить запрос. Это число также используется,
когда Вы ограничиваете запросы переменной max_join_size
.
Подробности в разделе "14.5.2
Настройка параметров сервера".
Следующий пример показывает, как JOIN
может быть
оптимизирован, прогрессивно используя информацию, предоставляемую
EXPLAIN
.
Предположим, что Вы имеете инструкцию SELECT
, показанную
ниже, и что Вы исследуете ее, используя EXPLAIN
:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC=et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
Например, предположим, что:
Таблица | Столбец | Тип столбца |
tt | ActualPC |
CHAR(10) |
tt | AssignedPC |
CHAR(10) |
tt | ClientID |
CHAR(10) |
et | EMPLOYID |
CHAR(15) |
do | CUSTNMBR |
CHAR(15) |
Таблица | Индекс |
tt | ActualPC |
tt | AssignedPC |
tt | ClientID |
et | EMPLOYID (первичный ключ) |
do | CUSTNMBR (первичный ключ) |
tt.ActualPC
распределены неравномерно.Первоначально, прежде, чем выполнились любые оптимизации, инструкция
EXPLAIN
производит следующую информацию:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 range checked for each record (key map: 35)
Поскольку type
равен ALL
для каждой таблицы,
этот вывод указывает, что MySQL делает полное объединение для всех таблиц!
Это займет очень длительное время, поскольку большое число строк в каждой
таблице должно быть исследовано! Для нашего случая это
74*2135*74*3872=45268558720
строк. Если бы таблицы были больше,
Вы можете только воображать, как много времени потребуется.
Одна проблема здесь состоит в том, что MySQL не может использовать
индексы на столбцах эффективно, если они объявлены по-другому. В этом
контексте VARCHAR
и CHAR
то же самое, если они не
объявлены как различные длины. Потому, что tt.ActualPC
определен
как CHAR(10)
, а et.EMPLOYID
объявлен как
CHAR(15)
, имеется несоответствие длин.
Чтобы исправить это неравенство между длинами столбца, используйте
ALTER TABLE
, чтобы удлинить ActualPC
с 10 до 15:
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
Теперь tt.ActualPC
и et.EMPLOYID
равны
VARCHAR(15)
. Выполнение инструкции EXPLAIN
производит этот результат:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1) et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
Это еще не совершенно, но намного лучше. Эта версия выполнена быстрее.
Второе исправление может быть сделано, чтобы устранить несоответствия длин
столбцов для сравнений tt.AssignedPC=et_1.EMPLOYID
и
tt.ClientID=do.CUSTNMBR
:
mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15), MODIFY ClientID VARCHAR(15);
Сейчас EXPLAIN
выведет следующее:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Это почти столь же хорошо, как это возможно вообще. Но все же еще недостаточно хорошо. Продолжим...
Остающаяся проблема состоит в том, что по умолчанию MySQL считает, что
значения в столбце tt.ActualPC
равномерно распределены, а это не
имеет место для таблицы tt
. Можно просто сообщить MySQL об этом:
shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt shell> mysqladmin refresh
Теперь объединение совершенно, и EXPLAIN
выведет такой отчет:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Обратите внимание, что столбец rows
в выводе
EXPLAIN
представляет собой обучаемое предположение оптимизатора
объединения MySQL. Чтобы оптимизировать запрос, Вы должны проверить, являются
ли числа близкими к истине. Если это не так, Вы можете получить лучшую
эффективность, используя STRAIGHT_JOIN
в Вашей инструкции
SELECT
и пробуя внести в список таблицы в различном порядке в
предложении FROM
запроса.
В большинстве случаев Вы можете оценивать эффективность, считая дисковые
установки. Для маленьких таблиц Вы можете обычно находить строку за одну
дисковую установку (поскольку индекс, вероятно, кэшируется). Для больших
таблиц Вы можете оценивать (используя индексы дерева B++), что надо
log(число строк)/log(длина блока индекса/3*2/(длина индекса+длина
указателя данных))+1
установок, чтобы найти строку.
В MySQL блок индекса обычно равен 1024 байтам, а длина указателя данных
составляет 4 байта. 500000 строк с индексом длиной в 3 (medium integer)
обрабатываются за log(500000)/log(1024/3*2/(3+4))+1
=4.
Поскольку вышеупомянутый индекс требовал бы приблизительно 500000*7*3/2=14.2M (считается, что индексные буфера заполнены на 2/3, что является типичным), Вы будете, вероятно, иметь многое из индекса в памяти, и Вы будете, вероятно, нуждаться только в 1-2 обращениях, чтобы читать данные из OS, чтобы найти строку.
Для записи, однако, Вы будете нуждаться в 4 запросах установки (как показано выше), чтобы найти, где поместить новый индекс, и обычно в 2 установках, чтобы модифицировать индекс и записать строку данных.
Обратите внимание, что вышеупомянутое не означает, что Ваша прикладная программа будет требовать сложности N log N! Пока все кэшируется OS или SQL-сервером, работа будет идти только незначительно медленнее в то время, как таблица становится большей. После того, как данные становятся слишком большими, чтобы кэшироваться, работа будет идти намного медленнее, пока Ваши прикладные программы ограничены дисковыми установками (которые растут как N log N). Чтобы избежать этого, увеличьте индексный кэш, поскольку данные растут. Подробности в разделе "14.5.2 Настройка параметров сервера ".
SELECT
Вообще, когда Вы хотите сделать медленный SELECT ... WHERE
быстрее, первое, что подлежит проверке, можете или нет Вы добавить индекс.
Подробности в разделе "14.4.3 Как MySQL
использует индексы". Все ссылки между различными таблицами должны обычно
делаться с индексами. Вы можете использовать команду EXPLAIN
,
чтобы определить, которые индексы используются для SELECT
.
Подробности в разделе "14.2.1 Синтаксис
EXPLAIN
(получение информации о SELECT
)".
Некоторые общие советы:
myisamchk
--analyze
на таблице после того, как она была загружена релевантными
данными. Это модифицирует значение для каждой индексной части, которая
указывает среднее число строк, которые имеют то же самое значение. Для
уникальных индексов, это всегда 1, конечно. MySQL использует это, чтобы
решить, которые индексы выбрать, когда Вы подключаете две таблицы с
неконстантным выражением. Вы можете проверять результат из
analyze
выполнением SHOW INDEX FROM table_name
и
исследования столбца Cardinality
.
myisamchk --sort-index --sort-records=1
(если Вы хотите
сортировать на индексе 1). Если Вы имеете уникальный индекс, из которого Вы
хотите читать все записи, это хороший способ сделать процесс быстрее.
Обратите внимание, однако, что эта сортировка не написана оптимально и будет
брать довольно длительное время для большой таблицы!WHERE
Оптимизация WHERE
помещена в часть SELECT
потому,
что она обычно используется с SELECT
, но теми же самыми методами
оптимизируются инструкции DELETE
и UPDATE
.
Также обратите внимание, что этот раздел незавершен. MySQL делает много оптимизаций, и авторы пакета не имели времени, чтобы документировать их все.
Некоторые из оптимизаций, выполняемых MySQL перечислены ниже:
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> B=5 OR B=6
COUNT(*)
на одиночной таблице без WHERE
получен непосредственно из информации таблицы. Это также выполнено для любого
выражения NOT NULL
, когда используется только с одной таблицей.
SELECT
невозможны, и не
возвращает никаких строк.
HAVING
объединено с WHERE
, если Вы не
используете GROUP BY
или групповые функции
(COUNT()
, MIN()
...).
WHERE
будет создан,
чтобы получить быструю оценку WHERE
для каждого подобъединения,
а также пропускать все записи как можно скорее.
WHERE
на
индексе UNIQUE
или PRIMARY KEY
, где все индексные
части используются с постоянными выражениями и индексными частями, определена
как NOT NULL
.mysql> SELECT * FROM t WHERE primary_key=1; mysql> SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
ORDER BY
и в
GROUP BY
исходят из той же самой таблицы, то эта таблица
использована сначала при объединении.
ORDER BY
и отличное от него
предложение GROUP BY
, или если ORDER BY
или
GROUP BY
содержит столбцы из таблиц, иных, чем первая таблица в
очереди объединений, создается временная таблица.
SQL_SMALL_RESULT
, MySQL использует
временную таблицу в памяти.
HAVING
, будут пропущены.Некоторые примеры запросов, которые являются очень быстрыми:
mysql> SELECT COUNT(*) FROM tbl_name; mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name; mysql> SELECT MAX(key_part2) FROM tbl_name WHERE key_part_1=constant; mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... LIMIT 10; mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
Следующие запросы решены, используя только индексное дерево (все индексированные столбцы числовые):
mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val; mysql> SELECT COUNT(*) FROM tbl_name WHERE key_part1=val1 AND key_part2=val2; mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;
Следующие запросы применяют индексы, чтобы получить строки в сортируемом порядке без отдельного прохода сортировки:
mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... ; mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,... ;
DISTINCT
DISTINCT
преобразован в GROUP BY
на всех
столбцах, DISTINCT
объединенный с ORDER BY
тоже
будет во многих случаях нуждаться во временной таблице.
При объединении LIMIT #
с DISTINCT
, MySQL
остановится, как только успешно найдет #
уникальных строк.
Если Вы не используете столбцы из всех применяемых таблиц, MySQL остановит просмотр неиспользуемых таблиц, как только найдет первое соответствие.
SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;
В этом случае t1 используется прежде t2 (проверьте с помощью
EXPLAIN
), затем MySQL перестанет читать из t2 (для той
специфической строки в t1), когда первая строка в t2 будет найдена.
LEFT JOIN
и RIGHT JOIN
Действие A LEFT JOIN B
в MySQL выполнено следующим образом:
B
установлена, чтобы зависеть от таблицы
A
, и всех таблиц, которые зависят от A
.
A
, чтобы зависеть от всех таблиц за
исключением B
, которые используются в
условии LEFT JOIN
.
LEFT JOIN
перемещаются в WHERE
.
WHERE
выполнены.
A
, которая соответствует предложению
WHERE
, но не имеется никакой строки в B
, которая
соответствует условию LEFT JOIN
, то дополнительные строки
B
сгенерированы со всем набором столбцов в NULL
.
LEFT JOIN
, чтобы найти строки, которые
не существуют в некоторой таблице, и Вы имеете следующий тест:
column_name IS NULL
в части WHERE
, где column_name
представляет собой столбец, который объявлен как NOT NULL
, то
MySQL перестанет искать после большего количества строк (для специфической
комбинации ключа после того, как найдет одну строку, которая соответствует
условию LEFT JOIN
).RIGHT JOIN
реализован аналогично LEFT JOIN
.
Порядок чтения таблицы, принудительно заданный LEFT JOIN
и
STRAIGHT JOIN
, поможет оптимизатору объединения (который
вычисляет, в каком порядке таблицы должны быть соединены) сделать работу
намного быстрее, так как имеется меньшее количество перестановок таблицы,
которые надо проверить.
Обратите внимание, что вышеупомянутое означает, что, если Вы делаете запрос типа:
SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key
MySQL будет делать полный просмотр b
, поскольку LEFT
JOIN
вынудит это читаться прежде, чем d
.
Исправление в этом случае должно изменить запрос на:
SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key
LIMIT
В некоторых случаях MySQL обработает запрос по-другому, когда Вы
используете LIMIT #
и не используете HAVING
:
LIMIT
, MySQL
использует индексы в некоторых случаях, когда он обычно предпочел бы сделать
полный просмотр таблицы.
LIMIT #
в сочетании с ORDER
BY
, MySQL закончит сортировку, как только найдет первые #
строк вместо того, чтобы сортировать целую таблицу.
LIMIT #
с DISTINCT
MySQL
остановится, как только найдет #
уникальных строк.
GROUP BY
может быть решено, читая ключ
по порядку (или сортируя по ключу) с последующим вычислением результата до
изменений значения ключа. В этом случае LIMIT #
не будет
вычислять никакую ненужную операцию GROUP BY
.
#
строк пользователю, он
прервет текущий запрос.
LIMIT 0
будет всегда быстро возвращать пустой набор. Это
полезно, чтобы проверить запрос и получить типы столбцов результата.
LIMIT #
, чтобы вычислить,
сколько места необходимо, чтобы решить этот запрос.INSERT
Время, нужное, чтобы вставить запись, состоит приблизительно из:
Здесь числа пропорциональны полному времени. Это не учитывает время, нужное, чтобы открыть таблицы (это выполнено лишь однажды для каждого одновременно выполняемого запроса).
Размер таблицы замедляет вставку индексов на N log N (B-деревья).
Некоторые способы ускорить вставки:
INSERT
. Это намного быстрее, чем использование отдельных
инструкций INSERT
. Грамотная настройка переменной
myisam_bulk_insert_tree_size
может сделать это даже быстрее.
Подробности в разделе "4.10.4
SHOW VARIABLES
".
INSERT DELAYED
.
Подробности в разделе "8.3 Синтаксис
INSERT
".
MyISAM
Вы можете вставлять строки
в то же самое время, когда работает SELECT
, если не имеется
никаких удаленных строк в таблицах.
LOAD DATA
INFILE
. Это примерно в 20 раз быстрее, чем использование набора
команд INSERT
. Подробности в разделе
"8.9 Синтаксис LOAD DATA INFILE
".
LOAD DATA INFILE
, когда
таблица имеет много индексов. Используйте следующую процедуру:
CREATE TABLE
.
Например, при использовании mysql
или Perl-DBI.
FLUSH TABLES
или команду оболочки
mysqladmin flush-tables
.
myisamchk --keys-used=0 -rq /path/to/db/tbl_name
.
Это удалит все применяемые индексы из таблицы.
LOAD DATA INFILE
.
Это не будет модифицировать никакие индексы вообще и, следовательно, будет
работать очень быстро.
myisampack
, чтобы сделать ее еще меньше.
myisamchk -r -q
/path/to/db/tbl_name
. Это создаст индексное дерево в памяти перед
записью его на диск, что является намного быстрее потому, что это избегает
большого количества дисковых установок. Возникающее в результате индексное
дерево также совершенно сбалансировано.
FLUSH TABLES
или команду оболочки
mysqladmin flush-tables
.LOAD DATA INFILE
в некоторой
будущей версии MySQL. Начиная с MySQL 4.0, Вы также можете
использовать ALTER TABLE tbl_name DISABLE KEYS
вместо
myisamchk --keys-used=0 -rq /path/to/db/tbl_name
и
ALTER TABLE tbl_name ENABLE KEYS
вместо
myisamchk -r -q /path/to/db/tbl_name
. Этим путем Вы также
можете обойти шаг FLUSH TABLES
.
mysql> LOCK TABLES a WRITE; mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33); mysql> INSERT INTO a VALUES (8,26),(6,29); mysql> UNLOCK TABLES;Основное различие в быстродействии в том, что буфер индексов сбрасывают на диск только однажды после того, как все инструкции
INSERT
завершили. Обычно имелось бы так много индексных буферных потоков, сколько
есть различных инструкций INSERT
. Блокировка не является
необходимой, если Вы можете вставлять все строки с одиночной инструкцией.
Блокировка будет также снижать общее время тестов с несколькими
подключениями, но максимальное время ожидания для некоторых потоков повысится
(потому, что они ждут блокировки). Например:
thread 1 does 1000 inserts thread 2, 3, and 4 does 1 insert thread 5 does 1000 insertsЕсли Вы не используете блокировку, 2, 3 и 4 закончаться перед 1 и 14. Если Вы используете блокировку, 2, 3 и 4, вероятно, не будут заканчиваться прежде, чем 1 или 5, но общее время должно быть приблизительно на 40% лучше. Так как операции
INSERT
, UPDATE
и DELETE
очень
быстры в MySQL, Вы получите лучшую полную эффективность, добавляя блокировки
вокруг всего, что делает больше, чем приблизительно 5 вставок или модификаций
в строке. Если Вы делаете очень много вставок в строке, Вы могли бы делать
LOCK TABLES
, сопровождаемые UNLOCK TABLES
время от
времени (примерно каждые 1000 строк), чтобы позволить другим потокам доступ к
таблице. Конечно же, LOAD DATA INFILE
все равно намного быстрее
для загрузки данных.Чтобы дополнительно получить несколько большее быстродействие для операций
LOAD DATA INFILE
и INSERT
, увеличьте буфер ключа.
Подробности в разделе "14.5.2
Настройка параметров сервера".
UPDATE
Запросы модификации оптимизированы как запрос SELECT
.
Быстродействие дополнительной записи зависит от размера данных, которые
изменяются, и числа индексов, в которые вносятся поправки. Индексы, которые
не изменены, не будет модифицироваться.
Также, другой способ получать быстрые модификации состоит в том, чтобы задержать модификации, а затем сделать много модификаций в строке позже. Выполнение многих модификаций в строке намного более быстрое, чем выполнение их по одной, если Вы блокируете таблицу.
Обратите внимание, что, при работе с динамическим форматом записи
модификация записи на более длинную может привести к разделению ее на
фрагменты. Так что, если Вы делаете это часто, очень важно иногда вызывать
OPTIMIZE TABLE
. Подробности в разделе
"4.6 Синтаксис OPTIMIZE TABLE
".
DELETE
Если надо удалить все строки из таблицы, примените вызов
TRUNCATE TABLE table_name
. Подробности в разделе
"8.7 Синтаксис TRUNCATE
".
Время, нужное, чтобы удалить запись, точно пропорционально числу индексов. Чтобы удалять записи быстрее, Вы можете увеличивать размер индексного кэша. Подробности в разделе "14.5.2 Настройка параметров сервера".
thread_cache_size
. Подробности в разделе
"14.5.2 Настройка параметров сервера
".
EXPLAIN
. Подробности в разделе
"14.2.1 Синтаксис EXPLAIN
(получение информации о SELECT
)".
SELECT
на таблицах, которые часто
модифицируются. Это должно помочь избежать проблем с блокировкой таблицы.
MyISAM
могут вставлять строки в таблицу без
удаленных строк в то же самое время, когда другой запрос ведет чтение. Если
это важно для Вас, Вы должны рассмотреть методы, где Вы не должны удалить
строки или выполните OPTIMIZE TABLE
после того, как Вы удалили
много строк сразу.
ALTER TABLE ... ORDER BY expr1,expr2...
если Вы обычно получаете строки в порядке expr1,expr2,... . Используя эту
опцию после внесения больших изменений для таблицы, Вы можете получить
значительно более высокую эффективность.
SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND
col_1='constant' AND col_2='constant'
VARCHAR
или BLOB
. Вы получите
динамическую длину строки, как только Вы используете хоть один стобец
VARCHAR
или BLOB
.
UPDATE table set count=count+1 where
index_column=constant
очень быстрая! Это действительно важно, когда Вы
используете базы данных подобные MySQL, которые имеют только блокировку
уровня таблицы. Это также даст лучшую эффективность с большинством баз
данных, поскольку администратор блокировки строки в этом случае будет иметь
куда меньше работы.
INSERT /*! DELAYED */
, если Вы не должны знать,
когда Ваши данные будут записаны. Это ускоряет дела потому, что много записей
могут быть выполнены за один дисковый обмен.
INSERT /*! LOW_PRIORITY */
, когда Вы хотите,
чтобы Ваши вызовы select были более важными.
SELECT /*! HIGH_PRIORITY */
, чтобы получить
select, обходящий очередь. То есть select будет выполнен, даже если имеется
кто-то ждущий, чтобы сделать запись в таблицу.
INSERT
, чтобы сохранить
много строк одной командой SQL (многие серверы SQL поддерживают это).
LOAD DATA INFILE
, чтобы загрузить большие
количества данных. Это быстрее, чем нормальные вставки, а будет еще быстрее,
когда myisamchk
интегрирован в mysqld
.
AUTO_INCREMENT
, чтобы
сделать уникальные значения.
OPTIMIZE TABLE
время от времени, чтобы избежать
фрагментации при использовании динамического формата таблицы. Подробности в
разделе "4.6
Синтаксис OPTIMIZE TABLE
".
name
вместо customer_name
в таблице
заказчиков). Чтобы сделать Ваши имена переносными на другие SQL-серверы, Вы
должны озаботиться тем, чтобы они не превышали в длину 18 символов.
MyISAM
непосредственно, Вы могли бы получить увеличение быстродействия в 2-5 раз в
сравнении с использованием интерфейса SQL. Чтобы сделать это, данные должны
быть на том же самом сервере, что и прикладная программа, и обычно к ним
можно обратиться только одним процессом (потому, что внешняя блокировка файла
работает очень медленно). Можно было устранить вышеупомянутые проблемы,
представляя команды MyISAM
низкого уровня в сервере MySQL (это
могло бы быть одним простым способом получить большее количество
эффективности, если необходимо).
DELAY_KEY_WRITE=1
будет делать
модифицирование индексов быстрее, поскольку они не регистрируются на диске,
пока файл не закрыт. Обратная сторона в том, что Вы должны выполнить
myisamchk
на этих таблицах прежде, чем Вы запускаете
mysqld
, чтобы гарантировать, что они правильные, если что-то
уничтожило mysqld
в середине запроса. Поскольку информация ключа
может всегда генерироваться из данных, Вы не должны терять что-нибудь,
используя DELAY_KEY_WRITE
.Вся блокировка в MySQL свободна от тупика. Она управляется, всегда запрашивая все необходимые блокировки сразу в начале запроса и всегда блокируя таблицы в том же самом порядке.
Метод блокировки MySQL, использованный для операции WRITE
,
работает следующим образом:
Метод блокировки MySQL, использованный для операции READ
,
работает следующим образом:
Когда блокировка освобождается, она становится доступной потокам в очереди блокировок записи, а после них потокам в очереди блокировок чтения.
Это означает, что, если Вы имеете много модификаций на таблице, инструкции
SELECT
будут ждать до окончания всех модификаций.
Чтобы обойти это для случая, где Вы хотите делать много операций
INSERT
и SELECT
на таблице, Вы можете вставлять
строки во временную таблицу и периодически модифицировать реальную таблицу
записями из временной таблицы.
Это может быть выполнено кодом:
mysql> LOCK TABLES real_table WRITE, insert_table WRITE; mysql> insert into real_table select * from insert_table; mysql> TRUNCATE TABLE insert_table; mysql> UNLOCK TABLES;
Вы можете использовать параметр LOW_PRIORITY
с инструкциями
INSERT
, UPDATE
или DELETE
, а
HIGH_PRIORITY
только с SELECT
, если Вы хотите
располагать по приоритетам поиск в некоторых специфических случаях. Вы можете
также запустить mysqld
с параметром
--low-priority-updates
, чтобы получить тот же самое поведение.
Использование SQL_BUFFER_RESULT
может также сделать
блокировку таблицы короче. Подробности в разделе
"8.1 Синтаксис SELECT
".
Вы могли бы также изменять код блокировки в mysys/thr_lock.c, чтобы использовать одиночную очередь. В этом случае блокировки записи и чтения имели бы тот же самый приоритет, что может помочь некоторым программам.
Код блокировки таблиц в MySQL свободен от тупиков.
MySQL использует блокировку таблицы (вместо блокировки строки или столбца)
на всех типах таблицы, за исключением BDB
, чтобы достичь очень
высокого быстродействия блокировки. Для больших таблиц блокировка таблицы
НАМНОГО лучше, чем блокировка строки для большинства прикладных программ, но
имеются, конечно, некоторые ловушки.
Для таблиц типов BDB
и InnoDB
MySQL использует
блокировку таблицы только, если Вы скомандовали LOCK TABLES
или
выполняете команду, которая изменит каждую строку в таблице подобно
ALTER TABLE
. Для этих типов таблицы я рекомендую Вам не
использовать LOCK TABLES
вообще.
В MySQL Version 3.23.7 и выше Вы можете вставлять строки в таблицы типа
MyISAM
в то же самое время, когда другие потоки читают из
таблицы. Обратите внимание, что в настоящее время это работает только, если
не имеется никаких отверстий после удаленных строк в таблице во время
вставки. Когда все отверстия будут заполнены новыми данными, параллельные
вставки снова будут допускаться автоматически.
Блокировка таблицы дает возможность многим потокам читать из таблицы в то же самое время, но если поток хочет писать в таблицу, он должен сначала получить исключительный доступ. В течение модификации все другие потоки, которые хотят обращаться к этой специфической таблице, будут ждать, пока модификация не завершится.
Поскольку модификации на таблицах обычно являются более важными, чем
SELECT
, все инструкции, которые модифицируют таблицу, имеют
более высокий приоритет, чем те инструкции, которые получают информацию из
таблицы. Вы можете изменять это, используя LOW_PRIORITY
с
инструкцией, которая делает модификацию, или HIGH_PRIORITY
с
SELECT
).
Начиная с MySQL Version 3.23.7, можно использовать переменную
max_write_lock_count
, чтобы заставить MySQL временно дать всем
инструкциям SELECT
, которые ждут таблицу, более высокий
приоритет после специфического числа вставок на таблице.
Блокировка таблицы, однако, не очень хороша в следующих случаях:
SELECT
, который берет длительное
время, чтобы выполниться.
UPDATE
на используемой
таблице. Этот клиент будет ждать, пока SELECT
не закончится.
SELECT
относительно той же самой таблицы. Поскольку UPDATE
имеет более
высокий приоритет, чем SELECT
, этот SELECT
будет
ждать UPDATE
, чтобы закончиться. Это будет также ждать, когда
закончится первый SELECT
!
full disk
, когда все потоки,
которые хотят обращаться к прикладной таблице, будут также помещены в
состояние ожидания до тех пор, пока большее количество дискового пространства
не станет доступно.Некоторые решения для этой проблемы:
SELECT
. Вам,
вероятно, придется создавать некоторые итоговые таблицы, чтобы сделать это.
mysqld
с опцией
--low-priority-updates
. Это даст всем инструкциям, которые
модифицируют таблицу, более низкий приоритет, чем инструкции
SELECT
. В этом случае последняя инструкция SELECT
в
предыдущем сценарии выполнилась бы перед инструкцией INSERT
.
INSERT
,
UPDATE
или DELETE
с более низким приоритетом,
указав атрибут LOW_PRIORITY
.
mysqld
с низким значением для
max_write_lock_count, чтобы дать блокировки
READ
после того, как отработает некоторое число блокировок
WRITE
.
SET SQL_LOW_PRIORITY_UPDATES=1
. Подробности в разделе
"14.5.6 Синтаксис SET
".
SELECT
очень важен с
помощью атрибута HIGH_PRIORITY
. Подробности в разделе
"8.1 Синтаксис SELECT
".
INSERT
, объединенной с
SELECT
, переключитесь, чтобы использовать новые таблицы типа
MyISAM
, поскольку они поддерживают параллельную работу вызовов
SELECT
и INSERT
.
INSERT
и
SELECT
, атрибут DELAYED
в вызове
INSERT
, вероятно, решит Ваши проблемы. Подробности в разделе
"8.3 Синтаксис INSERT
".
SELECT
и DELETE
,
опция LIMIT
в инструкции DELETE
может помочь.
Подробности в разделе "8.6 Синтаксис
DELETE
".MySQL хранит данные строк и индексные данные в отдельных файлах. Многие (почти все) другие базы данных смешивают строки и индексные данные в том же самом файле. Я полагаю, что выбор MySQL лучше для очень широкого диапазона современных систем.
Другой способ сохранять данные строк состоит в том, чтобы хранить информацию для каждого столбца в отдельной области (примеры: SDBM и Focus). Это вызовет падение эффективности для каждого запроса, который обращается больше, чем к одному столбцу. Эта модель далеко не хороша для построения универсальных баз данных.
Более общий случай: индекс и данные сохранены вместе (подобно Oracle/Sybase). В этом случае Вы найдете информацию строк в листе страниц индекса. Хорошо с этим размещением то, что во многих случаях, в зависимости от того, как хорошо индекс кэшируется, экономится медленное дисковое чтение. Плохо с этим размещением то, что:
Одна из наиболее распространенных оптимизаций должна получить Ваши данные и индексы, чтобы брать так мало места на диске, насколько возможно. Это может давать огромные улучшения потому, что диск читается меньше, и оперативная память экономится. Индексация также берет меньшее количество ресурсов, если выполнена на меньших столбцах.
MySQL поддерживает много различных типов таблиц и форматов строк. Выбор правильного формата таблицы может давать Вам большое усиление эффективности.
Вы можете получать лучшую эффективность на таблице и минимизировать "складские площади" на диске, используя методы, перечисленные ниже:
MEDIUMINT
часто бывает куда лучше,
чем INT
в чистом виде.
NOT NULL
, если это возможно. Это
сделает все быстрее, и Вы сэкономите один бит на столбец. Обратите внимание,
что, если Вы действительно нуждаетесь в NULL
в Вашей прикладной
программе, Вы должны определенно использовать это. Только не стоит иметь это
свойство заданным на всех столбцах по умолчанию.
VARCHAR
,
TEXT
или BLOB
), используется формат записи
фиксированного размера. Это работает быстрее, но, к сожалению, может тратить
впустую некоторое место.
Индексы используются, чтобы быстро найти строки со специфическим значением одного столбца. Без индекса MySQL должен начать с первой записи и затем пролистывать целую таблицу, пока не найдет релевантные строки. Если таблица имеет индекс для рассматриваемых столбцов, MySQL может быстро получить позицию, чтобы позиционироваться на середину файла данных без того, чтобы иметь необходимость рассматривать все данные. Если таблица имеет 1000 строк, это по крайней мере в 100 раз быстрее, чем последовательное чтение. Обратите внимание, что если Вы должны обратиться почти ко всем 1000 строкам, быстрее читать файл последовательно потому, что мы сэкономим дисковые установки.
Все индексы в MySQL (PRIMARY
, UNIQUE
и
INDEX
) сохранены в B-деревьях. Строки автоматически сжимаются с
использованием конечных пробелов и префикса. Подробности в разделе
"7.7 Синтаксис CREATE INDEX
".
Индексы используются для:
WHERE
.
MAX()
или MIN()
для
специфического индексированного столбца. Это оптимизировано препроцессором,
который проверяет, используете ли Вы WHERE
key_part_#=constant
на всех частях ключа <N. В этом случае MySQL будет делать одиночный поиск
ключа и заменит MIN()
выражением с константой. Если все
выражения заменятся на константы, запрос возвратится сразу:
SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
ORDER BY key_part_1,key_part_2
). Ключ читается в
обратном порядке, если все части ключа сопровождаются словом
DESC
. Индекс может также использоваться, даже если ORDER
BY
не соответствует индексу точно, пока все неиспользуемые индексные
части и все дополнительные столбцы в ORDER BY
представляют собой
константы в предложении WHERE
. Следующие запросы используют
индекс, чтобы решить часть ORDER BY
:
SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3; SELECT * FROM foo WHERE column=constant ORDER BY column, key_part1; SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
SELECT key_part3 FROM table_name WHERE key_part1=1
Предположим, что Вы выдаете следующую инструкцию SELECT
:
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
Если многостолбиковый индекс существует на col1
и
col2
, соответствующие строки могут быть выбраны непосредственно.
Если отдельные индексы с одним столбцом существуют на col1
и
col2
, оптимизатор пробует находить наиболее ограничительный
индекс, решая, который индекс найдет меньшее количество строк, и используя
этот индекс, чтобы выбрать строки.
Если таблица имеет
многостолбиковый индекс, любой крайний левый префикс индекса может
использоваться оптимизатором, чтобы найти строки. Например, если Вы имеете
индекс с тремя столбцами на (col1,col2,col3)
, Вы индексировали
возможности поиска на (col1)
, (col1,col2)
и
(col1,col2,col3)
.
MySQL не может использовать частичный индекс, если столбцы не формируют
крайний левый префикс из индекса. Предположим, что Вы имеете инструкции
SELECT
, показанные ниже:
mysql> SELECT * FROM tbl_name WHERE col1=val1; mysql> SELECT * FROM tbl_name WHERE col2=val2; mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
Если индекс существует на (col1,col2,col3)
, только первый
запрос, показанный выше, использует индекс. Второй и третий запросы включают
индексированные столбцы, но (col2)
и (col2,col3)
не крайние левые префиксы для (col1,col2,col3)
.
MySQL также использует индексы для сравнений
LIKE
, если параметр для LIKE
представляет собой
строку-константу, которая не начинается с группового символа. Например,
следующие инструкции SELECT
используют индексы:
mysql> select * from tbl_name where key_col LIKE "Patrick%"; mysql> select * from tbl_name where key_col LIKE "Pat%_ck%";
В первой инструкции только строки с "Patrick" <=key_col <
"Patricl"
рассматриваются. Во второй инструкции будут обработаны
только строки с "Pat" <=key_col < "Pau"
.
Следующие инструкции SELECT
не будут использовать индексы:
mysql> select * from tbl_name where key_col LIKE "%Patrick%"; mysql> select * from tbl_name where key_col LIKE other_col;
В первой инструкции значение LIKE
начинается с группового
символа. Во второй инструкции значение LIKE
не константа.
Поиск, использующий
column_name IS NULL
, применяет индексы, если column_name
представляет собой индекс.
MySQL обычно использует индекс, который находит наименьшее число строк.
Индекс используется для столбцов, которые Вы сравниваете следующими
операторами: =
, >
, >=
,
<
, <=
, BETWEEN
и
LIKE
с префиксом, представляющим собой не групповой символ,
например, допустимо something%
.
Любой индекс, который не охватывает все уровни AND
в
предложении WHERE
, не используется, чтобы оптимизировать запрос.
Другими словами: чтобы быть способным использовать индекс, префикс индекса
должен использоваться в каждом AND
в группе.
Следующие предложения WHERE
используют индексы:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3 ... WHERE index=1 OR A=10 AND index=2 /* index = 1 OR index = 2 */ ... WHERE index_part1='hello' AND index_part_3=5 /* optimized like "index_part1='hello'" */ ... WHERE index1=1 and index2=2 or index1=3 and index3=3; /* Can use index on index1 but not on index2 or index 3 */
Эти предложения WHERE
НЕ используют индексы:
... WHERE index_part2=1 AND index_part3=2 /* index_part_1 is not used */ ... WHERE index=1 OR A=10 /* Index is not used in both AND parts */ ... WHERE index_part1=1 OR index_part2=10 /* No index spans all rows */
Обратите внимание, что в некоторых случаях MySQL все равно не будет использовать индекс, даже если можно было бы это сделать. Это связано с особенностями логики СУБД. Некоторые из таких случаев:
LIMIT
,
чтобы получить только часть строк, MySQL использует индекс в любом случае,
поскольку может намного быстрее найти строки, возвращаемые в результате.Все типы столбцов MySQL могут быть индексированы. Использование индексов
на релевантных столбцах представляет собой самый лучший способ улучшить
эффективность операций SELECT
.
Максимальное число ключей и максимальная длина индекса определены в драйвере таблицы. Вы можете со всеми драйверами таблицы иметь по крайней мере 16 ключей и общую индексную длину по крайней мере в 256 байт.
Для столбцов типов CHAR
и VARCHAR
Вы можете
индексировать префикс столбца. Это намного быстрее и требует меньшего
количества дискового пространства, чем индексация целого столбца. Синтаксис,
который надо использовать в инструкции CREATE TABLE
, чтобы
индексировать префикс для столбца, выглядит следующим образом:
KEY index_name (col_name(length))
Пример ниже создает индекс первых 10 символов столбца name
:
mysql> CREATE TABLE test (name CHAR(200) NOT NULL, KEY index_name (name(10)));
Для столбцов BLOB
и TEXT
Вы должны индексировать
именно префикс столбца. Там Вы не можете индексировать весь столбец.
В MySQL Version 3.23.23 или позже Вы можете также создавать специальные
индексы FULLTEXT. Они используются для полнотекстового
поиска. Только тип таблицы MyISAM
поддерживает индексы
FULLTEXT
. Они могут быть созданы только из столбцов
VARCHAR
и TEXT
. Индексация всегда выполняется над
всем столбцом, частичная индексация пока не поддержана. Подробности в разделе
"9.4 Полнотекстовый поиск в MySQL".
MySQL может создавать индексы на нескольких столбцах. Индекс может
включать до 15 столбцов. На столбцах типов CHAR
и
VARCHAR
Вы можете использовать префикс столбца как часть индекса.
MySQL использует индексы на нескольких столбцах таким способом, что
запросы становятся более быстрыми, когда Вы определяете известное количество
данных для первого столбца индекса в предложении WHERE
, даже
если Вы не определяете значения для других столбцов вообще.
Предположим, что таблица создана, используя следующую спецификацию:
mysql> CREATE TABLE test (id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX name (last_name,first_name));
Индекс name
охватывает столбцы last_name
и
first_name
. Индекс будет использоваться для запросов, которые
определяют значения в известном диапазоне для last_name
или для
last_name
и first_name
вместе. Следовательно,
индекс name
будет использоваться для следующих запросов:
mysql> SELECT * FROM test WHERE last_name="Widenius"; mysql> SELECT * FROM test WHERE last_name="Widenius" AND first_name="Michael"; mysql> SELECT * FROM test WHERE last_name="Widenius" AND (first_name="Michael" OR first_name="Monty"); mysql> SELECT * FROM test WHERE last_name="Widenius" AND first_name >="M" AND first_name < "N";
Однако, индекс name
НЕ будет использоваться в запросах:
mysql> SELECT * FROM test WHERE first_name="Michael"; mysql> SELECT * FROM test WHERE last_name="Widenius" OR first_name="Michael";
За подробностями по улучшению работы с индексами в MySQL отсылаю Вас к разделу "14.4.3 Как MySQL использует индексы".
Переменные table_cache
, max_connections
и
max_tmp_tables
воздействуют на максимальное число файлов,
которые сервер хранит открытыми. Если Вы увеличиваете одно из них, Вы можете
нарваться на ограничение, наложенное Вашей операционной системой на число
описателей открытого файла на процесс. Однако, Вы можете обойти ограничение
многих систем. Консультируйтесь с Вашей документацией на OS, чтобы выяснить,
как это сделать потому, что методы для изменения ограничения везде свои.
Переменная table_cache
связана с max_connections
.
Например, для 200 параллельных подключений, Вы должны иметь кэш таблицы по
крайней мере 200*n
, где n
максимальное число таблиц
в объединении. Вы также должны резервировать некоторые описатели файла
дополнительно для временных таблиц и файлов.
Кэш открытых таблиц может расти до максимума, заданного
table_cache
(значение по умолчанию 64, это может быть изменено с
помощью опции -O table_cache=#
при вызове сервера
mysqld
). Таблица никогда не будет закрыта за исключением того
случая, когда кэш заполняется, а другой поток пробует открыть таблицу, или
если Вы используете команду mysqladmin refresh
или
mysqladmin flush-tables
.
Когда кэш таблицы заполняется, сервер использует следующую процедуру, чтобы найти запись кэша, которую надо использовать:
Таблица открыта для каждого параллельного доступа. Это означает, что, если
Вы имеете два потока, обращающиеся к той же самой таблице, или обращаетесь к
таблице дважды в том же самом запросе (через AS
), таблица должна
быть открыта дважды. Первое открытие любой таблицы берет два описателя файла,
каждое дополнительное использование таблицы берет только один описатель
файла. Лишний описатель для первого открытия используется для индексного
файла: этот описатель разделен между всеми потоками.
Вы можете проверять, является ли Ваш кэш таблицы слишком маленьким,
проверяя переменную opened_tables
в mysqld
. Если
это значение очень большое, даже если Вы не делали много вызовов
FLUSH TABLES
, Вы должны увеличить Ваш кэш таблицы. Подробности в
разделе "4.10.3 SHOW STATUS
".
Если Вы имеете много файлов в каталоге, операции открытия, закрытия и
создания будут медленными. Если Вы выполняете инструкции SELECT
относительно многих различных таблиц, будет иметься некоторое замедление,
когда кэш таблицы заполнится потому, что для каждой таблицы, которая должна
быть открыта, другая закроется. Вы можете уменьшить задержку, делая больше
кэш для таблиц.
Когда Вы выполняете mysqladmin status
, Вы будете видеть нечто
вроде этого вывода:
Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
Это может несколько озадачить, если Вы имеете только 6 таблиц.
MySQL представляет собой многопоточное приложение, так что он может иметь много запросов к той же самой таблице одновременно. Чтобы минимизировать проблему с двумя потоками, имеющими различные состояния на том же самом файле, таблица будет открыта независимо каждым параллельным потоком. Это берет некоторую дополнительную память и один описатель файла для файла данных. Описатель индексного файла разделен между всеми потоками.
Начнем обзор с уровня системы, так как некоторые из этих решений должны быть сделаны очень рано. В других случаях рассмотрение будет не очень глубоким потому, что не сможет сильно повлиять на результаты. Однако, всегда хорошо иметь представление относительно того, сколько можно извлечь пользы, меняя настройки на этом уровне.
Используемая OS очень важна! Чтобы с толком использовать многопроцессорные системы, нужно применять Solaris (потому, что потоки там работают очень хорошо) или Linux (потому, что ядро 2.2 имеет очень приличную поддержку SMP). Также на 32-разрядных машинах Linux имеет ограничение в 2G для размера файла по умолчанию. Но это исправлено в файловых системах XFS/Reiserfs. Если Вы имеете потребность в файлах больше, чем 2G, на Linux-intel 32 bit, Вы должны получить заплату LFS для файловой системы ext2.
Другие советы и предупреждения:
--skip-locking
в MySQL, чтобы избежать
внешней блокировки. Обратите внимание, что это не будет воздействовать на
функциональные возможности MySQL, пока Вы выполняете только один сервер.
Только не забудьте завершить сервер (или блокировать релевантные части)
прежде, чем Вы выполните myisamchk
. На некоторых системах эта
опция обязательна потому, что внешняя блокировка не работает в любом случае.
Опция --skip-locking
по умолчанию включена при компиляции с
MIT-pthreads потому, что flock()
не полностью поддержан
MIT-pthreads на всех платформах. Это также значение по умолчанию для Linux,
поскольку блокировка файлов в Linux еще не безопасна. Единственный случай,
когда Вы не можете использовать --skip-locking
: если Вы
выполняете много серверов MySQL (не клиентов) на тех же самых данных или
выполняете myisamchk
на таблице без предварительной блокировки
сервера и сброса таблиц на диск. Вы можете применять
LOCK TABLES
/UNLOCK TABLES
, даже если Вы используете
опцию --skip-locking
Вы можете получать заданные по умолчанию буферные размеры, используемые
сервером mysqld
, этой командой:
shell> mysqld --help
Эта команда производит список всех параметров mysqld
и
переменных с перестраиваемой конфигурацией. Вывод включает значения по
умолчанию и выглядит так:
Possible variables for option --set-variable (-O) are: back_log current value: 5 bdb_cache_size current value: 1048540 binlog_cache_size current_value: 32768 connect_timeout current value: 5 delayed_insert_timeout current value: 300 delayed_insert_limit current value: 100 delayed_queue_size current value: 1000 flush_time current value: 0 interactive_timeout current value: 28800 join_buffer_size current value: 131072 key_buffer_size current value: 1048540 lower_case_table_names current value: 0 long_query_time current value: 10 max_allowed_packet current value: 1048576 max_binlog_cache_size current_value: 4294967295 max_connections current value: 100 max_connect_errors current value: 10 max_delayed_threads current value: 20 max_heap_table_size current value: 16777216 max_join_size current value: 4294967295 max_sort_length current value: 1024 max_tmp_tables current value: 32 max_write_lock_count current value: 4294967295 myisam_sort_buffer_size current value: 8388608 net_buffer_length current value: 16384 net_retry_count current value: 10 net_read_timeout current value: 30 net_write_timeout current value: 60 query_buffer_size current value: 0 record_buffer current value: 131072 record_rnd_buffer current value: 131072 slow_launch_time current value: 2 sort_buffer current value: 2097116 table_cache current value: 64 thread_concurrency current value: 10 tmp_table_size current value: 1048576 thread_stack current value: 131072 wait_timeout current value: 28800
Если имеется работающий сервер mysqld
, Вы можете увидеть,
какие значения он фактически использует для переменных, выполняя эту команду:
shell> mysqladmin variables
Вы можете находить полное описание для всех переменных в разделе
"4.10.4 SHOW VARIABLES
".
Вы можете также видеть некоторую статистику с сервера, выдавая команду
SHOW STATUS
. Подробности в разделе
"4.10.3 SHOW STATUS
".
MySQL использует алгоритмы, которые являются очень хорошо масштабируемыми, так что Вы обычно можете работать с очень небольшой памятью. Если Вы даете MySQL больше памяти, Вы обычно будете получать лучшую эффективность.
При настройке сервера MySQL есть две наиболее важных переменных:
key_buffer_size
и table_cache
.
Если Вы имеете много памяти (>=256M) и много таблиц и хотите получить максимальную эффективность с умеренным числом клиентов, Вы должны использовать нечто подобное этому:
shell> safe_mysqld -O key_buffer=64M -O table_cache=256 \ -O sort_buffer=4M -O record_buffer=1M &
Если Вы имеете только 128M и всего несколько таблиц, но Вы делаете много сортировок, Вы можете использовать нечто, подобно этому:
shell> safe_mysqld -O key_buffer=16M -O sort_buffer=1M
Если Вы имеете небольшую память и большое количество подключений, используйте следующее решение:
shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k \ -O record_buffer=100k &
Или вот это:
shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k \ -O table_cache=32 -O record_buffer=8k \ -O net_buffer=1K &
Если Вы делаете GROUP BY
или ORDER BY
на файлах,
которые являются намного больше, чем Ваша доступная память, Вы должны
увеличить значение record_rnd_buffer
, чтобы ускорить чтение
строк после того, как сортировка будет выполнена.
Когда Вы установили MySQL, каталог support-files будет хранить
некоторые различные файлы примера my.cnf
, например,
my-huge.cnf, my-large.cnf, my-medium.cnf и
my-small.cnf, которые Вы можете использовать как основу, чтобы
оптимизировать Вашу систему.
Если имеется очень много подключений, может происходить ``swapping
problem'', если mysqld
не был конфигурирован, чтобы использовать
очень небольшую память для каждого подключения. Конечно, mysqld
работает много лучше, если Вы имеете достаточно памяти для всех подключений.
Обратите внимание, что, если Вы изменяете опцию mysqld
, это
остается в силе только для этого образца станции.
Чтобы увидеть эффект от изменения параметра, сделайте:
shell> mysqld -O key_buffer=32m --help
Удостоверьтесь, что опция --help
последняя; иначе эффект
любых перечисленных на командной строке после нее параметров не будет
отражен в выводе.
Большинство следующих тестов выполнено на Linux с эталонными тестами MySQL, но они должны дать некоторые данные для других операционных систем и рабочих нагрузок системы.
Вы получаете самую быструю выполнимую программу, когда Вы компонуете ее с
опцией времени компоновки -static
.
В Linux Вы получите самый быстрый код при компиляции с pgcc
и опцией -O3
. Чтобы откомпилировать sql_yacc.cc с этими
параметрами, Вы нуждаетесь примерно в 200M памяти потому, что
gcc/pgcc
требует много памяти, чтобы сделать все функции
встроенными. Вы должны также установить CXX=gcc
при
конфигурировании MySQL, чтобы избежать включения библиотеки
libstdc++
. Обратите внимание, что при работе с некоторыми
версиями pgcc
возникающий в результате код выполнится только на
истинных процессорах Pentium, даже если Вы используете опцию транслятора,
чтобы возникающий в результате код работал на всех процессорах типа x586.
Только используя лучший транслятор и/или лучшие параметры транслятора, Вы уже можете получить увеличение быстродействия Вашей прикладной программы на 10-30%! Это особенно важно, если Вы компилируете SQL-сервер сами.
Авторы пакета проверили компиляторы Cygnus CodeFusion и Fujitsu, но на момент этого тестирования они были недостаточно свободны от ошибок, чтобы позволить MySQL компилироваться с включенной оптимизацией.
Когда Вы компилируете MySQL, Вы должны включить поддержку только для тех
наборов символов, которые Вы собираетесь использовать (опция
--with-charset=xxx
). Стандартные двоичные дистрибутивы MySQL
компилируются с поддержкой всех наборов символов.
Имеется список некоторых измерений, которые сделали авторы пакета:
pgcc
и компилируете все с опцией
-O6
, сервер mysqld
на 1% быстрее, чем с
gcc
2.914.2.
-static
), результат на
14% медленнее в Linux. Обратите внимание, что Вы все еще можете использовать
динамическую библиотеку MySQL. Это критично только для сервера.
mysqld
командой strip
libexec/mysqld
, возникающий в результате двоичный код может
быть до 4% быстрее.
localhost
, MySQL по умолчанию использует именно сокеты.
--with-debug=full
, теряете 20%
скорости для большинства запросов, но некоторые запросы могут еще более
замедлиться (эталонные тесты до 36%). Если Вы используете
--with-debug
, потери составят около 15%. Запуская
mysqld
, скомпилированный с опцией
--with-debug=full
, с --skip-safemalloc
конечный
результат должен быть близок к варианту --with-debug
.
gcc
2.914.2.
gcc
2.914.2 для ultrasparc с опциями
-mcpu=v8 -Wa,-xarch=v8plusa
дает еще 4% эффективности.
--log-bin
сделает MySQL
примерно на 1% медленнее.
-fomit-frame-pointer
или -fomit-frame-pointer
-ffixed-ebp
делает mysqld
на 1-4% быстрее.Дистрибутив MySQL-Linux, собранный в MySQL AB, использовал
pgcc
, но из-за ошибки при работе на процессорах AMD (причина в
компиляторе, а не в процессорах, они-то как раз отменные!) теперь снова
применяется обычный gcc, и так будет до тех пор, пока та ошибка не будет
решена авторами транслятора. Тем временем, если Вы имеете не-AMD машину, Вы
можете попробовать применить pgcc
. Правда, не очень ясно, кто
победит в этом споре: то ли более совершенный компилятор pgcc
,
то ли процессоры от AMD, которые просто по конструкции быстрее Intel...
Стандартный двоичный дистрибутив MySQL для Linux скомпонован статически,
чтобы получить большие быстродействие и переносимость.
Список ниже указывает некоторые из путей, которыми сервер
mysqld
использует память. Там, где это нужно и важно, указаны
имена соответствующих переменных сервера.
key_buffer_size
) разделен всеми
потоками. Другие буфера, используемые сервером, распределены как необходимо.
Подробности в разделе "14.5.2
Настройка параметров сервера".
thread_stack
),
буфер подключений (переменная net_buffer_length
) и буфер
результатов (переменная net_buffer_length
). Буфер подключений и
буфер результатов будут динамически расширены до
max_allowed_packet
, когда это будет необходимо. Когда запрос
обрабатывается, копия текущей строки запроса также распределена.
record_buffer
).
record_rnd_buffer
).
BLOB
сохранены на
диске. Одна проблема в MySQL до Version 3.23.2 состоит в том, что, если
таблица HEAP превышает размер tmp_table_size
, Вы получите ошибку
The table tbl_name is full
. В более новых версиях это обработано
автоматической заменой таблиц в памяти на дисковые по мере необходимости.
Чтобы обойти эту проблему Вы можете увеличивать временный размер таблицы,
устанавливая опцию tmp_table_size
в mysqld
или
устанавливая в программе пользователя SQL-опцию SQL_BIG_TABLES
.
Подробности в разделе "14.5.6 Синтаксис
SET
". В MySQL Version 3.20 максимальный размер временной
таблицы был record_buffer*16
так, что, если Вы используете эту
версию, Вы должны увеличить значение record_buffer
. Вы можете
также запустить mysqld
с опцией --big-tables
,
чтобы всегда сохранять временные таблицы на диске. Однако, это будет плохо
воздействовать на быстродействие очень многих сложных запросов.
malloc()
и free()
).
3*n
(где n
максимальная длина строки, не
считая столбцы типа BLOB
). BLOB
использует от 5 до
8 байт плюс длина данных BLOB
. Драйвер таблиц
ISAM
/MyISAM
распределяет один буфер строк
дополнительно для внутреннего использования.
BLOB
, буфер будет
расширен динамически, чтобы читать большие значения BLOB
.
Если Вы просматриваете таблицу, распределяется буфер такого размера, как
самое большое значение BLOB
.
mysqladmin flush-tables
закрывает все таблицы,
которые не находятся в использовании, и отмечает все таблицы, находящиеся в
использовании, чтобы они были закрыты, когда работающий в настоящее время
поток завершится. Это действительно освободит много памяти.ps
и другие программы состояния системы может сообщать, что
mysqld
использует много памяти. Это может быть вызвано стеками
потоков на различных адресах памяти. Например, Solaris-версия ps
считает неиспользуемую память между стеками как используемую память! Вы
можете выяснить это, проверяя доступный своп командой swap -s
.
Сервер mysqld
проверен с коммерческими детекторами утечки
памяти, так что в нем не должно иметься никаких утечек памяти.
Когда новый процесс соединяется с mysqld
, он запустит новый
поток, чтобы обработать запрос. Этот поток сначала проверит, находится ли
hostname в кэше hostname. Если нет, поток вызовет
gethostbyaddr_r()
и gethostbyname_r()
, чтобы
получить адрес машины.
Если операционная система не поддерживает вышеупомянутые
поточно-безопасные обращения, поток блокирует mutex и вызывает
gethostbyaddr()
и gethostbyname()
. Обратите
внимание, что в этом случае никакой другой поток не может обработать другое
имя до завершения первого потока.
Вы можете отключить поддержку DNS запуском mysqld
с опцией
--skip-name-resolve
. В этом случае Вы можете использовать только
IP-адреса в таблицах привилегий MySQL.
Если Вы имеете очень медленный DNS и много компьютеров, Вы можете
получать большую эффективность отключая DNS опцией
--skip-name-resolve
или увеличивая определение
HOST_CACHE_SIZE
(значение по умолчанию: 128) с последующей
перекомпиляцией сервера mysqld
.
Вы можете отключать кэш hostname с помощью опции
--skip-host-cache
. Вы можете очищать кэш hostname с помощью
команд FLUSH HOSTS
или mysqladmin flush-hosts
.
Если Вы не хотите позволять подключения по TCP/IP
, Вы можете
сделать это, запуская mysqld
с опцией
--skip-networking
.
SET
SET [OPTION] SQL_VALUE_OPTION=value, ...
SET OPTION
устанавливает различные параметры, которые
воздействуют на работу клиента или сервера. Любая опция, которую Вы
устанавливаете, остается в силе до завершения текущего сеанса, или пока Вы не
установите ее в другое значение.
CHARACTER SET character_set_name|DEFAULT
character_set_name
является cp1251_koi8
, но Вы можете легко добавлять новые
отображения, редактируя файл sql/convert.cc в дистрибутиве исходных
текстов MySQL. Отображение значения по умолчанию может быть восстановлено,
используя значение DEFAULT
для переменной
character_set_name
. Обратите внимание, что синтаксис для
установки опции CHARACTER SET
отличается от синтаксиса для
установки других параметров.
PASSWORD=PASSWORD('some password')
PASSWORD FOR user=PASSWORD('some password')
mysql
может делать это. Пользователь должен быть указан в формате
user@hostname
, где user
и hostname
указаны точно так, как они перечислены в столбцах User
и
Host
записи в таблице mysql.user
. Например, если Вы
имели запись с полями User
и Host
равными
bob
и %.loc.gov
, Вы будете писать:
mysql> SET PASSWORD FOR bob@"%.loc.gov"=PASSWORD("newpass"); или mysql> UPDATE mysql.user SET password=PASSWORD("newpass") where user="bob' and host="%.loc.gov";
SQL_AUTO_IS_NULL=0|1
1
(значение по умолчанию), то можно
находить последнюю вставленную строку для таблицы с поддержкой
auto_increment применением следующей конструкции: WHERE
auto_increment_column IS NULL
. Это используется некоторыми программами
ODBC, например, Access.
AUTOCOMMIT=0|1
1
, все изменения для таблицы будут
выполнен сразу. Чтобы запустить многокомандную транзакцию, Вы должны
использовать инструкцию BEGIN
. Подробности в разделе
"9.2.1 Синтаксис
BEGIN/COMMIT/ROLLBACK
". Если установлено в 0
,
Вы должны использовать COMMIT
/ROLLBACK
, чтобы
принять или отменить эту транзакцию. Подробности в разделе
"9.2.1 Синтаксис
BEGIN/COMMIT/ROLLBACK
". Обратите внимание, что, когда Вы
изменяете режим с не-AUTOCOMMIT
на AUTOCOMMIT
,
MySQL автоматически будет делать COMMIT
на открытых транзакциях.
SQL_BIG_TABLES=0|1
1
, все временные
таблицы сохранены на диске, а не в памяти. Это будет немного медленнее, но Вы
не будете получать ошибку The table tbl_name is full
для больших
операций SELECT
, которые требуют большой временной таблицы.
Значение по умолчанию для нового подключения 0
(то есть
использовать временные таблицы в памяти).
SQL_BIG_SELECTS=0|1
0
, MySQL прервется, если
SELECT
, вероятно, будет брать очень длительное время. Это
полезно, когда была выдана нецелесообразная инструкция WHERE
.
Большой запрос определен как SELECT
, которому, вероятно,
придется исследовать больше, чем max_join_size
строк. Значение
по умолчанию для нового подключения: 1
(это позволяет выполнять
все инструкции SELECT
).
SQL_BUFFER_RESULT=0|1
SQL_BUFFER_RESULT
вынудит результат SELECT
попасть во временную таблицу. Это поможет MySQL освободить блокировку таблицы
пораньше и поможет в случаях, где требуется длительное время, чтобы послать
набор результатов пользователю.
SQL_LOW_PRIORITY_UPDATES=0|1
1
, все инструкции INSERT
,
UPDATE
, DELETE
и LOCK TABLE WRITE
ждут до тех пор, пока не останется ни одного ждущего обработки запроса
SELECT
или LOCK TABLE READ
на данной таблице.
SQL_MAX_JOIN_SIZE=value|DEFAULT
SELECT
, которые, вероятно, будут должны
исследовать больше, чем value
комбинаций строк. Устанавливая это
значение, Вы можете захватывать SELECT
, где ключи не
используются правильно. Установка этого к иному значению, чем
DEFAULT
сбросит флажок SQL_BIG_SELECTS
. Если Вы
снова устанавливаете флажок SQL_BIG_SELECTS
, переменная
SQL_MAX_JOIN_SIZE
будет игнорироваться. Вы можете устанавливать
значение по умолчанию для этой переменной, запуская mysqld
с
опцией -O max_join_size=#
.
SQL_SAFE_UPDATES=0|1
1
, MySQL прервется, если
UPDATE
или DELETE
не использует ключ или
LIMIT
в предложении WHERE
. Это делает возможным
захватить неправильные модификации при создании SQL-команды вручную.
SQL_SELECT_LIMIT=value|DEFAULT
SELECT
. Если SELECT
имеет предложение
LIMIT
, то LIMIT
имеет приоритет над значением в
SQL_SELECT_LIMIT
. Значение по умолчанию для нового подключения:
``unlimited''. Если Вы изменили ограничение, значение по умолчанию может быть
восстановлено, используя значение DEFAULT
.
SQL_LOG_OFF=0|1
1
, никакая регистрация не будет выполнена
в стандартный файл регистрации для этого пользователя, если пользователь
имеет привилегию process. Это не воздействует на
файл регистрации модификаций!
SQL_LOG_UPDATE=0|1
0
, никакая регистрация не будет выполнена
в файл регистрации модификаций для этого пользователя, если пользователь
имеет привилегию process. Это не воздействует на
стандартный файл регистрации!
SQL_QUOTE_SHOW_CREATE=0|1
1
, SHOW CREATE TABLE
цитирует имена столбцов и таблиц. Это включено по умолчанию
для репликации таблиц с нестандартными именами столбцов. Подробности в
разделе "4.10.8
SHOW CREATE TABLE
".
TIMESTAMP=timestamp_value|DEFAULT
timestamp_value
должен быть в формате UNIX
Epoch timestamp, а не MySQL timestamp.
LAST_INSERT_ID=#
LAST_INSERT_ID()
. Это будет сохранено в файле регистрации
модификаций, когда Вы используете LAST_INSERT_ID()
в команде,
которая модифицирует таблицу.
INSERT_ID=#
INSERT
или ALTER TABLE
при вставке значения
AUTO_INCREMENT
. Это главным образом используется вместе с файлом
для регистрации модификаций.hdparm -m 16 -d 1Обратите внимание, что эффективность и надежность при использовании вышеупомянутого зависят от Ваших аппаратных средств, так что я настоятельно советую, чтобы Вы проверили Вашу систему полностью после использования
hdparm
. Пожалуйста, проконсультируйтесь с man-страницей на
hdparm
для получения большего количества информации. Если
hdparm
не используется грамотно, можно прихлопнуть все данные на
диске. Резервируйте все перед экспериментированием.
Вы можете перемещать таблицы и базы данных из каталога баз данных куда хотите и заменять их на символические связи с новыми расположениями. Вы могли бы сделать это для решения проблем с диском, например, переместить базу данных на файловую систему с большим количеством свободного пространства или увеличить быстродействие Вашей системы, распространяя Ваши таблицы на различные диски.
Надо сначала создать каталог на некотором диске, где Вы имеете свободное пространство, и затем создать ссылку туда из каталога баз данных MySQL:
shell> mkdir /dr1/databases/test shell> ln -s /dr1/databases/test mysqld-datadir
MySQL не поддерживает привязку одного каталога к нескольким базам данных.
Замена каталога баз данных символической связью будет работать прекрасной,
пока Вы не сделаете символическую связь между базами данных. Предположим, что
Вы имеете базу данных db1
в каталоге данных MySQL, а затем
делаете ссылку db2
, которая указывает на db1
:
shell> cd /path/to/datadir shell> ln -s db1 db2
Теперь для любой таблицы tbl_a
в db1
также
имеется таблица tbl_a
в db2
. Если один поток
модифицирует db1.tbl_a
, а другой в то же время правит
db2.tbl_a
, они точно передерутся.
Если Вы хотите разрешить такие обращения, Вы должны изменить следующий код в файле исходного текста mysys/mf_format.c:
if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
на
if (1)
В Windows Вы можете использовать внутренние символические связи с
каталогами, компилируя MySQL с опцией -DUSE_SYMDIR
. Это
позволяет Вам размещать различные базы данных на разных дисках.
До MySQL 4.0 не стоило пользоваться ссылками без их тщательнейшего
контроля. Проблема состоит в том, что, если Вы выполняете ALTER
TABLE
, REPAIR TABLE
или OPTIMIZE TABLE
на
таблице со связью, ссылка будет удалена и заменена первоначальными файлами.
Это случается потому, что вышеупомянутая команда работает, создавая временный
файл в каталоге баз данных, а когда команда завершится, первоначальный файл
она заменит на временный файл.
Вы не должны связывать таблицы на системе, которая не имеет полностью
рабочее обращение realpath()
. По крайней мере Linux и Solaris
точно поддерживают realpath()
.
В MySQL 4.0 ссылки полностью поддержаны только для таблиц
MyISAM
. Для других типов таблиц Вы, вероятно, получите странные
проблемы при выполнении любой из вышеупомянутых команд.
Обработка символических связей в MySQL 4.0 работает следующим образом:
mysqld
не запущен) или с помощью команды INDEX/DATA
DIRECTORY="path-to-dir"
в CREATE TABLE
. Подробности в
разделе "7.3 Синтаксис CREATE TABLE
".
myisamchk
теперь уже не будет заменять ссылки на реальные
файлы, а работает непосредственно на нужных файлах. Любые временные файлы
будут созданы в том же самом каталоге, где лежит файл данных или индекса.
mysqld
как root, и не позволять кому попало иметь доступ для
записи к каталогам баз данных MySQL.
ALTER TABLE RENAME
и
не измените базу данных, ссылка в каталоге базы данных будет переименована,
как и файл данных/индекса.
ALTER TABLE RENAME
, чтобы переместить
таблицу в другую базу данных, то таблица будет перемещаться в другой каталог
баз данных, а старая ссылка и файл, на который она указывала, удалятся.
--skip-symlink
при запуске mysqld
, чтобы
гарантировать, что никто не может удалять или переименовывать файл вне
каталога данных MySQL.Свойства, которые еще не поддержаны:
ALTER TABLE
игнорирует все опции
INDEX/DATA DIRECTORY="path"
.
CREATE TABLE
не сообщает, имеет ли таблица ссылки.
mysqldump
не включает информацию ссылок в вывод.
BACKUP TABLE
и RESTORE TABLE
не
обрабатывают ссылки вообще.Число страниц (страница равна 2000 символов) | Краткое описание главы |
5 | Введение. Основные термины и соглашения, использованные в книге. Также обсуждает хронологию. |
7 | Глава 1 Описание стандартов, принятых в MySQL. |
35 | Глава 2 дает краткое введение в MySQL. |
8 | Глава 3 имеет дело со структурой языка. |
30 | Глава 4 рассматривает введение в администрирование. |
25 | Глава 5 подробно рассматривает типы столбцов. |
34 | Глава 6 рассматривает функции
для использования в самых главных операторах языка: SELECT и
WHERE |
18 | Глава 7 описывает определение
данных: вызовы CREATE , DROP и ALTER .
|
25 | Глава 8 объясняет манипуляции с
данными: команды SELECT , INSERT ,
UPDATE и DELETE . |
11 | Глава 9 охватывает обзор прочих инструментов языка MySQL. |
33 | Глава 10 обсуждает общие проблемы защиты и систему привилегий доступа в MySQL. |
27 | Глава 11 объясняет проблемы и общие ошибки. |
19 | Глава 12 описывает клиентские скрипты и утилиты MySQL. |
11 | Глава 13 охватывает поддержку MySQL ODBC. |
75 | Глава 14 рассказывает об оптимизации запросов. |
5 | Заключение. Ссылки на источники дополнительной информации по СУБД MySQL. |
1 | Приложение 1. Здесь описан комплектный CD-ROM. |
1 | Приложение 2. Переменные окружения. |
1 | Приложение 3. Выяснение вопросов или сообщение об ошибках в пакете |
Приложение 4. GNU GENERAL PUBLIC LICENSE. | |
Приложение 5. GNU LESSER GENERAL PUBLIC LICENSE. |
Всего: 370 страниц в формате А4.
За последнее время MySQL сильно продвинулась вперед. Уже сейчас эта СУБД стала фактическим стандартом для интернет-приложений (веб-магазины, сложные сайты, информационные порталы). Под открытыми системами (Linux, FreeBSD) и даже под закрытыми, где нет продукции Microsoft (Sun Solaris, разные коммерческие версии Unix), эта СУБД лидирует уже сейчас. Да оно и понятно: она обладает очень высоким быстродействием и надежностью (по некоторым параметрам поспорит даже с монстром от Oracle!).
Сейчас в крупных организациях все больше разворачивается война с пиратскими копиями программ. По крайней мере с практикой создания базы данных масштаба предприятия на основе ворованной СУБД явно стараются покончить. MySQL бесплатна (правда, за поддержку надо платить, но ведь поддержка не всем нужна), что еще больше повышает к ней интерес. К тому же, открытые системы ведут сейчас наступление широким фронтом, никуда тут не денешься, а под ними эта СУБД является безусловным лидером, оставив далеко позади все проекты свободных СУБД. Какой смысл покупать и ставить MS SQL под эмулятором в Linux, когда там уже есть СУБД, ничуть не уступающая MS SQL? Следует также отметить бурный рост числа баз данных масштаба предприятия, который уже начался.
Тут и возникает серьезная проблема: в России с литературой по открытым системам дело обстоит из рук вон плохо. То есть, хуже некуда. Представим такую ситуацию: на предприятии успешно идет внедрение корпоративной БД под MySQL (возможности этой СУБД легко позволяют управиться с потребностями довольно крупной компании, проверено лично). Есть много далеких от компьютерной техники людей (но все же не чайников), которые более-менее разбираются во всяких MS Windows и MS Office, но им теперь придется работать с клиентской частью MySQL (кстати, MySQL есть чуть ли не под любой ОС). Понятно, что необходимы знания о том, как это делается, особенно если учесть, что диалект языка SQL, реализованный в MySQL, имеет немало отличий от версии ANSI SQL93. Что делать администратору, на которого в ближайшее время обрушится шквал вопросов?
Вообще документация по MySQL на рынке есть, но направлена она несколько не в ту сторону, куда надо бы. Есть огромные тома (свыше 800 страниц), которые пытаются в одной книге описать все аспекты СУБД, что все равно невозможно сделать качественно ввиду огромных объемов информации. Есть компактные книжки, ориентированные на программистов, но нет почти ничего для администраторов и уже совсем ничего для пользователей. Именно по этой причине и возникла в свое время надобность написать книжку для пользователя. Почему-то молча считается, что эта СУБД нужна даже не администраторам, а программистам. Это далеко не так! Но это убеждение сильно мешает нормальной работе с этой системой.
По меньшей мере странным выглядит то, что никто до сих пор не подумал о том, что литература по MySQL нужна и тем, кто с этой СУБД будет работать на уровне пользователя. Сложно поверить в то, что здесь все считается интуитивно понятным. Все же это очень сложный пакет, даже на пользовательском уровне нельзя просто взять и начать с ним работать, надо учиться. Почему-то принято считать, что всякий, кто работает с MySQL, является администратором системы, ему нужны подробные сведения по настройкам пакета, и ему совсем не к чему описывать простые понятия, вроде языка этого пакета. Такое мнение глубоко ошибочно! Язык у этого пакета изобилует всякими скрытыми возможностями, хитростями и неожиданностями. Далеко не всем нужно и администрироваине.
Не следует также забывать о том, что пользователю могут быть поручены ограниченные функции администратора (например, координатору рабочей группы может быть предоставлено право управлять базами данных своей группы). MySQL имеет отличную систему привилегий и прав доступа, что делает эту СУБД поистине универсальным инструментом подобного рода. В этой книге я рассматриваю введение в администрирование пакета, предназначенное для пользователей с ограниченными администраторскими функциями.
Нельзя не учесть и то, что любая база данных работает значительно лучше при оптимальной обработке запросов. Разумеется, чтобы запрос обрабатывался оптимально, он должен быть правильно составлен. В этой книге я даю специальную главу по оптимизации запросов на уровне пользователя (без вмешательства администратора), что позволяет повысить эффективность работы пакета примерно в 3-5 раз.
Предполагаемый круг читателей: различные пользователи (но не чайники!): клерки, секретари и операторы, использующие в своей работе клиентскую часть данной СУБД, и нуждающиеся в руководстве по практическому (без лишних теорий) использованию пакета. Книга расчитана на подготовленных читателей, имеющих общее представление о базах данных. Книга не ориентирована на администраторов, им адресована следующая книга серии: MYSQL: руководство администратора.
Знание языка запросов SQL необязательно, поскольку в MySQL применен весьма специфический его диалект, который подробно рассмотрен в книге. Именно это описание языка SQL (а также главы по оптимизации запросов и администрированию пакета) может также пригодиться студентам, изучающим предмет "Базы данных" и программистам, которым приходится писать приложения для взаимодействия с данной СУБД. Книга представляет практическую ценность для очень широкого круга читателей, особенно для тех, кто стремится сам повысить свой профессиональный уровень.
В этой книге рассмотрены следующие вопросы:
Безусловно, многого в этой книге нет. В частности, она не охватывает проблемы компиляции и установки пакета на конкретную систему, его отладку, особенности различных типов таблиц, локализацию под разные языки, протоколирование событий, репликацию и многое другое. Но все это уже выходит за рамки пользовательского уровня работы с клиентской частью СУБД. Если интерес к этой работе будет достаточно сильным, автор рассмотрит возможность написания продолжения данной книги, но уже ориентируясь на администратора, где и рассмотрит перечисленные проблемы.
Это справочное описание, оно не обеспечивает основные инструкции по SQL или концепциям баз данных. Если Вы хотите получить общую информацию относительно SQL, обратитесь к заключению, там есть ссылки по этим вопросам.
В заключение хочу поблагодарить всех, кто помогал мне в работе над книгой, а особенно:
Это приложение вносит в список некоторых пользователей MySQL, которые дали разрешение внести их в список в документации. Это далеко не полный список, но он должен дать Вам общее представление относительно того, кто использует MySQL, и для чего этот пакет может использоваться. Этот раздел должен дать Вам идею относительно того, как другие MySQL пользователи применяют MySQL, чтобы решить свои проблемы. Кроме того, он должен дать Вам общее представление относительно того, кто использует MySQL, и для чего это может применяться.
Если Вы используете MySQL в уникальной среде или имеете память об успехе
относительно того, как Вы применяли MySQL, Вы можете написать на
docs@mysql.com
с темой Success:
.
Если Вам понравилась эта работа, напишите: считаете ли Вы ее качественной или нет? Стоит ли издавать? Хорошо ли изложен материал?
PHP
и MySQL
Посылайте обновления на webmaster@mysql.com.
SELECT
и WHERE
select_expression
или where_definition
в
инструкции SQL может состоять из любого выражения, использующего
функции, описанные ниже.
Выражение, которое содержит NULL
всегда, производит значение
NULL
, если иное не обозначено в документации для операторов и
функций, включаемых в выражении.
ОБРАТИТЕ ВНИМАНИЕ: не должно быть никаких пробелов между именем функции и круглой скобкой после него. Это помогает синтаксическому анализатору MySQL различать обращения к функции и ссылки к таблицам или столбцам, которые, случается, имеют то же самое имя, что и функция. Пробелы вокруг параметров разрешаются.
Вы можете заставить MySQL принимать пробелы после имени функции, запуская
mysqld
с опцией --ansi
или используя параметр
CLIENT_IGNORE_SPACE
в mysql_connect()
, но в этом
случае все имена функции станут зарезервированными словами. Подробности в
разделе "1.4.3 Запуск 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
( ... )
Используйте круглую скобку, чтобы принудительно задать порядок оценки в вычисляемом выражении. Например:
mysql> select 1+2*3; -> 7 mysql> select (1+2)*3; -> 9
Операторы сравнения возвращают значения 1
(TRUE),
0
(FALSE) или NULL
. Эти функции работают для чисел
и строк. Строки автоматически будут преобразованы в числа, а числа в строки,
как необходимо (как в языке Perl).
MySQL выполняет все сравнения, использующие следующие правила:
NULL
, результат
сравнения также равен NULL
, кроме операторов
<=>
.
TIMESTAMP
или
DATETIME
, а другой параметр является константой, то она будет
преобразована в timestamp прежде, чем сравнение выполняется. Это выполнено,
чтобы быть более дружественным к ODBC.
По умолчанию, сравнения строк выполнены независимо от регистра, используя текущий набор символов (по умолчанию это ISO-8859-1 Latin1, который работает превосходно для английского языка).
Примеры ниже иллюстрируют преобразование строк в соответствующие числа для выполнения операций сравнения:
mysql> SELECT 1 > '6x'; -> 0 mysql> SELECT 7 > '6x'; -> 1 mysql> SELECT 0 > 'x6'; -> 0 mysql> SELECT 0 = 'x6'; -> 1
=
mysql> select 1 = 0; -> 0 mysql> select '0' = 0; -> 1 mysql> select '0.0' = 0; -> 1 mysql> select '0.01' = 0; -> 0 mysql> select '.01' = 0.01; -> 1
<>
!=
mysql> select '.01' <> '0.01'; -> 1 mysql> select .01 <> '0.01'; -> 0 mysql> select 'zapp' <> 'zappp'; -> 1
<=
mysql> select 0.1 <= 2; -> 1
<
mysql> select 2 < 2; -> 0
>=
mysql> select 2 >= 2; -> 1
>
mysql> select 2 > 2; -> 0
<=>
mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1 1 0
IS NULL
IS NOT NULL
NULL
:
mysql> select 1 IS NULL, 0 IS NULL, NULL IS NULL; -> 0 0 1 mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL; -> 1 1 0
expr BETWEEN min AND max
expr
больше или равно min
, и
expr
меньше или равно max
, то BETWEEN
вернет 1
, иначе это возвращает 0
. Это эквивалентно
выражению (min <= expr AND expr <= max)
, если все
параметры имеют тот же самый тип. Первый параметр (expr
)
определяет, как выполняется сравнение следующим образом:
expr
представляет собой столбец типа
TIMESTAMP
, DATE
или DATETIME
, то
MIN()
и MAX()
приводятся к тому же самому формату,
если они константы.
expr
представляет собой строку, нечувствительную к
регистру, то сравнение выполняется без учета регистра.
expr
представляет собой строку, чувствительную к
регистру, то сравнение выполняется с учетом регистра символов.
expr
представляет собой целочисленное выражение, будет
выполнено целочисленное сравнение.
mysql> select 1 BETWEEN 2 AND 3; -> 0 mysql> select 'b' BETWEEN 'a' AND 'c'; -> 1 mysql> select 2 BETWEEN 2 AND '3'; -> 1 mysql> select 2 BETWEEN 2 AND 'x-3'; -> 0
expr IN (value,...)
1
, если expr
представляет собой
любое из значений в списке IN
, иначе возвращается
0
. Если все значения константы, то все значения оценены согласно
типу expr
и отсортированы. Поиск элемента затем будет выполнен,
используя двоичный поиск. Это означает, что IN
очень быстр, если
список значений IN
состоит полностью из констант. Если
expr
чувствительное к регистру строковое выражение, сравнение
строк выполняется с учетом регистра:
mysql> select 2 IN (0,3,5,'wefwf'); -> 0 mysql> select 'wefwf' IN (0,3,5,'wefwf'); -> 1
expr NOT IN (value,...)
NOT (expr IN (value,...))
.
ISNULL(expr)
expr
равен NULL
, ISNULL()
возвращает 1
, иначе это возвращает 0
:
mysql> select ISNULL(1+1); -> 0 mysql> select ISNULL(1/0); -> 1Обратите внимание, что сравнение значений
NULL
, использующих
=
всегда будет равно false!
COALESCE(list)
NULL
элемент в списке:
mysql> select COALESCE(NULL,1); -> 1 mysql> select COALESCE(NULL,NULL,NULL); -> NULL
INTERVAL(N,N1,N2,N3,...)
0
, если N
< N1
,
1
, если N
< N2
и так далее. Все
параметры обрабатываются как целые числа. Это требует, чтобы выполнялось
N1
< N2
< N3
<
...
< Nn
для этой функции, чтобы она могла
работать правильно. Это потому, что при работе функции используется двоичный
поиск (очень быстрый):
mysql> select INTERVAL(23, 1, 15, 17, 30, 44, 200); -> 3 mysql> select INTERVAL(10, 1, 10, 100, 1000); -> 2 mysql> select INTERVAL(22, 23, 30, 44, 200); -> 0
Если Вы сравниваете чувствительную к регистру строку любым из стандартных
операторов (=
, <>
..., но не
LIKE
), конечный пробел будет игнорироваться.
mysql> select "a" ="A "; -> 1
Все логические функции возвращают 1
(TRUE), 0
(FALSE) или NULL
(неизвестное, которое находится в большинстве
случаев также, как FALSE):
NOT
!
1
, если параметр 0
,
иначе возвращает 0
. Исключительная ситуация: NOT
NULL
возвращает NULL
:
mysql> select NOT 1; -> 0 mysql> select NOT NULL; -> NULL mysql> select ! (1+1); -> 0 mysql> select ! 1+1; -> 1Последний пример возвращает
1
потому, что выражение оценивается
так же, как (!1)+1
.
OR
||
1
, если любой параметр не
0
и не NULL
:
mysql> select 1 || 0; -> 1 mysql> select 0 || 0; -> 0 mysql> select 1 || NULL; -> 1
AND
&&
0
, если параметр 0
или NULL
, иначе возвращается 1
:
mysql> select 1 && NULL; -> 0 mysql> select 1 && 0; -> 0
IFNULL(expr1,expr2)
expr1
не NULL
, IFNULL()
вернет expr1
, иначе expr2
. IFNULL()
возвращает числовое или строковое значение в зависимости от контекста, в
котором это используется:
mysql> select IFNULL(1,0); -> 1 mysql> select IFNULL(NULL,10); -> 10 mysql> select IFNULL(1/0,10); -> 10 mysql> select IFNULL(1/0,'yes'); -> 'yes'
NULLIF(expr1,expr2)
expr1=expr2
, вернет NULL
, иначе возвращает
expr1
. Это работает также, как CASE WHEN x=y THEN
NULL ELSE x END
:
mysql> select NULLIF(1,1); -> NULL mysql> select NULLIF(1,2); -> 1Обратите внимание, что
expr1
будет оценен дважды в MySQL,
если параметры равны.
IF(expr1,expr2,expr3)
expr1
равно TRUE (expr1 <> 0
и
expr1 <> NULL
), то IF()
вернет
expr2
, иначе вернет expr3
. IF()
возвращает числовое или строковое значение в зависимости от контекста, в
котором это используется:
mysql> select IF(1>2,2,3); -> 3 mysql> select IF(1<2,'yes','no'); -> 'yes' mysql> select IF(strcmp('test','test1'),'no','yes'); -> 'no'
expr1
будет оценен как целочисленное значение, это означает,
что, если Вы проверяете выражение с плавающей запятой или строку, Вы должны
сделать следующее для корректного использования операции сравнения:
mysql> select IF(0.1,1,0); -> 0 mysql> select IF(0.1<>0,1,0); -> 1В первом случае выше
IF(0.1)
вернет 0
потому, что
0.1
преобразован в целочисленное значение, возникающее в
результате в IF(0)
. Это не может быть тем, что Вы ожидаете. Во
втором случае сравнение проверяет первоначальное значение с плавающей
запятой, чтобы видеть,является ли это отличным от нуля. Результат сравнения
используется как целое число. Заданный по умолчанию тип возврата
IF()
(который может иметь значение, когда это значение будет
сохранено во временной таблице) вычислен в MySQL 3.23 следующим образом:
Выражение | Возвращаемое значение |
expr2 или expr3 возвращает строку | Строка |
expr2 или expr3 возвращает значение с плавающей запятой | Число с плавающей запятой |
expr2 или expr3 возвращает целое число | Целое число |
CASE value WHEN [compare-value] THEN result
[WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition]
THEN result ...] [ELSE result] END
result
, где
value=compare-value
. Вторая версия возвращает результат для
первого условия, которое является истинным. Если не имелось никакого значения
результата соответствия, то будет возвращен результат после
ELSE
. Если не имеется части ELSE
, вернется
NULL
:
mysql> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END; -> "one" mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END; -> "true" mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END; -> NULL
Тип значения возврата (INTEGER
, DOUBLE
или
STRING
) такое же, как и тип первого возвращенного значения
(выражение после первого THEN
).
Строковые функции возвращают NULL
, если длина результата
большая, чем параметр сервера max_allowed_packet
.
Для функций, которые оперируют позициями в строке, первая позиция всегда пронумерована как 1, а не 0.
ASCII(str)
str
. Вернет
0
, если str
пустая. Вернет NULL
, если
str
равна NULL
:
mysql> select ASCII('2'); -> 50 mysql> select ASCII(2); -> 50 mysql> select ASCII('dx'); -> 100См. также описание функции
ORD()
.
ORD(str)
((первый байт ASCII-кода)*256+(второй байт ASCII-кода))[*256+
третий байт ASCII-кода...]
. Если крайний левый символ не является
многобайтным, действует аналогично функции ASCII()
:
mysql> select ORD('2'); -> 50
CONV(N,from_base,to_base)
N
, преобразованного из
from_base
в to_base
. Вернет NULL
, если
любой параметр равен NULL
. Параметр N
интерпретируется как целое число, но может быть определен как целое число или
строка. Минимальная система счисления 2
, максимальная
36
. Если to_base
отрицательное значение,
N
расценено как число со знаком. Иначе, N
обрабатывается как число без знака. Вызов CONV
всегда работает с
64-разрядной точностью:
mysql> select CONV("a",16,2); -> '1010' mysql> select CONV("6E",18,8); -> '172' mysql> select CONV(-17,10,-18); -> '-H' mysql> select CONV(10+"10"+'10'+0xa,10,10); -> '40'
BIN(N)
N
, где
N
представляет собой число типа longlong (BIGINT
).
Это эквивалентно CONV(N,10,2)
. Возвращает NULL
,
если N
равно NULL
:
mysql> select BIN(12); -> '1100'
OCT(N)
N
,
где N
представляет собой число типа longlong. Это эквивалентно
CONV(N,10,8)
. Возвращает NULL
,
если N
равно NULL
:
mysql> select OCT(12); -> '14'
HEX(N)
N
, где N
представляет собой число типа longlong.
Это эквивалентно CONV(N,10,16)
. Возвращает NULL
,
если N
равно NULL
:
mysql> select HEX(255); -> 'FF'
CHAR(N,...)
CHAR()
интерпретируют параметры как целые числа и возвращает
строку состоящую из символов, заданных значениями ASCII-кодов из тех целых
чисел. Значения NULL
будут пропущены:
mysql> select CHAR(77,121,83,81,'76'); -> 'MySQL' mysql> select CHAR(77,77.3,'77.3'); -> 'MMM'
CONCAT(str1,str2,...)
NULL
, если любой параметр NULL
. Может иметь больше,
чем 2 параметра. Числовой параметр будет автоматически преобразован в
эквивалентную строковую форму:
mysql> select CONCAT('My', 'S', 'QL'); -> 'MySQL' mysql> select CONCAT('My', NULL, 'QL'); -> NULL mysql> select CONCAT(14.3); -> '14.3'
CONCAT_WS(separator, str1, str2,...)
CONCAT_WS()
расшифровывается как CONCAT With Separator и
представляет собой специальную форму функции CONCAT()
. Первый
параметр задает разделитель для остальной части параметров. Разделитель может
быть строкой так же, как и остальная часть параметров. Если разделитель равен
NULL
, результат превратится в NULL
. Разделитель
будет добавлен между строками, которые нужно объединить в одну целую:
mysql> select CONCAT_WS(",","First name","Second name","Last Name"); -> 'First name,Second name,Last Name' mysql> select CONCAT_WS(",","First name",NULL,"Last Name"); -> 'First name,Last Name'
LENGTH(str)
OCTET_LENGTH(str)
CHAR_LENGTH(str)
CHARACTER_LENGTH(str)
str
:
mysql> select LENGTH('text'); -> 4 mysql> select OCTET_LENGTH('text'); -> 4Обратите внимание, что для
CHAR_LENGTH()
любой многобайтный
символ считается одним.
LOCATE(substr,str)
POSITION(substr IN str)
substr
в строке str
. Если не нашла substr
в
str
, вернет 0
:
mysql> select LOCATE('bar', 'foobarbar'); -> 4 mysql> select LOCATE('xbar', 'foobar'); -> 0Поддерживаются многобайтные символы.
LOCATE(substr,str,pos)
substr
в строке str
, после позиции pos
. Если не нашла
substr
в str
, вернет 0
:
mysql> select LOCATE('bar', 'foobarbar',5); -> 7Поддерживаются многобайтные символы.
INSTR(str,substr)
LOCATE()
, но с переставленными параметрами:
mysql> select INSTR('foobarbar', 'bar'); -> 4 mysql> select INSTR('xbar', 'foobar'); -> 0Поддерживаются многобайтные символы.
LPAD(str,len,padstr)
str
, дополненную слева строкой
padstr
. Максимальная длина str
равна
len
символам. Если str
длиннее, чем
len
, она будет урезана до len
символов. Если
str
короче, чем len
символов, padstr
будет приписана несколько раз.
mysql> select LPAD('hi',4,'??'); -> '??hi'
RPAD(str,len,padstr)
LPAD(str,len,padstr)
, но строка
padstr
приписывается справа.
mysql> select RPAD('hi',5,'?'); -> 'hi???'
LEFT(str,len)
len
крайних левых символов из строки
str
:
mysql> select LEFT('foobarbar', 5); -> 'fooba'Поддерживаются многобайтные символы.
RIGHT(str,len)
len
крайних правых символов из строки
str
:
mysql> select RIGHT('foobarbar', 4); -> 'rbar'Поддерживаются многобайтные символы.
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
MID(str,pos,len)
len
символов из строки
str
, начиная с позиции pos
. Иная форма, которая
использует синтаксис FROM
из ANSI SQL92:
mysql> select SUBSTRING('Quadratically',5,6); -> 'ratica'Поддерживаются многобайтные символы.
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
str
. начиная с позиции
pos
:
mysql> select SUBSTRING('Quadratically',5); -> 'ratically' mysql> select SUBSTRING('foobarbar' FROM 4); -> 'barbar'Поддерживаются многобайтные символы.
SUBSTRING_INDEX(str,delim,count)
str
, отступив
count
символов от разделителя delim
. Если
count
положителен, вернется все левее разделителя. Если
count
отрицателен, вернется все правее заданного разделителя:
mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2); -> 'www.mysql' mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2); -> 'mysql.com'Поддерживаются многобайтные символы.
LTRIM(str)
str
с удаленными ведущими пробелами:
mysql> select LTRIM(' barbar'); -> 'barbar'
RTRIM(str)
str
с удаленными конечными пробелами:
mysql> select RTRIM('barbar '); -> 'barbar'Поддерживаются многобайтные символы.
TRIM([[BOTH|LEADING|TRAILING] [remstr] FROM] str)
str
, из которой удалены все префиксы и
суффиксы remstr
. Если ни один из спецификаторов
BOTH
, LEADING
или TRAILING
не задан,
принимается BOTH
. Если не задан параметр remstr
,
будут удалены пробелы:
mysql> select TRIM(' bar '); -> 'bar' mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx'); -> 'barxxx' mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx'); -> 'bar' mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz'); -> 'barx'Поддерживаются многобайтные символы.
SOUNDEX(str)
str
. Две строки, которые
звучат почти одинаково, должны иметь идентичные soundex-строки. Стандартная
soundex-строка длиной 4 символа, но функция SOUNDEX()
возвращает
произвольно длинную строку. Вы можете использовать SUBSTRING()
на результате, чтобы получить стандартную soundex-строку. Все не
алфавитно-цифровые символы игнорируются в данной строке. Все международные
алфавитные символы вне диапазона A-Z обрабатываются как гласные:
mysql> select SOUNDEX('Hello'); -> 'H400' mysql> select SOUNDEX('Quadratically'); -> 'Q36324'
SPACE(N)
N
пробелов:
mysql> select SPACE(6); -> ' '
REPLACE(str,from_str,to_str)
str
, где все вхождения подстроки
from_str
заменены на подстроку to_str
:
mysql> select REPLACE('www.mysql.com', 'w', 'Ww'); -> 'WwWwWw.mysql.com'Поддерживаются многобайтные символы.
REPEAT(str,count)
str
повторенной count
раз. Если count <=0
,
возвращает пустую строку. Если str
или count
равны
NULL
, вернет NULL
:
mysql> select REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL'
REVERSE(str)
str
с обращенным порядком символов:
mysql> select REVERSE('abc'); -> 'cba'Поддерживаются многобайтные символы.
INSERT(str,pos,len,newstr)
str
с подстрокой, начинающейся в позиции
pos
и длиной в len
символов, замененной на строку
newstr
:
mysql> select INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic'Поддерживаются многобайтные символы.
ELT(N,str1,str2,str3,...)
str1
, если N
=1
,
str2
, если N
=2
и так далее. Возвращает
NULL
, если N
меньше, чем 1
, или
больше, чем число параметров. ELT()
дополняет функцию
FIELD()
:
mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo'); -> 'ej' mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo'); -> 'foo'
FIELD(str,str1,str2,str3,...)
str
в списке str1
,
str2
, str3
, ...
. Вернет
0
, если str
не найдена. FIELD()
дополняет функцию ELT()
:
mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 2 mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 0
FIND_IN_SET(str,strlist)
1
до N
, если строка
str
находится в списке strlist
, состоящем из
N
подстрок. Список строк представляет собой строку, составленную
из подстрок, отделяемых символом запятой (,). Если первый
параметр постоянная строка, а второй столбец типа SET
, то
функция FIND_IN_SET()
оптимизирована, чтобы использовать
разрядную арифметику. Возвращается 0
, если str
не в
strlist
или strlist
является пустой строкой.
Возвращает NULL
, если любой параметр NULL
. Эта
функция не будет работать правильно, если первый параметр содержит запятую:
mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2
MAKE_SET(bits,str1,str2,...)
bits
. str1
соответствует биту 0,
str2
биту 1 и так далее. NULL
в str1
,
str2
, ...
не попадут в результат:
mysql> SELECT MAKE_SET(1,'a','b','c'); -> 'a' mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world'); -> 'hello,world' mysql> SELECT MAKE_SET(0,'a','b','c'); -> ''
EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
mysql> select EXPORT_SET(5,'Y','N',',',4) -> Y,N,Y,N
LCASE(str)
LOWER(str)
str
со всеми символами, измененными на
нижний регистр согласно текущему отображению набора символов (значение по
умолчанию: ISO-8859-1 Latin1):
mysql> select LCASE('QUADRATICALLY'); -> 'quadratically'Поддерживаются многобайтные символы.
UCASE(str)
UPPER(str)
str
со всеми символами, измененными на
верхний регистр согласно текущему отображению набора символов (значение по
умолчанию: ISO-8859-1 Latin1):
mysql> select UCASE('Hej'); -> 'HEJ'Поддерживаются многобайтные символы.
LOAD_FILE(file_name)
max_allowed_packet
. Если файл не существует или не может
читаться из-за одной из вышеупомянутых причин, функция возвратит
NULL
:
mysql> UPDATE table_name SET blob_column=LOAD_FILE("/tmp/picture") WHERE id=1;
Если Вы не используете MySQL Version 3.23, Вы должны делать чтение файла
внутри Вашей прикладной программы и создавать инструкцию INSERT
,
чтобы модифицировать базу данных с информацией из файла. Один способ сделать
это, если Вы используете библиотеку MySQL++, есть на страничке
http://www.mysql.com/documentation/mysql++/mysql++-examples.html.
MySQL по мере необходимости автоматически преобразует числа в строки и наоборот (как в Perl):
mysql> SELECT 1+"1"; -> 2 mysql> SELECT CONCAT(2,' test'); -> '2 test'
Если Вы хотите преобразовывать число в строку явно, передайте его как
параметр функции CONCAT()
.
Если строковая функция получает двоичную строку как параметр, возникающая в результате строка также будет двоичной. Числа, преобразованные в строку, также обрабатываются как двоичные строки. Это важно только для сравнений.
Обычно, если любое выражение при сравнении строк чувствительно к регистру, сравнение выполняется в режиме чувствительности к регистру символов.
expr LIKE pat [ESCAPE 'escape-char']
1
(TRUE) или 0
(FALSE). С LIKE
Вы можете использовать следующие два групповых
символа в задаваемом образце:
% | Соответствует любому числу символов. |
_ | Соответствует строго одному символу. |
mysql> select 'David!' LIKE 'David_'; -> 1 mysql> select 'David!' LIKE '%D%v%'; -> 1Чтобы проверять для литеральных образцов группового символа, экранируйте его символом escape. Если Вы не определяете символ
ESCAPE
, будет
принято значение \:
\% | Соответствует одному символу % .
|
\_ | Соответствует одному символу _ .
|
mysql> select 'David!' LIKE 'David\_'; -> 0 mysql> select 'David_' LIKE 'David\_'; -> 1Чтобы определять иной символ escape, используйте предложение
ESCAPE
:
mysql> select 'David_' LIKE 'David|_' ESCAPE '|'; -> 1Следующие две инструкции иллюстрируют сравнения нечувствительных к регистру строк, если один из операндов не двоичная строка:
mysql> select 'abc' LIKE 'ABC'; -> 1 mysql> SELECT 'abc' LIKE BINARY 'ABC'; -> 0
LIKE
позволяется на числовых выражениях! Это MySQL-расширение
ANSI SQL LIKE
.
mysql> select 10 LIKE '1%'; -> 1Обратите внимание: поскольку MySQL использует C-escape синтаксис в строках (например, \n), Вы должны удвоить любой символ \, который Вы используете в Вашем выражении
LIKE
. Например, чтобы
искать \n, определите это как \\n. Чтобы искать
\, определите это как \\\\ (наклонные черты влево
будут удалены синтаксическим анализатором и повторно, когда соответствие
образца выполнено, оставляя одиночную наклонную черту влево, которая будет
согласована в данном выражении).
expr NOT LIKE pat [ESCAPE 'escape-char']
NOT (expr LIKE pat
[ESCAPE 'escape-char'])
.
expr REGEXP pat
expr RLIKE pat
expr
для
образца pat
. Образец может быть расширенным регулярным
выражением. Подробности в разделе "6.7 Описание
синтаксиса регулярных выражений MySQL". Возвращает 1
, если
expr
соответствует pat
, иначе вернется
0
. RLIKE
представляет собой синоним для
REGEXP
, предусмотренный для совместимости с mSQL
.
Обратите внимание: поскольку MySQL использует C-escape синтаксис в строках
(например, \n), Вы должны удвоить любой символ \,
который Вы используете в Вашем выражении REGEXP
. Например, чтобы
искать \n, определите это как \\n. Начиная с MySQL
Version 3.23.4, REGEXP
нечувствителен к регистру для нормальных
(не двоичных) строк:
mysql> select 'Monty!' REGEXP 'm%y%%'; -> 0 mysql> select 'Monty!' REGEXP '.*'; -> 1 mysql> select 'new*\n*line' REGEXP 'new\\*.\\*line'; -> 1 mysql> select "a" REGEXP "A", "a" REGEXP BINARY "A"; -> 1 0 mysql> select "a" REGEXP "^[a-d]"; -> 1
REGEXP
и RLIKE
используют текущий набор
символов (по умолчанию задан ISO-8859-1 Latin1).
expr NOT REGEXP pat
expr NOT RLIKE pat
NOT (expr REGEXP pat)
.
STRCMP(expr1,expr2)
STRCMP()
возвращает 0
, если строки одинаковые,
-1
, если первый параметр меньше, чем второй согласно текущему
порядку сортировки, или 1
в противном случае:
mysql> select STRCMP('text', 'text2'); -> -1 mysql> select STRCMP('text2', 'text'); -> 1 mysql> select STRCMP('text', 'text'); -> 0
MATCH (col1,col2,...) AGAINST (expr)
MATCH ... AGAINST()
используется для полнотекстового поиска
и возвращает релевантность (она же уместность), меру подобия между текстом в
столбцах (col1,col2,...)
и запросе expr
.
Релевантность представляет собой положительное число с плавающей запятой.
Нулевое значение данной величины означает отсутствие схожести. Для работы
MATCH ... AGAINST()
сначала должен быть создан индекс
FULLTEXT. Подробности в разделе
"7.3 Синтаксис CREATE TABLE
". MATCH ... AGAINST()
доступен в MySQL Version 3.23.23 или
более поздних. Подробности в разделе
"9.4 Полнотекстовый поиск в MySQL".
BINARY
BINARY
приводит строку к
двоичной форме. Это простой способ вынудить сравнение столбца быть
чувствительным к регистру, даже если столбец не определен как
BINARY
или BLOB
:
mysql> select "a" = "A"; -> 1 mysql> select BINARY "a" = "A"; -> 0
BINARY
появился в MySQL Version 3.23.0. Обратите внимание, что в
некотором контексте MySQL не будет способен использовать индекс эффективно,
когда Вы приводите индексированный столбец к BINARY
.Если Вы хотите сравнивать нечувствительные к регистру объекты blob, Вы можете всегда преобразовывать blob в верхний регистр перед сравнением:
SELECT 'A' LIKE UPPER(blob_col) FROM table_name;
Обычные арифметические операторы доступны. Обратите внимание, что в случае
`-', `+' и `*', результат вычислен с
точностью BIGINT
(64-bit), если оба параметра целые числа!
+
mysql> select 3+5; -> 8
-
mysql> select 3-5; -> -2
*
mysql> select 3*5; -> 15 mysql> select 18014398509481984*18014398509481984.0; -> 324518553658426726783156020576256.0 mysql> select 18014398509481984*18014398509481984; -> 0Результат последнего выражения ошибочен потому, что результат целочисленного умножения превышает 64-разрядный диапазон вычислений
BIGINT
.
/
mysql> select 3/5; -> 0.60Деление на ноль вернет
NULL
:
mysql> select 102/(1-1); -> NULLДеление будет вычислено с арифметикой
BIGINT
только, если
выполняется в контексте, где результат преобразован в целое число!Все математические функции возвращают NULL
в случае ошибки.
-
mysql> select - 2; -> -2Обратите внимание, что, если этот оператор используется с
BIGINT
, значение возврата будет типа BIGINT
!
Это означает, что Вы должны избегать использования -
на целых
числах, которые могут иметь значение -2^63
!
ABS(X)
X
:
mysql> select ABS(2); -> 2 mysql> select ABS(-32); -> 32Эта функция безопасна, чтобы использовать со значениями
BIGINT
.
SIGN(X)
-1
, 0
или
1
, в зависимости от того, является ли X
отрицательным, нулевым или положительным:
mysql> select SIGN(-32); -> -1 mysql> select SIGN(0); -> 0 mysql> select SIGN(234); -> 1
MOD(N,M)
%
%
в языке C). Возвращает остаток от
деления N
на M
:
mysql> select MOD(234, 10); -> 4 mysql> select 253 % 7; -> 1 mysql> select MOD(29,9); -> 2Эта функция безопасна, чтобы использовать со значениями
BIGINT
.
FLOOR(X)
X
:
mysql> select FLOOR(1.23); -> 1 mysql> select FLOOR(-1.23); -> -2Обратите внимание, что значение возврата преобразовано в
BIGINT
!
CEILING(X)
X
:
mysql> select CEILING(1.23); -> 2 mysql> select CEILING(-1.23); -> -1Обратите внимание, что значение возврата преобразовано в
BIGINT
!
ROUND(X)
X
, округленный к самому близкому целому:
mysql> select ROUND(-1.23); -> -1 mysql> select ROUND(-1.58); -> -2 mysql> select ROUND(1.58); -> 2Обратите внимание, что поведение
ROUND()
, когда параметр
расположен точно между двумя целыми числами, зависит от реализации библиотеки
C. Некоторые версии всегда округляют к самому близкому четному числу, другие
всегда к самому большому, самому меньшему или вообще возвращают ноль. Если Вы
нуждаетесь в одном виде округления, Вы должны использовать четкую функцию,
подобно TRUNCATE()
или FLOOR()
.
ROUND(X,D)
X
, округленный к числу с D
десятичными цифрами. Если D
равно 0
, результат не
будет иметь никакой десятичной отметки или дробной части:
mysql> select ROUND(1.298, 1); -> 1.3 mysql> select ROUND(1.298, 0); -> 1
EXP(X)
e
(основание натуральных логарифмов),
предварительно возведенное в степень X
:
mysql> select EXP(2); -> 7.389056 mysql> select EXP(-2); -> 0.135335
LOG(X)
X
:
mysql> select LOG(2); -> 0.693147 mysql> select LOG(-2); -> NULLДля других логарифмов пользуйтесь формулой
LOG(X)/LOG(B)
.
LOG10(X)
X
:
mysql> select LOG10(2); -> 0.301030 mysql> select LOG10(100); -> 2.000000 mysql> select LOG10(-100); -> NULL
POW(X,Y)
POWER(X,Y)
X
в степени Y
:
mysql> select POW(2,2); -> 4.000000 mysql> select POW(2,-2); -> 0.250000
SQRT(X)
X
:
mysql> select SQRT(4); -> 2.000000 mysql> select SQRT(20); -> 4.472136
PI()
mysql> select PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116
COS(X)
X
, где X
задан в радианах:
mysql> select COS(PI()); -> -1.000000
SIN(X)
X
, где X
задан в радианах:
mysql> select SIN(PI()); -> 0.000000
TAN(X)
X
, где X
задан в радианах:
mysql> select TAN(PI()+1); -> 1.557408
ACOS(X)
X
, то есть значение, чей косинус равен
X
. Вернет NULL
, если X
не в диапазоне
от -1
до 1
:
mysql> select ACOS(1); -> 0.000000 mysql> select ACOS(1.0001); -> NULL mysql> select ACOS(0); -> 1.570796
ASIN(X)
X
, то есть значение, чей синус равен
X
. Вернет NULL
, если X
не в диапазоне
от -1
до 1
:
mysql> select ASIN(0.2); -> 0.201358 mysql> select ASIN('foo'); -> 0.000000
ATAN(X)
X
, то есть значение, чей тангенс равен
X
:
mysql> select ATAN(2); -> 1.107149 mysql> select ATAN(-2); -> -1.107149
ATAN2(Y,X)
X
и
Y
. Это подобно вычислению тангенса дуги Y/X
, за
исключением того, что знаки обоих параметров используются, чтобы определить
quadrant результата:
mysql> select ATAN(-2,2); -> -0.785398 mysql> select ATAN(PI(),0); -> 1.570796
COT(X)
X
:
mysql> select COT(12); -> -1.57267341 mysql> select COT(0); -> NULL
RAND()
RAND(N)
0
до 1.0
. Если целочисленный параметр
N
определен, он используется как значение инициализации:
mysql> select RAND(); -> 0.5925 mysql> select RAND(20); -> 0.1811 mysql> select RAND(20); -> 0.1811 mysql> select RAND(); -> 0.2079 mysql> select RAND(); -> 0.7888Вы не можете использовать столбец со значением
RAND()
в
предложении ORDER BY
потому, что ORDER BY
вычисляется несколько раз. В MySQL Version 3.23, Вы, однако, это можете:
SELECT * FROM table_name ORDER BY RAND()
Это полезно, чтобы получить произвольную выборку SELECT * FROM
table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000
.
Обратите внимание, что RAND()
в предложенииi WHERE
будет переоценен каждый раз, когда выполняется WHERE
.
LEAST(X,Y,...)
INTEGER
,
или все параметры целые числа, они сравниваются как целые числа.
REAL
, или
все параметры представляют собой числа real, они сравниваются как real.
mysql> select LEAST(2,0); -> 0 mysql> select LEAST(34.0,3.0,5.0,767.0); -> 3.0 mysql> select LEAST("B","A","C"); -> "A"В MySQL до Version 3.22.5 Вы можете использовать
MIN()
вместо
LEAST
.
GREATEST(X,Y,...)
LEAST
:
mysql> select GREATEST(2,0); -> 2 mysql> select GREATEST(34.0,3.0,5.0,767.0); -> 767.0 mysql> select GREATEST("B","A","C"); -> "C"В MySQL до Version 3.22.5 Вы можете использовать
MAX()
вместо
GREATEST
.
DEGREES(X)
X
, преобразованный из радиан в градусы:
mysql> select DEGREES(PI()); -> 180.000000
RADIANS(X)
DEGREES(X)
:
mysql> select RADIANS(90); -> 1.570796
TRUNCATE(X,D)
X
, усеченное до D
десятичных
чисел. Если D
равно 0
, результат не будет
иметь никакой десятичной отметки или дробной части:
mysql> select TRUNCATE(1.223,1); -> 1.2 mysql> select TRUNCATE(1.999,1); -> 1.9 mysql> select TRUNCATE(1.999,0); -> 1Обратите внимание, что, поскольку десятичные числа обычно сохраняются в компьютерах не как точные числа, а как двоичные значения, Вы можете быть введены в заблуждение следующим результатом:
mysql> select TRUNCATE(10.28*100,0); -> 1027Вышеупомянутое случается потому, что число 10.28 фактически будет сохранено как нечто вроде 10.2799999999999999.
Обратитесь к разделу "5.2 Типы Date и Time" для описания диапазона значений, которые имеет каждый тип, и форматов, в которых значения даты и времени могут быть определены.
Имеется пример, который использует функции даты. Запрос ниже выбирает все
записи со значением date_col
в пределах последних 30 дней:
mysql> SELECT something FROM table WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
DAYOFWEEK(date)
date
(1
=воскресенье, 2
=понедельник, ...,
7
=суббота). Эти индексные значения соответствуют стандарту ODBC:
mysql> select DAYOFWEEK('1998-02-03'); -> 3
WEEKDAY(date)
date
(0
=понедельник, 1
=вторник, ...,
6
=воскресенье):
mysql> select WEEKDAY('1997-10-04 22:23:00'); -> 5 mysql> select WEEKDAY('1997-11-05'); -> 2
DAYOFMONTH(date)
date
, в диапазоне от
1
до 31
:
mysql> select DAYOFMONTH('1998-02-03'); -> 3
DAYOFYEAR(date)
date
, в диапазоне от 1
до 366
:
mysql> select DAYOFYEAR('1998-02-03'); -> 34
MONTH(date)
date
, в диапазоне от 1
до
12
:
mysql> select MONTH('1998-02-03'); -> 2
DAYNAME(date)
date
:
mysql> select DAYNAME("1998-02-05"); -> 'Thursday'
MONTHNAME(date)
date
:
mysql> select MONTHNAME("1998-02-05"); -> 'February'
QUARTER(date)
date
, в диапазоне от
1
до 4
:
mysql> select QUARTER('98-04-01'); -> 2
WEEK(date)
WEEK(date,first)
date
, в
диапазоне от 0
до 53
(да, могут иметься начала
недели 53), для расположений, где воскресенье считается первым днем недели.
Форма с двумя параметрами WEEK()
позволяет Вам определять,
начинается ли неделя в воскресенье или в понедельник. Неделя начинается в
воскресенье, если второй параметр равен 0
, или в понедельник,
если он равен 1
:
mysql> select WEEK('1998-02-20'); -> 7 mysql> select WEEK('1998-02-20',0); -> 7 mysql> select WEEK('1998-02-20',1); -> 8 mysql> select WEEK('1998-12-31',1); -> 53
YEAR(date)
date
, в диапазоне от 1000
до
9999
:
mysql> select YEAR('98-02-03'); -> 1998
YEARWEEK(date)
YEARWEEK(date,first)
WEEK()
. Обратите внимание, что
год может отличаться от года в параметре для первой и последней недель:
mysql> select YEARWEEK('1987-01-01'); -> 198653
HOUR(time)
time
, в диапазоне от 0
до
23
:
mysql> select HOUR('10:05:03'); -> 10
MINUTE(time)
time
, в диапазоне от 0
до
59
:
mysql> select MINUTE('98-02-03 10:05:03'); -> 5
SECOND(time)
time
, в диапазоне от 0
до 59
:
mysql> select SECOND('10:05:03'); -> 3
PERIOD_ADD(P,N)
N
месяцев к периоду P
(в формате
YYMM
или YYYYMM
). Возвращает значение в формате
YYYYMM
. Обратите внимание, что параметр P
НЕ является датой:
mysql> select PERIOD_ADD(9801,2); -> 199803
PERIOD_DIFF(P1,P2)
P1
и
P2
. P1
и P2
должны быть в формате
YYMM
или YYYYMM
. Обратите внимание, что параметры
P1
и P2
НЕ являются датами:
mysql> select PERIOD_DIFF(9802,199703); -> 11
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
ADDDATE()
и SUBDATE()
представляют собой синонимы
DATE_ADD()
и DATE_SUB()
. В MySQL Version 3.23 Вы
можете использовать +
и -
вместо
DATE_ADD()
и DATE_SUB()
, если выражение справа
является столбом типа datetime или датой (пример ниже). date
значение типа DATETIME
или DATE
, определяющее
стартовую дату. expr
задает выражение, определяющее значение
интервала, которое будет добавлено или вычтено из стартовой даты.
expr
является строкой, оно может начинаться с `-'
для отрицательных интервалов. type
представляет собой ключевое
слово, указывающее, как данное выражение должно интерпретироваться. Связанная
функция EXTRACT(type FROM date)
возвращает интервал 'type' даты.
Следующая таблица показывает, как параметры type
и
expr
связаны:
type значение |
ожидаемый формат expr |
SECOND | SECONDS |
MINUTE | MINUTES |
HOUR | HOURS |
DAY | DAYS |
MONTH | MONTHS |
YEAR | YEARS |
MINUTE_SECOND | "MINUTES:SECONDS"
|
HOUR_MINUTE | "HOURS:MINUTES" |
DAY_HOUR | "DAYS HOURS" |
YEAR_MONTH | "YEARS-MONTHS" |
HOUR_SECOND | "HOURS:MINUTES:SECONDS"
|
DAY_MINUTE | "DAYS HOURS:MINUTES"
|
DAY_SECOND | "DAYS HOURS:MINUTES:SECONDS"
|
expr
. Показанные в
таблице представляют собой предложенные разделители. Если параметр
date
значение типа DATE
, и Ваши вычисления включают
только части YEAR
, MONTH
и DAY
,
(то есть никаких частей времени), результат будет значением типа
DATE
. Иначе будет установлен тип DATETIME
:
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; -> 1998-01-01 00:00:00 mysql> SELECT INTERVAL 1 DAY + "1997-12-31"; -> 1998-01-01 mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND; -> 1997-12-31 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 SECOND); -> 1998-01-01 00:00:00 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 DAY); -> 1998-01-01 23:59:59 mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL "1:1" MINUTE_SECOND); -> 1998-01-01 00:01:00 mysql> SELECT DATE_SUB("1998-01-01 00:00:00", INTERVAL "1 1:1:1" DAY_SECOND); -> 1997-12-30 22:58:59 mysql> SELECT DATE_ADD("1998-01-01 00:00:00", INTERVAL "-1 10" DAY_HOUR); -> 1997-12-30 14:00:00 mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY); -> 1997-12-02Если Вы определяете значение интервала, которое является слишком коротким (не включает все части интервала, которые ожидались бы из ключевого слова
type
), MySQL считает, что Вы не учли крайние левые части
значения интервала. Например, если Вы определяете type
как
DAY_SECOND
, значение expr
, как ожидается, будет
иметь дни, часы, минуты и секунды. Если Вы определяете, что значение выглядит
как "1:10"
, MySQL считает, что части дней и часов отсутствуют, а
значение представляет минуты и секунды. Другими словами, "1:10"
DAY_SECOND
интерпретируется таким способом, которым это является
эквивалентным "1:10" MINUTE_SECOND
. Это аналогично пути, которым
MySQL интерпретирует значения TIME
как представление прошедшего
времени, а не время дня. Обратите внимание, что, если Вы добавляете или
вычитаете значение date, работая с частями времени, оно будет автоматически
преобразовано в значение time:
mysql> select date_add("1999-01-01", interval 1 day); -> 1999-01-02 mysql> select date_add("1999-01-01", interval 1 hour); -> 1999-01-01 01:00:00Если Вы используете, действительно, неправильные даты, результатом будет
NULL
. Если Вы добавляете MONTH
,
YEAR_MONTH
или YEAR
, и возникающая в результате
дата имеет день, который является большим, чем максимальный день нового
месяца, день откорректирован к максимальному дню в новом месяце:
mysql> select DATE_ADD('1998-01-30', Interval 1 month); -> 1998-02-28Обратите внимание, что слово
INTERVAL
и ключевое слово
type
не чувствительны к регистру.
EXTRACT(type FROM date)
EXTRACT()
использует те же самые виды спецификаторов
типа интервала, что и DATE_ADD()
или DATE_SUB()
, но
извлекает части даты, а не проводит выполнение арифметики даты.
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02"); -> 1999 mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03"); -> 199907 mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03"); -> 20102
TO_DAYS(date)
date
, возвращает порядковый номер дня, считая с
самого первого года:
mysql> select TO_DAYS(950501); -> 728779 mysql> select TO_DAYS('1997-10-07'); -> 729669
TO_DAYS()
не предназначена для использования со значениями,
которые предшествуют появлению Грегорианского календаря (1582) потому, что
эта функция не принимает во внимание дни, которые были потеряны, когда
календарь был изменен.
FROM_DAYS(N)
N
, возвращает значение DATE
:
mysql> select FROM_DAYS(729669); -> '1997-10-07'
FROM_DAYS()
не предназначена для использования со значениями,
которые предшествуют появлению Грегорианского календаря (1582) потому, что
эта функция не принимает во внимание дни, которые были потеряны, когда
календарь был изменен.
DATE_FORMAT(date,format)
date
согласно строке
format
. Следующие спецификаторы могут использоваться в формате:
%M | Имя месяца
(январь ..декабрь ). |
%W | День недели
(воскресенье ..суббота ). |
%D | День месяца с английским суффиксом
(1st , 2nd , 3rd , ...). |
%Y | Год, числовое представление, 4 цифры. |
%y | Год, числовое представление, 2 цифры. |
%X | Год для недель, где воскресенье первый день недели, числовое представление, 4 цифры, используемые с '%V'. |
%x | Год для недель, где понедельник первый день недели, числовое представление, 4 цифры, используемые с '%v'. |
%a | Краткая форма названия дня
(Sun ..Sat ). |
%d | День месяца, числовой
(00 ..31 ). |
%e | День месяца, числовой
(0 ..31 ). |
%m | Месяц, числовой
(01 ..12 ). |
%c | Месяц, числовой
(1 ..12 ). |
%b | Краткая форма названия месяца
(Jan ..Dec ). |
%j | День года
(001 ..366 ). |
%H | Час (00 ..23 ). |
%k | Час (0 ..23 ). |
%h | Час (01 ..12 ). |
%I | Час (01 ..12 ). |
%l | Час (1 ..12 ). |
%i | Минуты, числовая форма
(00 ..59 ). |
%r | Время, 12-часовой формат
(hh:mm:ss [AP]M ). |
%T | Время, 24-часовой формат
(hh:mm:ss ). |
%S | Секунды (00 ..59 ).
|
%s | Секунды (00 ..59 ).
|
%p | AM или PM . |
%w | День недели
(0 =воскресенье..6 =суббота). |
%U | Неделя (0 ..53 ), где
воскресенье первый день недели. |
%u | Неделя (0 ..53 ), где
понедельник первый день недели. |
%V | Неделя (1 ..53 ), где
воскресенье первый день недели. Использован с '%X'. |
%v | Неделя (1 ..53 ), где
понедельник первый день недели. Использован с '%x'. |
%% | Знак процента (%). |
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); -> 'Saturday October 1997' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> select DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52'Начиная с MySQL Version 3.23, символ % обязательно требуется указывать перед символами спецификатора формата. В более ранних версиях MySQL символ % был факультативным.
TIME_FORMAT(time,format)
DATE_FORMAT()
, но строка
format
может содержать только те спецификаторы формата, которые
обрабатывают часы, минуты и секунды. Другие спецификаторы производят значения
NULL
или 0
.
CURDATE()
CURRENT_DATE
YYYY-MM-DD
или YYYYMMDD
, в зависимости от того,
используется ли функция в контексте строки или числа:
mysql> select CURDATE(); -> '1997-12-15' mysql> select CURDATE() + 0; -> 19971215
CURTIME()
CURRENT_TIME
HH:MM:SS
или
HHMMSS
, в зависимости от того, используется ли функция в
контексте строки или числа:
mysql> select CURTIME(); -> '23:50:26' mysql> select CURTIME() + 0; -> 235026
NOW()
SYSDATE()
CURRENT_TIMESTAMP
YYYY-MM-DD HH:MM:SS
или YYYYMMDDHHMMSS
в
зависимости от того, используется ли функция в контексте строки или числа:
mysql> select NOW(); -> '1997-12-15 23:50:26' mysql> select NOW() + 0; -> 19971215235026
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
1970-01-01 00:00:00
GMT). Если UNIX_TIMESTAMP()
вызван с параметром date
, это возвращает значение параметра как
секунды с момента 1970-01-01 00:00:00
GMT. date
может быть строками типов DATE
, DATETIME
,
TIMESTAMP
или числом в форматах YYMMDD
или
YYYYMMDD
в местном времени:
mysql> select UNIX_TIMESTAMP(); -> 882226357 mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580Когда
UNIX_TIMESTAMP
используется на столбце типа
TIMESTAMP
, функция получит значение непосредственно, без
неявного преобразования ``string-to-unix-timestamp''. Если Вы задаете
UNIX_TIMESTAMP()
неправильно, вернется 0.
FROM_UNIXTIME(unix_timestamp)
unix_timestamp
как
значение в формате YYYY-MM-DD HH:MM:SS
или
YYYYMMDDHHMMSS
в зависимости от того, используется ли функция в
контексте строки или числа:
mysql> select FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00' mysql> select FROM_UNIXTIME(875996580) + 0; -> 19971004222300
FROM_UNIXTIME(unix_timestamp,format)
unix_timestamp
как
строку, форматируемую согласно строке format
. Строка
format
может содержать те же самые спецификаторы, что и для
функции DATE_FORMAT()
:
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x'); -> '1997 23rd December 03:43:30 x'
SEC_TO_TIME(seconds)
seconds
, преобразованный в часы, минуты
и секунды, как значение в формате HH:MM:SS
или
HHMMSS
в зависимости от того, используется ли функция в
контексте строки или числа:
mysql> select SEC_TO_TIME(2378); -> '00:39:38' mysql> select SEC_TO_TIME(2378) + 0; -> 3938
TIME_TO_SEC(time)
time
, преобразованный в секунды:
mysql> select TIME_TO_SEC('22:23:00'); -> 80580 mysql> select TIME_TO_SEC('00:39:38'); -> 2378
MySQL использует BIGINT
(64-bit) арифметику для битовых
операций, так что эти операторы имеют максимальный диапазон в 64 бита.
|
mysql> select 29 | 15; -> 31
&
mysql> select 29 & 15; -> 13
<<
BIGINT
) влево:
mysql> select 1 << 2; -> 4
>>
BIGINT
) вправо:
mysql> select 4 >> 2; -> 1
~
mysql> select 5 & ~1; -> 4
BIT_COUNT(N)
N
:
mysql> select BIT_COUNT(29); -> 4
DATABASE()
mysql> select DATABASE(); -> 'test'Если не имеется никакой текущей базы данных,
DATABASE()
возвращает пустую строку.
USER()
SYSTEM_USER()
SESSION_USER()
mysql> select USER(); -> 'davida@localhost'В MySQL Version 3.22.11 и более поздних версиях это включает hostname пользователя, а не только имя пользователя. Вы можете извлекать только часть имени пользователя подобно этому:
mysql> select substring_index(USER(),"@",1); -> 'davida'
PASSWORD(str)
str
. Это
функция, которая используется для шифрования паролей MySQL для хранения в
столбце Password
таблицы привилегий user
:
mysql> select PASSWORD('badpwd'); -> '7f84554057dd964b'Шифрование
PASSWORD()
необратимо.
PASSWORD()
не выполняет шифрование пароля таким же образом, что
и Unix. Вы не должны считать, что, если Ваши пароли для Unix и MySQL
одинаковы, PASSWORD()
выдаст то же самое шифрованное значение,
какое сохранено в файле паролей Unix. См. функцию ENCRYPT()
.
ENCRYPT(str[,salt])
str
, используя системный вызов Unix
crypt()
. Параметр salt
должен быть строкой с двумя
символами. Начиная с MySQL Version 3.22.16, salt
может быть
длиннее, чем два символа:
mysql> select ENCRYPT("hello"); -> 'VxuFAJXVARROc'Если
crypt()
недоступен на Вашей системе, ENCRYPT()
всегда возвращает NULL
. ENCRYPT()
игнорирует все,
кроме первых 8 символов str
, по крайней мере на некоторых
системах. Это определено поведением системного вызова crypt()
.
ENCODE(str,pass_str)
str
, используя pass_str
как пароль.
Для дешифрования примените вызов DECODE()
. Результат: двоичная
строка string
той же самой длины. Если Вы хотите сохранять это в
столбце, используйте тип столбца BLOB
.
DECODE(crypt_str,pass_str)
crypt_str
, используя
pass_str
как пароль. crypt_str
должна быть строкой,
возвращенной из ENCODE()
.
MD5(string)
mysql> select MD5("testing"); -> 'ae2b1fca515949e5d54fb22b8ed95575'Это "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
LAST_INSERT_ID([expr])
AUTO_INCREMENT
.
mysql> select LAST_INSERT_ID(); -> 195Последний ID, который был сгенерирован, поддерживается сервером на основании подключения. Это не будет изменено другим пользователем. Это не будет даже изменено, если Вы модифицируете другой столбец
AUTO_INCREMENT
с
нормальным значением (то есть значением, которое не NULL
и не
0
). Если Вы вставляете много строк в то же самое время с
инструкцией insert, LAST_INSERT_ID()
возвращает значение для
первой вставленной строки. Причина для этого в том, чтобы сделать возможным
легкое воспроизведение той же самой инструкции на другом сервере.
Если expr
дан как параметр
LAST_INSERT_ID()
, то значение параметра возвращенного функцией,
будет установлено в следующее значение, которое будет возвращено
LAST_INSERT_ID()
и будет использоваться как следующее значение
auto_increment. Это может применяться, чтобы моделировать последовательности.
Сначала создайте таблицу:
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
, Вы не можете использовать эту
функцию, чтобы получать значение для 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> 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 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()
или уже снята.
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)
mysql> select INET_NTOA(3520061480); -> "209.207.224.40"
INET_ATON(expr)
mysql> select INET_ATON("209.207.224.40"); -> 3520061480Сгенерированное число всегда в порядке сетевых байт. Например, вышеупомянутое число вычислено как
209*255^3+207*255^2+224*255+40
.
MASTER_POS_WAIT(log_name, log_pos)
GROUP BY
Если Вы используете функцию в инструкции, не содержащей предложение
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(*)
оптимизирован, чтобы возвратить данные очень быстро,
если SELECT
получает данные из одной таблицы, никакие другие
столбцы не задействованы, и в запросе не имеется никакого предложения
WHERE
. Например:
mysql> select COUNT(*) from student;
COUNT(DISTINCT expr,[expr...])
NULL
:
mysql> select COUNT(DISTINCT results) from student;В MySQL Вы можете получить число различных комбинаций выражений, которые не содержат NULL, задавая список выражений. В ANSI SQL Вы были бы должны сделать конкатенацию всех выражений внутри
CODE(DISTINCT...)
.
AVG(expr)
expr
:
mysql> select student_name, AVG(test_score) from student GROUP BY student_name;
MIN(expr)
MAX(expr)
expr
.
MIN()
и MAX()
может брать строковый параметр. В
таких случаях они возвращают минимальное или максимальное значение строки.
mysql> select student_name, MIN(test_score), MAX(test_score) from student GROUP BY student_name;
SUM(expr)
expr
. Обратите внимание, что, если набор
возвратов не имеет никаких строк, это возвращает NULL!
STD(expr)
STDDEV(expr)
expr
. Это расширение ANSI
SQL. Форма STDDEV()
этой функции предусмотрена
для совместимости с Oracle.
BIT_OR(expr)
OR
всех битов в expr
.
Вычисление выполняется с 64-разрядной точностью (BIGINT
).
BIT_AND(expr)
AND
всех битов в 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 Вы были бы должны добавить customer.name
к
предложению GROUP BY
. В MySQL имя избыточно, если Вы не
выполняетесь в ANSI режиме.
Не используйте это свойство, если столбцы, которые Вы
получаете из предложения GROUP BY
не уникальны в группе! Вы
получите непредсказуемые результаты.
В некоторых случаях Вы можете использовать MIN()
и
MAX()
чтобы получить специфическое значение столбца, даже если
оно неуникально. Следующее выдает значение column
из строки,
содержащей самое маленькое значение в столбце sort
:
substr(MIN(concat(rpad(sort,6,' '),column)),7)
Подробности в разделе "3.5.4 В какой строке максимум по группе".
Обратите внимание, что, если Вы используете MySQL Version 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 Version 3.23 Вы можете сделать:
mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
Регулярные выражения (они же regular expression или regex) представляют собой мощный путь для определения сложного поиска.
MySQL использует реализацию Henry Spencer's, которая нацелена на соответствие POSIX 1003.2. MySQL использует ее расширенную версию.
Это упрощенное описание, которое опускает ряд деталей. За подробной
информацией отсылаю Вас к man-странице Henry Spencer's regex(7)
,
которая включена в дистрибутив исходного кода.
Регулярное выражение описывает набор строк. Самый простой regexp такой,
который не имеет никаких специальных символов. Например, regexp
hello
соответствует hello
и ничему другому.
Нетривиальные регулярные выражения используют некоторые специальные
конструкции так, чтобы они могли соответствовать больше, чем одной строке.
Например, regexp hello|word
соответствует строке
hello
или word
.
Как более сложный пример, regexp B[an]*s
соответствует любой
из строк Bananas
, Baaaaas
, Bs
и любой
другой строке, начинающейся с B
, заканчивающейся на
s
и содержащей любое число символов в диапазоне от
a
до n
между ними.
Регулярное выражение может использовать любой из следующих спецсимволов:
^
mysql> select "fo\nfo" REGEXP "^fo$"; -> 0 mysql> select "fofo" REGEXP "^fo"; -> 1
$
mysql> select "fo\no" REGEXP "^fo\no$"; -> 1 mysql> select "fo\no" REGEXP "^fo$"; -> 0
.
mysql> select "fofo" REGEXP "^f.*"; -> 1 mysql> select "fo\nfo" REGEXP "^f.*"; -> 1
a*
a
.
mysql> select "Ban" REGEXP "^Ba*n"; -> 1 mysql> select "Baaan" REGEXP "^Ba*n"; -> 1 mysql> select "Bn" REGEXP "^Ba*n"; -> 1
a+
a
.
mysql> select "Ban" REGEXP "^Ba+n"; -> 1 mysql> select "Bn" REGEXP "^Ba+n"; -> 0
a?
a
.
mysql> select "Bn" REGEXP "^Ba?n"; -> 1 mysql> select "Ban" REGEXP "^Ba?n"; -> 1 mysql> select "Baan" REGEXP "^Ba?n"; -> 0
de|abc
de
или abc
.
mysql> select "pi" REGEXP "pi|apa"; -> 1 mysql> select "axe" REGEXP "pi|apa"; -> 0 mysql> select "apa" REGEXP "pi|apa"; -> 1 mysql> select "apa" REGEXP "^(pi|apa)$"; -> 1 mysql> select "pi" REGEXP "^(pi|apa)$"; -> 1 mysql> select "pix" REGEXP "^(pi|apa)$"; -> 0
(abc)*
abc
.
mysql> select "pi" REGEXP "^(pi)*$"; -> 1 mysql> select "pip" REGEXP "^(pi)*$"; -> 0 mysql> select "pipi" REGEXP "^(pi)*$"; -> 1
{1}
{2,3}
a*
a{0,}
.
a+
a{1,}
.
a?
a{0,1}
.i
без запятой соответствует последовательности точно
i
вхождений атома. Атом, сопровождаемый одним числом с запятой,
соответствует последовательности из одного или большего числа вхождений
i
. Атом, сопровождаемый двумя целыми числами i
и
j
соответствует последовательности, включающей от i
до j
копий атома (границы диапазона входят в число). Оба
аргумента должны быть в диапазоне от 0
до
RE_DUP_MAX
(по умолчанию 255), включая границы. Если заданы два
аргумента, второй должен быть больше или равен первому, но не меньше его.
[a-dX]
[^a-dX]
a
, b
, c
,
d
или X
. Чтобы включить литеральный символ
]
, он должен следовать сразу за открывающейся скобкой
[
. Чтобы включить символ -
, он должен быть написан
первым или последним. Так [0-9]
соответствует любой десятичной
цифре. Любой символ, который не имеет определенного значения внутри
[]
, не имеет никакого специального значения.
mysql> select "aXbc" REGEXP "[a-dXYZ]"; -> 1 mysql> select "aXbc" REGEXP "^[a-dXYZ]$"; -> 0 mysql> select "aXbc" REGEXP "^[a-dXYZ]+$"; -> 1 mysql> select "aXbc" REGEXP "^[^a-dXYZ]+$"; -> 0 mysql> select "gheis" REGEXP "^[^a-dXYZ]+$"; -> 1 mysql> select "gheisa" REGEXP "^[^a-dXYZ]+$"; -> 0
[[.characters.]]
ch
, то регулярное выражение [[.ch.]]*c
соответствует первым пяти символам chchcc
.
[=character_class=]
o
и (+)
члены класса
эквивалентности, то [[=o=]]
, [[=(+)=]]
и
[o(+)]
синонимы. Класс эквивалентности не может
быть краем диапазона.
[:character_class:]
[:
и :]
, представляет список всех символов,
принадлежащих к классу. Стандартные символьные имена:
alnum | digit | punct |
alpha | graph | space |
blank | lower | upper |
cntrl | xdigit |
ctype(3)
. Регион или язык может обеспечивать другие. Символьный
класс не может использоваться как край диапазона.
mysql> select "justalnums" REGEXP "[[:alnum:]]+"; -> 1 mysql> select "!!" REGEXP "[[:alnum:]]+"; -> 0
[[:<:]]
[[:>:]]
ctype(3)
) или символов подчеркивания
(_
).
mysql> select "a word a" REGEXP "[[:<:]]word[[:>:]]"; -> 1 mysql> select "a xword a" REGEXP "[[:<:]]word[[:>:]]"; -> 0
mysql> select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1
Все клиенты MySQL, которые связываются с сервером, используя библиотеку
mysqlclient
, применяет следующие системные переменные:
Имя | Описание |
MYSQL_UNIX_PORT | Сокет по умолчанию. Используется
для связи с localhost |
MYSQL_TCP_PORT | TCP/IP порт по умолчанию |
MYSQL_PWD | Пароль по умолчанию |
MYSQL_DEBUG | Опции для трассировки, если используется режим отладки |
TMPDIR | Каталог для временных файлов и таблиц |
Применение MYSQL_PWD
опасно. Подробности в разделе
"2.1 Соединение с сервером".
Клиент mysql использует файл, именованный в системной переменной
MYSQL_HISTFILE
, чтобы сохранить хронологию командной строки.
Значение по умолчанию для файла хронологии: $HOME/.mysql_history,
здесь $HOME
представляет собой значение системной переменной
HOME
. Подробности в разделе
"Приложение 2. Переменные окружения
".
Все программы MySQL имеют много различных параметров. Однако, каждая
программа MySQL обеспечивает опцию --help
, которую Вы можете
использовать, чтобы получить полное описание различных параметров программы.
Например, mysql --help
.
Вы можете отменять заданные по умолчанию параметры для всех стандартных программ пользователя с помощью файла опций.
Список ниже кратко описывает программы MySQL:
myisamchk
myisamchk
имеет много
функций, он описан в собственной главе. Подробности в разделе
"4 Администрирование СУБД
MySQL".
make_binary_distribution
support.mysql.com
для удобства других пользователей MySQL.
msql2mysql
mSQL
в
MySQL. Не обрабатывает все случаи, но дает хорошее начало при преобразовании.
mysqlaccess
mysqladmin
mysqladmin
может
также использоваться, чтобы узнавать версию, данные о процессах и информацию
о текущем состоянии сервера.
mysqlbug
mysqld
mysqldump
mysqlimport
LOAD DATA INFILE
. Подробности в разделе
"12.7 mysqlimport, импортирование данных из
текстовых файлов".
mysqlshow
mysql_install_db
replace
msql2mysql
, но имеет более
общую применимость. replace
меняет строки в файлах или на
стандартном вводе. Использует специальный алгоритм, чтобы сначала
соответствовать более длинным строкам. Может использоваться, чтобы менять
строки. Например, эта команда меняет a
и b
в файлах:
shell> replace a b b a -- file1 file2 ...
mysql
простая SQL оболочка (с возможностями GNU
readline
). Это поддерживает интерактивное и не интерактивное
использование. Когда используется в интерактивном режиме, результаты запроса
будут представлены в формате ASCII-таблицы. Когда используется в не
интерактивном режиме (например, как фильтр), результат будет выведен в
разделяемом табуляциями формате. Выходной формат может быть изменен,
используя параметры командной строки. Вы можете выполнять скрипты так:
shell> mysql database < script.sql > output.tab
Если Вы имеете проблемы из-за недостаточной памяти у клиента, используйте
опцию --quick
! Это вынуждает клиент mysql
использовать mysql_use_result()
вместо вызова
mysql_store_result()
, чтобы отыскать набор результатов.
Использование mysql
очень просто. Только запустите его
следующим образом: mysql database
или mysql
--user=user_name --password=your_password database
. Напечатайте
инструкцию SQL, закончите ее `;', `\g' или
`\G' и нажмите RETURN/ENTER.
mysql
поддерживает следующие параметры:
-?, --help
-A, --no-auto-rehash
-B, --batch
--character-sets-dir=...
-C, --compress
-#, --debug[=...]
-D, --database=...
my.cnf
.
--default-character-set=...
-e, --execute=...
-E, --vertical
\G
.
-f, --force
-g, --no-named-commands
-G, --enable-named-commands
-i, --ignore-space
-h, --host=...
-H, --html
-L, --skip-line-numbers
--no-pager
--no-tee
-n, --unbuffered
-N, --skip-column-names
-O, --set-variable var=option
--help
.
-o, --one-database
--pager[=...]
PAGER
. Допустимые значения: less, more, cat [> filename],
etc. Подробности в интерактивной справке (\h). Эта опция не работает в
пакетном режиме. Pager работает только в UNIX.
-p[password], --password[=...]
-p
, Вы не
можете иметь пробелов между этой опцией и паролем.
-P --port=...
-q, --quick
-r, --raw
--batch
.
-s, --silent
-S --socket=...
-t --table
-T, --debug-info
--tee=...
-u, --user=#
-U, --safe-updates[=#], --i-am-a-dummy[=#]
UPDATE
и DELETE
, которые
используют ключи. Вы можете сбрасывать эту опцию, если Вы имеете ее в Вашем
файле my.cnf
, используя параметр --safe-updates=0
.
-v, --verbose
-V, --version
-w, --wait
Вы можете также устанавливать следующие переменные через -O
или --set-variable
:
Имя переменной | Значение по умолчанию | Описание |
connect_timeout | 0 | Число секунд перед завершением подключения по тайм-ауту. |
max_allowed_packet | 16777216 | Максимальная длина пакетов для обмена с сервером. |
net_buffer_length | 16384 | Буфер для связи через сокет или TCP/IP. |
select_limit | 1000 | Автоматическое ограничение для SELECT при использовании --i-am-a-dummy |
max_join_size | 1000000 | Автоматическое ограничение для строк в объединении при использовании --i-am-a-dummy. |
Если Вы напечатаете 'help' в командной строке, mysql
распечатает команды, которые он поддерживает:
mysql> help MySQL commands: help (\h) Display this text. ? (\h) Synonym for `help'. clear (\c) Clear command. connect (\r) Reconnect to the server. Optional arguments are db and host. edit (\e) Edit command with $EDITOR. ego (\G) Send command to mysql server, display result vertically. exit (\q) Exit mysql. Same as quit. go (\g) Send command to mysql server. nopager (\n) Disable pager, print to stdout. notee (\t) Don't write into outfile. pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. print (\p) Print current command. quit (\q) Quit mysql. rehash (\#) Rebuild completion hash. source (\.) Execute a SQL script file. Takes a file name as an argument. status (\s) Get status information from the server. tee (\T) Set outfile [to_outfile]. Append everything into given outfile. use (\u) Use another database. Takes database name as argument.
Внимание: pager работает только в UNIX.
Команда status
дает Вам некоторую
информацию относительно подключения и сервера, который Вы используете. Если
Вы работаете в режиме --safe-updates
, status
будет
также печатать значения для переменных mysql
, которые
воздействуют на Ваши запросы.
Полезная опция запуска для новичков (появилась в
MySQL Version 3.23.11): --safe-updates
(или
--i-am-a-dummy
для пользователей, которые скомандовали
DELETE FROM table_name
, но забыли указать предложение
WHERE
). При использовании этой опции, mysql
посылает следующую команду серверу MySQL при открытии подключения:
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#, SQL_MAX_JOIN_SIZE=#max_join_size#"
Здесь #select_limit#
и #max_join_size#
являются
переменными, которые могут быть заданы в командной строке mysql
.
Эффект вышеупомянутой команды:
UPDATE
или
DELETE
, если Вы не имеете ограничения ключа в части
WHERE
. Можно, однако, выполнить UPDATE/DELETE
,
используя слово LIMIT
:
UPDATE table_name SET not_key_column=# WHERE not_key_column=# LIMIT 1;
#select_limit#
.
SELECT
, который, вероятно, должен будет исследовать больше,
чем #max_join_size
комбинаций строк, будет прерван.Некоторые полезные советы относительно применения клиента
mysql
:
Некоторые данные намного более читаемы, когда отображаются вертикально, вместо обычного горизонтального вывода, типа блока. Например, более длинный текст, который включает новые строки, часто намного проще читать с вертикальным выводом. Например:
mysql> select * from mails where length(txt) < 300 limit 300,1\G *************************** 1. row *************************** msg_nro: 3068 date: 2000-03-01 23:29:50 time_zone: +0200 mail_from: Monty reply: monty@no.spam.com mail_to: "Thimble Smith" <tim@no.spam.com> sbj: UTF-8 txt: >>>>> "Thimble" == Thimble Smith writes: Thimble> Hi. I think this is a good idea. Is anyone familiar with Thimble> UTF-8 or Unicode? Otherwise I'll put this on my TODO list Thimble> and see what happens. Yes, please do that. Regards, Monty file: inbox-jani-1 hash: 190402944 1 row in set (0.09 sec)
tee
. Режим
tee
может быть начат с помощью опции --tee=...
или
из командной строки в интерактивном режиме с помощью команды
tee
. Все данные, отображаемые на экране, будут также добавляться
в заданный файл. Это может быть очень полезно для отладки. Режим может быть
заблокирован из командной строки командой notee
. Выполнение
tee
второй раз снова начинает регистрировать вывод. Без
параметра будет использоваться предыдущий файл. Обратите внимание, что
tee
сбрасывает результаты в файл после каждой команды прежде,
чем появляется командная строка.
--pager[=...]
. Без параметра клиент mysql
будет искать системную переменную PAGER и соответственно устанавливать свой
параметр pager
. Этот режим может быть запущен из интерактивной
командной строки командой pager
и заблокирован командой
nopager
. Команда факультативно берет параметр, и
pager
будет установлен в заданное им значение. Команда
pager
может быть вызвана без параметра, но это требует, чтобы
использовалась опция --pager
, или pager
будет
значением по умолчанию (stdout). pager
работает только в UNIX,
так как это использует функцию popen(), которая не существует в Windows. Под
ОС Windows опция tee
может использоваться вместо этого, хотя она
не может быть столь же удобна, как pager
в некоторых ситуациях.
pager
: Вы можете использовать
его, чтобы писать в файл:
mysql> pager cat > /tmp/log.txtИ результаты будут переданы только в этот файл. Вы можете также передавать любые параметры для программ, которые Вы хотите использовать с
pager
:
mysql> pager less -n -i -SИз вышеупомянутого обратите внимание на опцию '-S'. Вы можете посчитать ее очень полезной при просмотре результатов. Попробуйте опцию с горизонтальным выводом (команды заканчиваются на '\g' или ';') и с вертикальным выводом (команды заканчиваются на '\G'). Иногда очень широкий набор результатов должен быстро читаться с экрана, с опцией -S и программой less Вы сможете просмотреть результаты внутри интерактивного less слева направо без строк, более длинных, чем Ваш экран. Это может сделать результат намного более читаемым. Вы можете переключать режим внутри интерактивного less с помощью '-S'. Подробности в описании на 'h'.
mysql> pager cat|tee /dr1/tmp/res.txt|tee /dr2/tmp/res2.txt| \ less -n -i -S
tee
,
pager
установить на 'less', и Вы будете способны просмотреть
результаты в unix 'less' и все еще копировать весь вывод в файл. Различие
между UNIX tee
, используемом с pager
и клиентом
mysql
то, что встроенный режим tee
работает, даже
если Вы не имеете UNIX tee
.Утилита для выполнения административных операций. Синтаксис:
shell> mysqladmin [OPTIONS] command [command-option] command ...
Вы можете получить список параметров, которые Ваша версия
mysqladmin
поддерживает, выполняя mysqladmin
--help
.
Текущая версия mysqladmin
поддерживает следующие команды:
create databasename
drop databasename
extended-status
flush-hosts
flush-logs
flush-tables
flush-privileges
kill id,id,...
password
ping
processlist
reload
refresh
shutdown
slave-start
slave-stop
status
variables
version
Все команды могут быть сокращены к их уникальному префиксу. Например:
shell> mysqladmin proc stat +----+-------+-----------+----+-------------+------+-------+------+ | Id | User | Host | db | Command | Time | State | Info | +----+-------+-----------+----+-------------+------+-------+------+ | 6 | monty | localhost | | Processlist | 0 | | | +----+-------+-----------+----+-------------+------+-------+------+ Uptime: 10077 Threads: 1 Questions: 9 Slow queries: 0 Opens: 6 Flush tables: 1 Open tables: 2 Memory in use: 1092K Max memory used: 1116K
Результат команды mysqladmin status
имеет следующие столбцы:
Если Вы делаете myslqadmin shutdown
на сокете (другими
словами, на компьютере, где запущен mysqld
),
mysqladmin
будет ждать, пока не будет удален MySQL
pid-file
, чтобы гарантировать, что сервер mysqld
был завершен правильно.
mysqlcheck
для
поддержания таблиц и восстановленияНачиная с MySQL version 3.23.38, Вы можете использовать новый инструмент
для проверки и ремонта таблиц MyISAM
. Отличие от
myisamchk
в том, что mysqlcheck
должен
использоваться, когда сервер mysqld
работает, а
myisamchk
работает только, когда сервер выключен.
mysqlcheck
использует команды сервера MySQL
CHECK
, REPAIR
, ANALYZE
и
OPTIMIZE
удобным для пользователя способом.
Имеются три альтернативных способа вызвать mysqlcheck
:
shell> mysqlcheck [OPTIONS] database [tables] shell> mysqlcheck [OPTIONS] --databases DB1 [DB2 DB3...] shell> mysqlcheck [OPTIONS] --all-databases
mysqlcheck
имеет специальное свойство, сравнимое с другой
клиентурой: заданное по умолчанию поведение при проверке таблиц (-c) может
быть изменено переименованием. Так, если Вы хотите иметь инструмент для
ремонта таблиц по умолчанию, Вы должны только скопировать
mysqlcheck
под именем mysqlrepair
или создать
символическую связь mysqlrepair
.
Имена, которые Вы можете использовать, чтобы изменить заданное по
умолчанию поведение mysqlcheck
:
mysqlrepair: По умолчанию опция -r mysqlanalyze: По умолчанию опция -a mysqloptimize: По умолчанию опция -o
Параметры, доступные для mysqlcheck
, перечислены здесь,
пожалуйста, проверьте, что Ваша версия поддерживает вызов
mysqlcheck --help
.
-A, --all-databases
-1, --all-in-1
-a, --analyze
--auto-repair
-#, --debug=...
--character-sets-dir=...
-c, --check
-C, --check-only-changed
--compress
-?, --help
-B, --databases
--default-character-set=...
-F, --fast
-f, --force
-e, --extended
-h, --host=...
-m, --medium-check
-o, --optimize
-p, --password[=...]
-P, --port=...
-q, --quick
-r, --repair
-s, --silent
-S, --socket=...
--tables
-u, --user=#
-v, --verbose
-V, --version
Утилита позволяет сбросить в дамп одну или несколько баз данных для резервирования или транспортировки на другой сервер SQL (необязательно MySQL). Дамп будет содержать инструкции SQL, чтобы создать и заполнять таблицу данными.
Если Вы делаете копию на сервер, Вы должны рассмотреть использование
вместо этой утилиты mysqlhotcopy
. Подробности в разделе
"12.6 mysqlhotcopy, копирование баз
данных и таблиц MySQL".
shell> mysqldump [OPTIONS] database [tables] mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] mysqldump [OPTIONS] --all-databases [OPTIONS]
Если Вы не задаете таблицы или используете --databases
или
--all-databases
, целая база данных будет сброшена в дамп.
Вы можете получить список параметров, которые поддерживает Ваша версия
mysqldump
, выполняя mysqldump --help
.
Обратите внимание, что, если Вы выполняете mysqldump
без
опций --quick
или --opt
, mysqldump
загрузит целый набор результатов в память перед дампингом. Это будет,
вероятно, проблемой, если Вы обрабатываете большую базу данных.
Обратите внимание, что, если Вы используете новую копию программы
mysqldump
и собираетесь делать дамп, который будет читаться
очень старым сервером MySQL, Вы не должны использовать параметры
--opt
или -e
.
mysqldump
поддерживает следующие параметры:
--add-locks
LOCK TABLES
перед и UNLOCK TABLE
после
каждого дампа таблицы, чтобы получить быстрые вставки в MySQL.
--add-drop-table
drop table
перед каждой инстукцией создания.
-A, --all-databases
--databases
со всеми выбранными базами данных.
-a, --all
--allow-keywords
-c, --complete-insert
-C, --compress
-B, --databases
USE
db_name;
будет включен в вывод перед каждой новой базой данных.
--delayed
INSERT DELAYED
.
-e, --extended-insert
INSERT
. Дает более компактные и
быстрые инструкции вставок.
-#, --debug[=option_string]
--help
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
-T
и имеют то же самое
значение, что и соответствующие предложения для LOAD DATA
INFILE
. Подробности в разделе "8.9
Синтаксис LOAD DATA INFILE
".
-F, --flush-logs
-f, --force,
-h, --host=...
localhost
.
-l, --lock-tables
READ LOCAL
, чтобы позволить параллельные вставки в
случае таблиц MyISAM
.
-n, --no-create-db
-t, --no-create-info
CREATE TABLE
).
-d, --no-data
--opt
--quick --add-drop-table --add-locks
--extended-insert --lock-tables
. Опция должна дать Вам самый быстрый
возможный дамп для чтения на сервере MySQL.
-pyour_pass, --password[=your_pass]
-P port_num, --port=port_num
localhost
, там применяются Unix-сокеты.
-q, --quick
mysql_use_result()
.
-r, --result-file=...
-S /path/to/socket, --socket=/path/to/socket
localhost
.
Он является заданным по умолчанию компьютером.
--tables
-T, --tab=path-to-some-directory
table_name.sql
, который содержит команды SQL
CREATE, и файл table_name.txt
, который содержит данные для
каждой указанной таблицы. ОБРАТИТЕ ВНИМАНИЕ: Это работает
только, если mysqldump
выполнен на той же самой машине, что и
сервер mysqld
. Формат файла .txt
соответствует
опциям --fields-xxx
и --lines--xxx
.
-u user_name, --user=user_name
-O var=option, --set-variable var=option
-v, --verbose
-V, --version
-w, --where='where-condition'
"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
-O net_buffer_length=#, where # < 16M
--extended-insert
или --opt
),
mysqldump
создаст строки длины до net_buffer_length
.
Если Вы увеличиваете эту переменную, Вы должны также гарантировать, что
переменная max_allowed_packet
в сервере MySQL больше, чем
net_buffer_length
.Наиболее нормальное использование mysqldump
: создание копий
целых баз данных. Подробности в разделе "4.1
Резервирование баз данных":
mysqldump --opt database > backup-file.sql
Вы можете прочитать этот файл обратно в MySQL:
mysql database < backup-file.sql
или:
mysql -e "source /patch-to-backup/backup-file.sql" database
Однако, утилита также очень полезна, когда надо заполнить другой сервер MySQL информацией из базы данных:
mysqldump --opt database|mysql --host=remote-host -C database
Возможно выполнить дамп нескольких баз данных одной командой:
mysqldump --databases database1 [database2 database3...] > my_databases.sql
Если требуются все базы данных, можно использовать:
mysqldump --all-databases > all_databases.sql
mysqlhotcopy
представляет собой perl-скрипт, который
использует LOCK TABLES
, FLUSH TABLES
и
cp
или scp
, чтобы быстро сделать копию базы данных.
Это самый быстрый способ сделать копию с базы данных или одиночной таблицы,
но это может быть выполнено только на той же самой машине, где находятся
каталоги баз данных.
mysqlhotcopy db_name [/path/to/new_directory] mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory mysqlhotcopy db_name./regex/
mysqlhotcopy
поддерживает следующие параметры:
-?, --help
-u, --user=#
-p, --password=#
-P, --port=#
-S, --socket=#
--allowold
--keepold
--noindices
myisamchk -rq
.
--method=#
cp
или scp
).
-q, --quiet
--debug
-n, --dryrun
--regexp=#
--suffix=#
--checkpoint=#
--flushlog
--tmpdir=#
Вы можете использовать perldoc mysqlhotcopy
, чтобы получить
более полную документацию для mysqlhotcopy
.
mysqlhotcopy
читает группы [client]
и
[mysqlhotcopy]
из файлов опций.
Чтобы выполнить mysqlhotcopy
, Вы нуждаетесь в доступе к
резервному каталогу для записи, в привилегии SELECT
для таблиц,
которые Вы собираетесь копировать, и в привилегии MySQL Reload
,
чтобы выполнить команду FLUSH TABLES
.
mysqlimport
интерфейс командной строки к инструкции SQL
LOAD DATA INFILE
. Большинство параметров
mysqlimport
непосредственно соответствует тем же самым
параметрам LOAD DATA INFILE
. Подробности в разделе
"8.9 Синтаксис LOAD DATA INFILE
".
mysqlimport
вызывается подобно этому:
shell> mysqlimport [options] database textfile1 [textfile2....]
Для каждого текстового файла, указанного в командной строке,
mysqlimport
отделяет любое расширение от имени файла и
использует результат, чтобы определить, в которую таблицу импортировать
содержание файла. Например, файлы с именами patient.txt,
patient.text и patient будут все вместе импортированы в
одну таблицу patient
.
mysqlimport
поддерживает следующие параметры:
-c, --columns=...
LOAD DATA
INFILE
, которая затем будет передана MySQL. Подробности в разделе
"8.9 Синтаксис LOAD DATA INFILE
".
-C, --compress
-#, --debug[=option_string]
-d, --delete
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
LOAD DATA INFILE
. Подробности в разделе
"8.9 Синтаксис LOAD DATA INFILE
".
-f, --force
--force
mysqlimport
прерывает работу, если нужная
таблица не существует.
--help
-h host_name, --host=host_name
localhost
.
-i, --ignore
--replace
.
-l, --lock-tables
-L, --local
localhost
(который является заданным по умолчанию компьютером).
-pyour_pass, --password[=your_pass]
mysqlimport
запросит
Вас относительно пароля.
-P port_num, --port=port_num
localhost
,
там применены сокеты Unix.
-r, --replace
--replace
и --ignore
контролируют
обработку управления параметров входных записей, которые дублируют
существующие записи на уникальных значениях ключа. Если Вы определяете
--replace
, новые строки заменят существующие, которые имеют то
же самое уникальное значение ключа. Если Вы определяете
--ignore
, они будут пропущены. Если Вы не определяете никакой
опции вообще, происходит ошибка, когда найдено двойное значение ключа, а
остальная часть текстового файла игнорируется.
-s, --silent
-S /path/to/socket, --socket=/path/to/socket
localhost
(является заданным по умолчанию компьютером).
-u user_name, --user=user_name
-v, --verbose
-V, --version
Имеется типовой образец выполнения mysqlimport
:
$ mysql --version mysql Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686) $ uname -a Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown $ mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test $ ed a 100 Max Sydow 101 Count Dracula . w imptest.txt 32 q $ od -c imptest.txt 0000000 1 0 0 \t M a x S y d o w \n 1 0 0000020 1 \t C o u n t D r a c u l a \n 0000040 $ mysqlimport --local test imptest.txt test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0 $ mysql -e 'SELECT * FROM imptest' test +------+---------------+ | id | n | +------+---------------+ | 100 | Max Sydow | | 101 | Count Dracula | +------+---------------+
mysqlshow
может использоваться, чтобы быстро посмотреть,
какие базы данных существуют, их таблицы и столбцы этих таблиц.
Программой mysql
Вы можете получать ту же самую информацию
командой SHOW
. Подробности в разделе
"4.10 Синтаксис SHOW
".
mysqlshow
вызывается подобно этому:
shell> mysqlshow [OPTIONS] [database [table [column]]]
Обратите внимание, что в более новых версиях MySQL, Вы только видите те базы данных/таблицы/столбцы, для которых Вы имеете некоторые привилегии.
Если последний параметр содержит подстановочные знаки оболочки или SQL
(*
, ?
, %
или _
),
показывается только то, что согласовано групповым символом. Это может вызвать
некоторый беспорядок, когда Вы пробуете отображать столбцы для таблицы с
символом _
в имени, поскольку в этом случае
mysqlshow
показывает Вам имена, соответствующие образцу. Это
легко устранимо добавлением в конце командной строки символа %
(как отдельный параметр).
perror
может использоваться, чтобы печатать сообщения об
ошибках. perror
может вызываться подобно этому:
shell> perror [OPTIONS] [ERRORCODE [ERRORCODE...]] например: shell> perror 64 79 Error code 64: Machine is not on the network Error code 79: Can not access a needed shared library
perror
может использоваться, чтобы отобразить описание для
кода ошибки системы или драйвера таблицы MyISAM/ISAM. Сообщения об ошибках
обычно зависят от системы.
Клиент mysql
обычно используется в интерактивном режиме:
shell> mysql database
Однако, также возможно поместить Ваши команды SQL в файл и сообщить, чтобы
mysql
читал ввод из того файла. Чтобы сделать так, создайте
текстовый файл text_file, хранящий команды, которые Вы желаете
выполнить. Затем вызовите mysql
как показано ниже:
shell> mysql database < text_file
Вы можете также запустить Ваш текстовый файл с помощью инструкции
USE db_name
. В этом случае, не нужно определять имя базы данных
на командной строке:
shell> mysql < text_file