RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 4. Учебник

Эта глава обеспечивает учебное введение в MySQL, показывая, как использовать mysql , чтобы создать и использовать простую базу данных. mysql (иногда называемый terminal monitor или monitor) является интерактивной программой, которая позволяет Вам соединиться с сервером MySQL, выполнить запросы и рассмотреть результаты. mysql может также использоваться в пакетном режиме: Вы помещаете свои запросы в файл заранее, затем говорите mysql, чтобы выполнять содержание файла. Оба способа использовать mysql покрыты здесь подробно.

Чтобы видеть список возможностей, предоставленных mysql, вызовите это с опцией --help :

shell> mysql --help
Эта глава предполагает, что mysql установлен на Вашей машине и что сервер MySQL доступен, с которым Вы можете соединиться. Если это не так, свяжитесь со своим администратором MySQL. Если Вы и есть администратор, Вы должны консультироваться с соответствующими частями этого руководства, такими как глава 6.

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

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

4.1. Соединение с и отсоединение от сервера

Чтобы соединиться с сервером, Вы должны будете обычно обеспечивать имя пользователя MySQL, когда Вы вызовете mysql и, наиболее вероятно, пароль. Если сервер будет работать не на той машине, где Вы входите в систему, то Вы должны будете также определить имя хоста. Свяжитесь со своим администратором, чтобы узнать, какие параметры соединения Вы должны использовать, чтобы соединиться (то есть, узел, имя пользователя и пароль, чтобы использовать). Как только Вы знаете надлежащие параметры, Вы должны быть в состоянии соединиться:

shell> mysql -h host -u user -p
Enter password: ********
host и user представляют имя хоста, где Ваш сервер MySQL работает и имя пользователя Вашей учетной записи MySQL. Замените на соответствующие значения для Вашей установки. ******** представляет Ваш пароль, введите его, когда 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 25338 to server version: 8.0.1-standard

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>
Приглашение mysql> говорит Вам, что mysql готов к работе с запросами.

Если Вы входите в систему на той же самой машине, где работает MySQL, Вы можете опустить узел и просто использовать следующее:

shell> mysql -u user -p
Если, когда Вы пытаетесь войти в систему, Вы получаете сообщение об ошибке, например, ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2), это означает, что демон сервера MySQL (Unix) или служба (Windows) не работает. Консультируйтесь с администратором или см. раздел главы 2, который является соответствующим Вашей операционной системе.

Для помощт с другими проблемами, с которыми часто сталкиваются, пытаясь войти в систему, см. раздел B.5.2.

Некоторые установки MySQL разрешают пользователям соединяться как анонимный (неназванный) пользователь с сервером, работающим на местном узле. Если это верно на Вашей машине, Вы должны быть в состоянии соединиться с тем сервером, вызывая mysql без любых опций:

shell> mysql
После того, как Вы соединились успешно, Вы можете разъединиться в любое время, вводя QUIT (или \q) в ответ на подсказку mysql>:
mysql> QUIT
Bye

В Unix Вы можете также разъединиться, нажимая Control+D.

Большинство примеров в следующих разделах предполагает, что Вы соединены с сервером. Они указывают на это подсказкой mysql>.

4.2. Ввод запросов

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

Вот простой запрос, который просит, чтобы сервер сказал Вам свой номер версии и текущую дату. Напечатайте это как показано здесь после подсказки mysql> и нажмите Enter:

mysql> SELECT VERSION(), CURRENT_DATE;
+-----------+--------------+
| VERSION() | CURRENT_DATE |
+-----------+--------------+
| 5.8.0-m17 | 2015-12-21   |
+-----------+--------------+
1 row in set (0.02 sec)
mysql>
Этот запрос иллюстрирует несколько вещей о mysql:

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

  • Когда Вы делаете запрос, mysql посылает это в сервер для выполнения и выводит на экран результаты, затем печатает другое приглашение mysql>, чтобы указать, что это готово к другому запросу.
  • mysql выводит на экран вывод запроса в табличной форме (строки и столбцы). Первая строка содержит метки для столбцов. Следующие строки это результаты запроса. Обычно метки столбца это названия столбцов, которые Вы приносите от таблиц базы данных. Если Вы получаете значение выражения, а не столбец таблицы, mysql маркирует столбец, используя выражение непосредственно.
  • mysql показывает, сколько строк было возвращено и сколько времени запрос взял, чтобы выполниться, что дает Вам общее представление о работе сервера. Эти значения неточны, потому что они представляют время с часов (а не центрального процессора или машинное время), и потому что они затронуты такими факторами, как загрузка сервера и сетевое время ожидания. Для краткости строка 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.70710678118655 | 25      |
+------------------+---------+
1 row in set (0.02 sec)
Запросы, показанные к настоящему времени, были относительно короткими однострочными запросами. Вы можете даже ввести много запросов в одной строке. Только закончите каждый точкой с запятой:
mysql> SELECT VERSION(); SELECT NOW();
+-----------+
| VERSION() |
+-----------+
| 5.8.0-m17 |
+-----------+
1 row in set (0.00 sec)

+---------------------+
| NOW()               |
+---------------------+
| 2015-12-21 14:06:10 |
+---------------------+
1 row in set (0.00 sec)
Запросы нельзя дать все на одной строке, так что длинные запросы, которые требуют несколько строк, не проблема. mysql определяет, где Ваш запрос заканчивается, ища заканчивающую точку с запятой, а не конец входной строки. Другими словами, mysql принимает ввод свободного формата: это собирает входные строки, но не выполняет их, пока не увидит точку с запятой.

Вот простой многострочный запрос:

mysql> SELECT
    -> USER()
    -> ,
    -> CURRENT_DATE;
+---------------+--------------+
| USER()        | CURRENT_DATE |
+---------------+--------------+
| jon@localhost | 2015-12-21   |
+---------------+--------------+
В этом примере, заметьте, как подсказка изменяется от mysql> на -> после того, как Вы вводите первую строку многострочного запроса. Это то, как mysql указывает, что еще не видел полный запрос. Подсказка Ваш друг, потому что она обеспечивает ценную обратную связь. Если Вы используете эту обратную связь, Вы можете всегда знать о том, чего ждет mysql.

Если Вы решаете, что не хотите выполнять запрос, когда находитесь в процессе ввода, отмените это, вводя \c:

mysql> SELECT
    -> USER()
    -> \c
mysql>
Здесь, также, заметьте подсказку. Это переключается назад на mysql> после ввода \c, для обеспечения обратной связи, чтобы указать, что mysql готов к новому запросу.

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

ПодсказкаСмысл
mysql> Готов к новому запросу.
-> Ожидание следующей строки многострочного запроса.
'>Ожидание следующей строки, ожидая завершения строки, которая началась с одинарной кавычки (').
"> Ожидание следующей строки, ожидая завершения строки, которая началась с двойной кавычки (").
`> Ожидание следующей строки, ожидая завершения идентификатора, который начался с обратной кавычки (`).
/*> Ожидание следующей строки, ожидая завершения комментария, который начался с /*.

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

mysql> SELECT USER()
    ->
Если это происходит с Вами (Вы думаете, что ввели запрос, но единственный ответ ->), наиболее вероятно, что mysql ждет точку с запятой. Если Вы не замечаете то, что подсказка говорит Вам, Вы могли бы сидеть так некоторое время прежде, чем понять, что Вы должны сделать. Введите точку с запятой, чтобы завершить запрос, и mysql его сразу выполнит:
mysql> SELECT USER()
    -> ;
+---------------+
| USER()        |
+---------------+
| jon@localhost |
+---------------+
'> и "> происходят во время строкового набора (другой способ сказать, что MySQL ждет завершения строки). В MySQL Вы можете написать строки, окруженные также ' или " (например, 'hello' или "goodbye"), и mysql позволяет Вам вводить строки, которые охватывают многократные строки. Когда Вы видите подсказку '> или ">, это означает, что Вы ввели строку, содержащую строку, которая начинается с ' или ", но еще не ввели соответствующую кавычку, которая заканчивает строку. Это часто указывает, что Вы неосторожно не учли символ кавычки. Например:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
    '>
Если Вы вводите этот SELECT, затем нажмете Enter и ждете результата, ничего не происходит. Вместо того, чтобы задаться вопросом, почему этот запрос занимает много времени, заметьте представление, данное подсказкой '>. Это говорит Вам, что mysql ожидает увидеть остальную часть незаконченной строки. Вы видите ошибку в запросе? Строка 'Smith пропускает вторую одинарную кавычку.

В этом пункте, что Вы делаете? Самая простая вещь состоит в том, чтобы отменить запрос. Однако, Вы не можете просто ввести \c в этом случае, потому что mysql интерпретирует это как часть строки, которую это собирает. Вместо этого введите заключительный символ кавычки (таким образом mysql узнает, что Вы закончили строку), затем введите \c:

mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
    '> '\c
mysql>
Подсказка изменяется назад на mysql>, указывая, что mysql готов к новому запросу.

Подсказка `> подобна '> и ">, но указывает, что Вы начали, но не завершили заключенный в кавычки идентификатор.

Важно знать, что подсказки '>, "> и `> имеют значение, потому что, если Вы по ошибке вводите незаконченную строку, дальнейшие строки, Вы вводите, кажется, проигнорированы mysql , включая строку, содержащую QUIT. Это может быть довольно запутывающим, особенно если Вы не знаете, что должны поставлять заканчивающую кавычку прежде, чем Вы сможете отменить текущий запрос.

4.3. Создание и использование базы данных

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

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

  • Создайте базу данных.

  • Составьте таблицу.
  • Загрузите данные в таблицу.
  • Получите данные от таблицы различными способами.
  • Используйте много таблиц.

База данных зверинца проста (сознательно), но не трудно думать о ситуациях реального мира, в которых мог бы использоваться подобный тип базы данных. Например, такая база данных могла использоваться фермером, чтобы отследить домашний скот, или ветеринаром, чтобы отследить пациентов. Распределение зверинца, содержащее некоторые из запросов и типовых данных, используемых в следующих разделах, может быть получено с Веб-сайта MySQL. Это доступно в сжатом файле tar и Zip на http://dev.mysql.com/doc/.

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

mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql    |
| test     |
| tmp      |
+----------+
База данных mysql описывает пользовательские привилегии доступа. test часто доступна как рабочее пространство пользователям, чтобы испытать запросы.

Список баз данных, выведенных на экран запросом, может отличаться на Вашей машине, SHOW DATABASES не показывает базы данных, на которые у Вас нет никаких привилегий, если Вы не имеете привилегии SHOW DATABASES . См. раздел 14.7.5.14.

Если есть база test, попробуйте ее:

mysql> USE test
Database changed
USE, аналогично QUIT, не требует точки с запятой. Вы можете закончить такие запросы точкой с запятой, если Вам нравится, это не причиняет вреда. USE является особенным в другом отношении: это должно быть дано на одной строке.

Вы можете использовать базу данных test (если у Вас есть доступ к этому) для примеров, но что-либо, что Вы создаете в этой базе данных, может быть удалено кем-либо еще с доступом к ней. Поэтому Вы должны, вероятно, попросить у своего администратора MySQL разрешение использовать собственную базу данных. Предположите, что Вы хотите назвать ее menagerie. Администратор должен выполнить запрос:

mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';
здесь your_mysql_name это имя пользователя MySQL, назначенное Вам, а your_client_host это узел, от которого Вы соединяетесь с сервером.

4.3.1. Создание и выбор базы данных

Если администратор создает Вашу базу данных для Вас, настраивая Ваши разрешения, Вы можете начать использовать ее. Иначе Вы должны создать это непосредственно:

mysql> CREATE DATABASE menagerie;
В Unix имена баз данных являются чувствительными к регистру (в отличие от ключевых слов SQL), таким образом, Вы должны всегда обращаться к своей базе данных как к menagerie, но не Menagerie, MENAGERIE или еще как-то. Это также истина для имен таблиц. Под Windows не применяется это ограничение, хотя Вы должны обратиться к базам данных и таблицам, используя тот же самый регистр символов всюду по данному запросу. Однако, по множеству причин, рекомендуемая передовая практика это всегда использовать тот же самый регистр, который использовался, когда база данных создавалась.

Если Вы получаете такую ошибку, как ERROR 1044 (42000): Access denied for user 'micah'@'localhost' to database 'menagerie' , пытаясь создать базу данных, это означает, что у Вашей учетной записи пользователя нет необходимых привилегий. Обсудите это с администратором или см. раздел 7.2.

Создание базы данных не выбирает ее для использования, Вы должны сделать это явно. Чтобы сделать menagerie текущей базой данных, используйте этот запрос:

mysql> USE menagerie
Database changed
Ваша база данных должна быть создана только однажды, но Вы должны выбрать ее для использования каждый раз, когда Вы начинаете сессию mysql. Вы можете сделать это, выполняя USE. Альтернативно, Вы можете выбрать базу данных в командной строке, когда Вы вызываете mysql . Только определите имя после любых параметров соединения, которые Вы, возможно, должны были бы обеспечить. Например:
shell> mysql -h host -u user -p menagerie
Enter password: ********

menagerie в этой команде не Ваш пароль. Если Вы хотите поставлять свой пароль в командной строке после -p, Вы должны сделать так без пробела (например, как -pmypassword, а не -p mypassword). Однако, помещение Вашего пароля в командной строке не рекомендуется, потому что выполнение это выставляет его на всеобщее обозрение другими пользователями на Вашей машине.

Вы можете видеть в любое время, какая база данных в настоящее время выбирается, используя SELECT DATABASE().

4.3.2. Составление таблицы

Создание базы данных является легкой частью, но в этом пункте ее пока нет, как показывает 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 до 65535, независимо от того, что кажется самым разумным Вам. Если Вы делаете короткий столбец и оказывается позже, что Вы нуждаетесь в более длинной области, 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 в любое время, например, если Вы забываете названия столбцов в Вашей таблице или типы, которые они имеют.

4.3.3. Загрузка данных в таблицу

После составления Вашей таблицы Вы должны заполнить ее. LOAD DATA и INSERT полезны для этого.

Предположите, что Ваши любимые записи могут быть описаны как показано здесь. Заметьте, что MySQL ожидает даты в формате 'YYYY-MM-DD', это может отличаться от того, к чему Вы привыкли.

nameowner speciessex birthdeath
FluffyHaroldcatf 1993-02-04
ClawsGwencatm 1994-03-17
BuffyHarolddogf 1989-05-13
FangBennydogm 1990-08-27
BowserDianedogm 1979-08-311995-07-29
ChirpyGwenbirdf 1998-09-11
WhistlerGwenbird 1997-12-09
SlimBennysnakem 1996-04-29

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

Вы можете создать текстовый файл pet.txt, содержащий один запись на строку со значениями, отделенными табуляцией, в том порядке, в котором столбцы были перечислены в CREATE TABLE. Для того, чтобы пропустить значения (такие как неизвестный пол или дату смерти для животных, которые все еще живут), Вы можете использовать NULL. Чтобы представить их в Вашем текстовом файле, надо использовать \N (backslash, capital-N). Например, запись для птицы Whistler была бы похожа на это (где пробел между значениями это единственный символ табуляции):

Whistler Gwen bird \N 1997-12-09 \N
Загрузить текстовый файл pet.txt в таблицу pet можно так:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
Если Вы создали файл в Windows редактором, который использует \r\n как разделитель строк, Вы должны использовать этот запрос:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet
    ->      LINES TERMINATED BY '\r\n';
На Apple под OS X, Вы, вероятно, хотели бы использовать LINES TERMINATED BY '\r'.

Вы можете определить разделитель значения столбца и конец маркера строки явно в LOAD DATA, если Вы желаете, но значения по умолчанию являются табуляцией и переводом строки. Они достаточны для запроса, чтобы считать файл pet.txt.

Если запрос терпит неудачу, вероятно, что Вашей установке MySQL не включили местное чтение файла по умолчанию. См. раздел 7.1.6.

Когда Вы хотите добавить новые записи по одной, используйте запрос INSERT. В его самой простой форме Вы поставляете значения для каждого столбца, в том порядке, в котором столбцы были перечислены в CREATE TABLE . Предположите, что Диана получает нового хомяка, названного Puffball. Вы могли добавить новую запись, используя INSERT:

mysql> INSERT INTO pet
    ->        VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
Строки и значения даты определены как заключенные определены как заключенные в кавычки строки. Также с INSERT Вы можете вставить NULL непосредственно, чтобы представлять недостающее значение. Вы не используете \N как Вы делаете с LOAD DATA.

Из этого примера Вы должны быть в состоянии видеть, что было бы намного больше ввода, чтобы загрузить Ваши записи первоначально, используя несколько INSERT вместо LOAD DATA.

4.3.4. Получение информации от таблицы

SELECT используется, чтобы вытянуть информацию из таблицы. Общая форма запроса:

SELECT what_to_select FROM which_table
       WHERE conditions_to_satisfy;
what_to_select указывает на то, что Вы хотите видеть. Это может быть списком столбцов или *, чтобы указать все столбцы. which_table указывает на таблицу, от которой Вы хотите получить данные. WHERE является дополнительным. Если это присутствует, conditions_to_satisfy определяет одно или более условий, которым строки должны удовлетворить, чтобы иметь право на извлечение.

4.3.4.1. Выбор всех данных

Самая простая форма 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    | 1979-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 полезна, если Вы хотите рассмотреть всю таблицу, например, после того, как Вы только что загрузили ее своей группой исходных данных. Например, Вы думаете, что дата рождения Bowser не кажется правильной. Консультируясь с Вашей оригинальной родословной животного, Вы находите, что правильный год рождения должен быть 1989, а не 1979.

Есть по крайней мере два способа исправить это:

  • Отредактируйте файл pet.txt, чтобы исправить ошибку, освободите таблицу и перезагрузите ее с использованием DELETE и LOAD DATA:

    mysql> DELETE FROM pet;
    mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;
    
    Однако, если Вы делаете это, Вы должны также повторно ввести запись для Puffball.
  • Исправьте только ошибочную запись с помощью UPDATE:
    mysql> UPDATE pet SET birth = '1989-08-31'
                     WHERE name = 'Bowser';
    
    UPDATE изменяет только рассматриваемую запись и не требует, чтобы Вы перезагрузили таблицу.

4.3.4.2. Выбор особых строк

Как показано в предыдущем разделе, легко получить всю таблицу. Только опустите WHERE в 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, а не 1979.

Строковые сравнения обычно являются нечувствительными к регистру, таким образом, Вы можете определить имя как '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 могут быть смешаны, хотя 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  |
+-------+--------+---------+-----+------------+-------+

4.3.4.3. Выбор особых столбцов

Если Вы не хотите видеть все строки от своей таблицы, только называйте столбцы, которыми Вы интересуетесь, отделенные запятыми. Например, если Вы хотите знать, когда Ваши животные родились, выберите столбцы 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 |
+--------+---------+------------+

4.3.4.4. Сортировка строк

Вы, возможно, заметили в предыдущих примерах, что строки результата выведены на экран без определенного порядка. Часто легче исследовать вывод запроса, когда строки сортированы некоторым значащим способом. Чтобы сортировать результат, используйте 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 |
+----------+------------+
На символьных столбцах тип сортировки, как все другие операции сравнения, обычно выполняется нечувствительным к регистру. Это означает, что порядок неопределен для столбцов, которые идентичны за исключением их регистра. Вы можете вызвать чувствительный к регистру вид сортировки для столбца при использовании BINARY: ORDER BY BINARY col_name.

Порядок сортировки по умолчанию поднимается, с самыми маленькими значениями сначала. Для сортировки в обратном (убывающем) порядке, добавьте ключевое слово 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.

4.3.4.5. Вычисления даты

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

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

mysql> SELECT name, birth, CURDATE(),
    ->        TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age
    ->        FROM pet;
+----------+------------+------------+-----+
| name     | birth      | CURDATE()  | age |
+----------+------------+------------+-----+
| Fluffy   | 1993-02-04 | 2003-08-19 | 10  |
| Claws    | 1994-03-17 | 2003-08-19 |  9  |
| Buffy    | 1989-05-13 | 2003-08-19 |  14 |
| Fang     | 1990-08-27 | 2003-08-19 |  12 |
| Bowser   | 1989-08-31 | 2003-08-19 |  13 |
| Chirpy   | 1998-09-11 | 2003-08-19 |  4  |
| Whistler | 1997-12-09 | 2003-08-19 |  5  |
| Slim     | 1996-04-29 | 2003-08-19 |  7  |
| Puffball | 1999-03-30 | 2003-08-19 |  4  |
+----------+------------+------------+-----+
Запрос работает, но результат могли быть просмотрены более легко, если бы строки были представлены в некотором порядке. Это может быть сделано, добавляя ORDER BY name, чтобы сортировать вывод по имени:
mysql> SELECT name, birth, CURDATE(),
    ->        TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age
    ->        FROM pet ORDER BY name;
+----------+------------+------------+-----+
| name     | birth      | CURDATE()  | age |
+----------+------------+------------+-----+
| Bowser   | 1989-08-31 | 2003-08-19 |  13 |
| Buffy    | 1989-05-13 | 2003-08-19 |  14 |
| Chirpy   | 1998-09-11 | 2003-08-19 |  4  |
| Claws    | 1994-03-17 | 2003-08-19 |  9  |
| Fang     | 1990-08-27 | 2003-08-19 |  12 |
| Fluffy   | 1993-02-04 | 2003-08-19 |  10 |
| Puffball | 1999-03-30 | 2003-08-19 | 4   |
| Slim     | 1996-04-29 | 2003-08-19 | 7   |
| Whistler | 1997-12-09 | 2003-08-19 | 5   |
+----------+------------+------------+-----+
Чтобы отсортировать вывод по age вместо name, используйте различный ORDER BY:
mysql> SELECT name, birth, CURDATE(),
    ->        TIMESTAMPDIFF(YEAR, birth, CURDATE()) AS age
    ->        FROM pet ORDER BY age;
+----------+------------+------------+-----+
| name     | birth      | CURDATE()  | age |
+----------+------------+------------+-----+
| Chirpy   | 1998-09-11 | 2003-08-19 | 4   |
| Puffball | 1999-03-30 | 2003-08-19 | 4   |
| Whistler | 1997-12-09 | 2003-08-19 | 5   |
| Slim     | 1996-04-29 | 2003-08-19 | 7   |
| Claws    | 1994-03-17 | 2003-08-19 | 9   |
| Fluffy   | 1993-02-04 | 2003-08-19 | 10  |
| Fang     | 1990-08-27 | 2003-08-19 | 12  |
| Bowser   | 1989-08-31 | 2003-08-19 | 13  |
| Buffy    | 1989-05-13 | 2003-08-19 | 14  |
+----------+------------+------------+-----+
Подобный запрос может использоваться, чтобы определить возраст для животных, которые умерли. Вы определяете, какие это животные, проверяя, что death это NULL. Тогда, для животных со значениями не-NULL вычислите различие между death и birth:
mysql> SELECT name, birth, death,
    ->        TIMESTAMPDIFF(YEAR,birth,death) 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 это специальное значение, которое не может быть сравнено, используя обычные операторы сравнения. Это обсуждено позже. См. раздел 4.3.4.6.

Что, если Вы хотите знать, у каких животных есть дни рождения в следующем месяце? Для этого типа вычисления год и день не важны: Вы просто хотите извлечь часть месяца столбца birth. MySQL обеспечивает несколько функций для того, чтобы они извлекли части дат, например, YEAR(), MONTH() и DAYOFMONTH(). MONTH() как раз соответствующая функция здесь. Чтобы видеть, как это работает, выполните простой запрос, который выводит на экран значение 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            |
+----------+------------+--------------+
Обнаружение животных с днями рождения в наступающем месяце также просто. Предположите, что текущий месяц апрель. Тогда значение месяца 4 и Вы можете искать животных, родившихся в мае (месяц 5):
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name  | birth      |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
Есть маленькое осложнение, если текущий месяц декабрь. Вы не можете просто добавить единицу к числу месяца (12) и получить животных, родившихся в месяце 13, потому что нет такого месяца. Вместо этого Вы ищете животных, родившихся в январе (месяц 1).

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

mysql> SELECT name, birth FROM pet
    ->        WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
Другой способ выполнить ту же самую задачу состоит в том, чтобы добавить 1, чтобы получить следующий месяц после текущего после использования функции модуля (MOD), чтобы сделать значение месяца 0, если это в настоящее время 12:
mysql> SELECT name, birth FROM pet
    ->        WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
MONTH() возвращает число между 1 и 12. И MOD(something,12) возвращает число между 0 и 11. Таким образом, дополнение должно быть после MOD(), иначе мы пошли бы с ноября (11) в январь (1).

4.3.4.6. Работа с нулевыми значениями

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             |
+-----------+---------------+
Вы не можете использовать арифметические операторы сравнения, например, =, < или <>, чтобы проверить на NULL. Чтобы продемонстрировать это для вас непосредственно, попробуйте следующий запрос:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL     | NULL      | NULL     | NULL     |
+----------+-----------+----------+----------+
Поскольку результат любого арифметического сравнения с NULL тоже NULL, Вы не можете получить значащие следствия таких сравнений.

В MySQL 0 или NULL означает ложный, а что-либо еще означает истину. Значение true по умолчанию от логической операции 1.

Специальный режим NULL объясняет, почему в предыдущем разделе было необходимо определить, какие животные больше не живы, с использованием death IS NOT NULL вместо death <> NULL.

Два значения NULL расценены как равные в GROUP BY.

Делая ORDER BY, значения NULL представлены сначала, если Вы делаете ORDER BY ... ASC и последними для ORDER BY ... DESC.

Распространенная ошибка, работая с NULL, это предположить, что невозможно вставить ноль или пустую строку в столбец, определенный как NOT NULL, но дело обстоит не так. Они фактически значения, тогда как NULL значит нет значения вообще. Вы можете проверить это достаточно легко при использовании IS [NOT] NULL:

mysql> SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL;
+-----------+---------------+------------+----------------+
| 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL |
+-----------+---------------+------------+----------------+
| 0         | 1             |   0        |   1            |
+-----------+---------------+------------+----------------+
Таким образом полностью возможно вставить нулевое значение или пустую строку в столбец NOT NULL, так как они фактически и есть NOT NULL. См. раздел B.5.4.3.

4.3.4.7. Соответствие образцу

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).

Следующий список описывает некоторые характеристики расширенных регулярных выражений:

  • . соответствует любому единственному символу.

  • Символьный класс [...] соответствует любому символу в пределах скобок. Например, [abc] соответствует a, b или c. Чтобы назвать диапазон символов, используйте тире. [a-z] соответствует любой латинской букве, [0-9] любой цифре.
  • * соответствует нулю или больше экземпляров объекта, предшествующего этому. Например, x* соответствует любому числу символов x (возможно, 0), [0-9]* соответствует любому числу цифр, а .* соответствует любому количеству чего угодно.
  • Соответствие образца REGEXP преуспевает, если образец соответствует где-нибудь в проверяемом значении. Это отличается от LIKE , которое преуспевает, только если образец соответствует всему значению.
  • Чтобы поставить на якорь образец так, чтобы это соответствовало началу или концу проверяемого значения, надо использовать ^ для начала или $ в конце образца.

Чтобы продемонстрировать, как расширенные регулярные выражения работают, запросы 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 |
+--------+--------+---------+-----+------------+------------+
Если Вы действительно хотите, чтобы сравнение 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} (повторить n раз):
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  |
+-------+--------+---------+------+------------+-------+
См. раздел 13.5.2.

4.3.4.8. Подсчет строк

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

Подсчет общего количества животных, которых Вы имеете, является тем же самым вопросом как Сколько строк находится в таблице pet?, потому что есть одна запись на домашнее животное. COUNT(*) считает число строк, таким образом, запрос, чтобы посчитать Ваших животных похож на это:

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. Использование 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        |
+---------+-----+----------+
Если Вы называете столбцы, чтобы выбрать в дополнение к COUNT(), GROUP BY должен присутствовать, который называет те же самые столбцы. Иначе, следующее происходит:

  • Если включен режим SQL ONLY_FULL_GROUP_BY , то будет ошибка:

    mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT owner, COUNT(*) FROM pet;
    ERROR 1140 (42000): In aggregated query without GROUP BY, expression
    #1 of SELECT list contains nonaggregated column 'menagerie.pet.owner';
    this is incompatible with sql_mode=only_full_group_by
    
  • Если режим ONLY_FULL_GROUP_BY выключен, запрос обработан, обрабатывая все строки как единственную группу, но значение, выбранное для каждого названного столбца, неопределенно. Сервер свободен выбрать значение из любой строки:

    mysql> SET sql_mode = '';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT owner, COUNT(*) FROM pet;
    +--------+----------+
    | owner  | COUNT(*) |
    +--------+----------+
    | Harold | 8        |
    +--------+----------+
    1 row in set (0.00 sec)
    

См. раздел 13.19.3.

4.3.4.9. Используя больше, чем одну таблицу

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

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

  • Дата, чтобы Вы знали, когда событие имело место.
  • Область, чтобы описать событие.
  • Область типа событий, если Вы хотите быть в состоянии категоризировать события.

Запрос CREATE TABLE для таблицы event:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
    ->        type VARCHAR(15), remark VARCHAR(255));
Как с таблицей pet, является самым легким загрузить начальные записи, создавая разграниченный табуляциями текстовый файл, содержащий следующую информацию.

namedate typeremark
Fluffy1995-05-15litter 4 kittens, 3 female, 1 male
Buffy1993-06-23litter 5 puppies, 2 female, 3 male
Buffy1994-06-19litter 3 puppies, 3 female
Chirpy1999-03-21vet needed beak straightened
Slim1997-08-03vetbroken rib
Bowser1991-10-12kennel
Fang1991-10-12kennel
Fang1998-08-28birthday Gave him a new chew toy
Claws1998-03-17birthday Gave him a new flea collar
Whistler1998-12-09birthday First birthday

Загрузите записи так:

mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;
Основываясь на том, что Вы узнали из запросов из таблицы pet, Вы должны быть в состоянии выполнить извлечения на записях в event, принципы те же самые.

Предположите, что Вы хотите узнать возрасты, в которых у каждого домашнего животного был детеныш. Мы видели ранее, как вычислить возрасты с двух дат. Дата появления детеныша находится в таблице event, но надо вычислить возраст матери на ту дату, Вы нуждаетесь в ее дате рождения, которая сохранена в таблице pet. Это означает, что запрос требует обеих таблиц:

mysql> SELECT pet.name,
    ->        TIMESTAMPDIFF(YEAR,birth,date) AS age,
    ->        remark FROM pet INNER JOIN event
    ->        ON pet.name = event.name
    ->        WHERE event.type = 'litter';
+--------+-----+-----------------------------+
| name   | age | remark                      |
+--------+-----+-----------------------------+
| Fluffy | 2   | 4 kittens, 3 female, 1 male |
| Buffy  | 4   | 5 puppies, 2 female, 3 male |
| Buffy  | 5   | 3 puppies, 3 female         |
+--------+-----+-----------------------------+
Есть несколько вещей, которые надо отметить об этом запросе:

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

  • Комбинируя присоединяющуюся информацию от многократных таблиц, Вы должны определить, как записи в одной таблице могут быть соответствующими записям в другой. Это легко, потому что у них обоих есть столбец name. Запрос использует ON, чтобы связать записи в этих двух таблицах, основываясь на значениях name.

    Запрос использует INNER JOIN, чтобы объединить таблицы. INNER JOIN разрешает строкам от любой таблицы появиться в результате, если и только если обе таблицы удовлетворяют условиям, определенным в ON. В этом примере ON определяет, что столбец name в таблице pet должен соответствовать столбцу name в таблице event. Если имя появится в одной таблице, но не в другой, то строка не будет появляться в результате потому, что условие в ON не выполнено.

  • Поскольку столбец name в обеих таблицах, Вы должны быть определенными, которую таблицу имеете в виду, обращаясь к столбцу. Это сделано, добавляя имя таблицы к имени столбца.

У Вас не должно быть двух различных таблиц, чтобы выполнить соединение. Иногда полезно соединить таблицу с собой, если Вы хотите сравнить записи в таблице с другими записями в той же самой таблице. Например, чтобы найти родительские пары среди Ваших домашних животных, Вы можете присоединить таблицу pet с собой, чтобы произвести пары подобных разновидностей:

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
    ->        FROM pet AS p1 INNER JOIN pet AS p2
    ->        ON 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     |
+--------+-----+--------+-----+---------+
В этом запросе мы определяем псевдонимы для имени таблицы, чтобы обратиться к столбцам и сохранить прямо, с каким случаем таблицы каждая ссылка столбца связана.

4.4. Получение информации о базах данных и таблицах

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

Вы ранее видели SHOW DATABASES , который перечисляет базы данных, которыми управляет сервер. Чтобы узнать, какая база данных в настоящее время выбрана, используйте DATABASE():

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+
Если Вы еще не выбрали базу данных, результат NULL.

Чтобы знать, что какие таблицы включает база данных по умолчанию (например, когда Вы не уверены в названии таблицы), используйте этот запрос:

mysql> SHOW TABLES;
+---------------------+
| Tables_in_menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+
Название столбца в выводе, произведенном этим запросом, всегда Tables_in_db_name, где db_name это название базы данных. См. раздел 14.7.5.37.

Если Вы хотите узнать о структуре таблицы, используйте 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 определяет значение по умолчанию столбца. Extra отображает специальную информацию о столбцах: если столбец создавался с AUTO_INCREMENT, значение будет auto_increment .

DESC это краткая форма DESCRIBE. См. раздел 14.8.1.

Вы можете получить запрос CREATE TABLE, необходимый, чтобы составить существующую таблицу, используя SHOW CREATE TABLE, см. раздел 14.7.5.10.

Если Вы имеете индексы на таблице, SHOW INDEX FROM tbl_name производит информацию о них. См. раздел 14.7.5.22.

4.5. Используя mysql в пакетном режиме

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

shell> mysql < batch-file
Если Вы выполняете mysql в Windows и имеете некоторые специальные символы в файле, которые вызывают проблемы, Вы можете сделать это:
C:\> mysql -e "source batch-file"
Если Вы должны определить параметры соединения в командной строке, команда могла бы быть похожей на это:
shell> mysql -h host -u user \
                   -p < batch-file
Enter password: ********
Когда Вы используете mysql этим путем, Вы создаете файл скрипта, затем выполняя скрипт.

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

Почему используется скрипт? Вот несколько причин:

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

  • Вы можете произвести новые запросы от существующих, которые подобны, копируя и редактируя файлы скриптов.
  • Пакетный режим может также быть полезным в то время как, Вы развиваете запрос, особенно для многострочных запросов или последовательностей запросов. Если Вы делаете ошибку, Вы не должны перепечатать все. Только отредактируйте свой скрипт, чтобы исправить ошибку, затем скажите mysql выполнять это снова.
  • Если у Вас есть запрос, который производит большой вывод, Вы можете выполнить вывод через пейджер:
    shell> mysql < batch-file | more
    
  • Вы можете поймать вывод в файл для дальнейшей обработки:

    shell> mysql < batch-file > mysql.out
    
  • Вы можете дать свой скрипт другим людям так, чтобы они могли также выполнить запросы.

  • Некоторые ситуации не учитывают интерактивное использование, например, когда Вы выполняете запрос через cron. В этом случае Вы должны использовать пакетный режим.

Выходной формат по умолчанию отличается (более краткий), когда Вы выполняете mysql в пакетном режиме от того, когда Вы используете это в интерактивном режиме. Например, вывод SELECT DISTINCT species FROM pet похож на это, когда mysql выполнен в интерактивном режиме:

+---------+
| species |
+---------+
| bird    |
| cat     |
| dog     |
| hamster |
| snake   |
+---------+
В пакетном режиме вывод похож на это:
species
bird
cat
dog
hamster
snake
Если Вы хотите получить интерактивный выходной формат в пакетном режиме, используйте mysql -t . Чтобы добавить к выводу запросы, которые выполнены, используют mysql -v.

Вы можете также использовать скрипты из подсказки mysql с помощью команд source или \.:

mysql> source filename;
mysql> \. filename
См. раздел 5.5.1.5.

4.6. Примеры общих запросов

Вот примеры того, как решить некоторые типичные проблемы с MySQL.

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

Запустите инструмент командной строки mysql и выберите базу данных:

shell> 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);
После выполнения запросов у таблицы должно быть следующее содержание:
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 |
+---------+--------+-------+

4.6.1. Максимальное значение для столбца

Каков самый большой номер изделия?

SELECT MAX(article) AS article FROM shop;
+---------+
| article |
+---------+
| 4       |
+---------+

4.6.2. Строка, содержащая максимум для определенного столбца

Задача: Найдите число, дилера, и цену самого дорогого артикула .

Это легко сделано с подзапросом:

SELECT article, dealer, price FROM shop
       WHERE price=(SELECT MAX(price) FROM shop);
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0004    | D      | 19.95 |
+---------+--------+-------+
Другие решения состоят в том, чтобы использовать LEFT JOIN или отсортировать все убывание строк по цене и получить только первую строку, используя MySQL-определенный параметр LIMIT:
SELECT s1.article, s1.dealer, s1.price FROM shop s1
       LEFT JOIN shop s2 ON s1.price < s2.price
       WHERE s2.article IS NULL;
SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1;

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

4.6.3. Максимум столбца на группу

Задача: Найдите самую высокую цену за артикул.

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 |
+---------+-------+

4.6.4. Строки, содержащие максимум определенного столбца в группе

Задача: Для каждого артикула найдите дилера или дилеров с самой высокой ценой.

Эта проблема может быть решена с подзапросом:

SELECT article, dealer, price FROM shop s1
       WHERE price=(SELECT MAX(s2.price) FROM shop s2
       WHERE s1.article = s2.article);
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001    | B      |  3.99 |
| 0002    | A      | 10.99 |
| 0003    | C      |  1.69 |
| 0004    | D      | 19.95 |
+---------+--------+-------+
Предыдущий пример использует коррелированый подзапрос, который может быть неэффективным (см. раздел 14.2.10.7 ). Другие возможности для того, чтобы решить проблему состоят в том, чтобы использовать некоррелированый подзапрос в FROM или LEFT JOIN.

Некоррелированый подзапрос:

SELECT s1.article, dealer, s1.price FROM shop s1
       JOIN (SELECT article, MAX(price) AS price FROM shop
             GROUP BY article) AS s2
       ON s1.article = s2.article AND s1.price = s2.price;
LEFT JOIN:
SELECT s1.article, s1.dealer, s1.price FROM shop s1
       LEFT JOIN shop s2 ON s1.article = s2.article AND
       s1.price < s2.price WHERE s2.article IS NULL;
LEFT JOIN работает на основе того что, когда s1.price в его максимальном значении, нет s2.price с большим значением и значения строк s2 будут NULL. См. раздел 14.2.9.2.

4.6.5. Используя определяемые пользователем переменные

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

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

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0003    | D      |  1.25 |
| 0004    | D      | 19.95 |
+---------+--------+-------+

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

4.6.6. Используя внешние ключи

В MySQL таблицы InnoDB поддерживают ограничения внешнего ключа. См. главу 16 и раздел 1.8.2.3.

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

  • MySQL не выполняет проверку CHECK, чтобы удостовериться, что col_name фактически существует в tbl_name (или даже что tbl_name непосредственно существует).

  • MySQL не выполняет такие действия на tbl_name, как удаление строк в ответ на действия со строками в таблице, которую Вы определяете, другими словами, этот синтаксис не вызывает ON DELETE или ON UPDATE вообще. Хотя Вы можете написать ON DELETE или ON UPDATE как часть REFERENCES, это также проигнорировано.
  • Этот синтаксис создает столбец, это не создает индекс или ключ.

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

CREATE TABLE person (id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
                     name CHAR(60) NOT NULL,
                     PRIMARY KEY (id));

CREATE TABLE shirt (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 person(id),
       PRIMARY KEY (id));

INSERT INTO person VALUES (NULL, 'Antonio Paz');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES (NULL, 'polo', 'blue', @last),
                         (NULL, 'dress', 'white', @last),
                         (NULL, 't-shirt', 'blue', @last);

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES (NULL, 'dress', 'orange', @last),
                         (NULL, 'polo', 'red', @last),
                         (NULL, 'dress', 'blue', @last),
                         (NULL, 't-shirt', 'white', @last);

SELECT * FROM person;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | Antonio Paz         |
|  2 | Lilliana Angelovska |
+----+---------------------+

SELECT * FROM shirt;
+----+---------+--------+-------+
| 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 person p INNER JOIN shirt s ON s.owner = p.id
       WHERE p.name LIKE 'Lilliana%' AND
       s.color <> 'white';

+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange | 2     |
|  5 | polo  | red    | 2     |
|  6 | dress | blue   | 2     |
+----+-------+--------+-------+
Когда используется этим способом, REFERENCES не выведен на экран в выводе SHOW CREATE TABLE или DESCRIBE :
SHOW CREATE TABLE shirt\G
*************************** 1. row ***************************
Table: shirt
Create Table: CREATE TABLE `shirt` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`style` enum('t-shirt','polo','dress') NOT NULL,
`color` enum('red','blue','orange','white','black') NOT NULL,
`owner` smallint(5) unsigned NOT NULL,
PRIMARY KEY  (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1
Использование REFERENCES таким образом как комментарий или напоминание в определении столбца работает с таблицами MyISAM.

4.6.7. Поиск на двух ключах

OR с использованием единственного ключа хорошо оптимизировано, как обработка AND.

Один хитрый случай это случай поиска на двух различных ключах, объединенных с OR:

SELECT field1_index, field2_index FROM test_table
       WHERE field1_index = '1' OR  field2_index = '1'
Этот случай оптимизирован. См. раздел 9.2.1.4.

Вы можете также решить проблему эффективно при использовании UNION, это комбинирует вывод двух отдельных SELECT. См. раздел 14.2.9.3.

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

SELECT field1_index, field2_index
       FROM test_table WHERE field1_index = '1'
       UNION SELECT field1_index, field2_index
       FROM test_table WHERE field2_index = '1';

4.6.8. Вычисление посещений в день

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

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    |
+------+-------+------+
Запрос вычисляет, сколько различных дней появляется в таблице для каждой комбинации года/месяца, с автоматическим удалением двойных записей.

4.6.9. Использование AUTO_INCREMENT

Атрибут AUTO_INCREMENT может использоваться, чтобы произвести уникальную идентичность для новых строк:

CREATE TABLE animals (id MEDIUMINT NOT NULL AUTO_INCREMENT,
       name CHAR(30) NOT NULL, PRIMARY KEY (id));
INSERT INTO animals (name) VALUES ('dog'),('cat'),('penguin'),
                                  ('lax'),('whale'),('ostrich');
SELECT * FROM animals;
Результат примерно такой:
+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+
Никакое значение не было определено для столбца AUTO_INCREMENT, таким образом, MySQL назначал порядковые номера автоматически. Вы можете также явно назначить 0 столбцу, чтобы производить порядковые номера, если включен режим SQL NO_AUTO_VALUE_ON_ZERO. Если столбец объявлен как NOT NULL, также возможно назначить NULL к столбцу, чтобы произвести порядковые номера. Когда Вы вставляете любое другое значение в AUTO_INCREMENT, столбец установлен в то значение, и последовательность сброшена так, чтобы следующее автоматически произведенное значение следовало последовательно от самого большого значения столбца.

Вы можете получить новое, автоматически произведенное значение AUTO_INCREMENT с помощью функции SQL LAST_INSERT_ID() или функции C API mysql_insert_id(). Эти функции являются определенными для соединения, таким образом, их возвращаемые значения не затронуты другим соединением, которое также вставляет.

Используйте самый маленький тип данных целого числа для AUTO_INCREMENT, который является достаточно большим, чтобы содержать максимальное значение последовательности, в котором Вы будете нуждаться. Когда столбец достигает верхнего предела типа данных, следующая попытка произвести порядковый номер терпит неудачу. Используйте атрибут UNSIGNED, если возможно, чтобы позволить больший диапазон. Например, если Вы используете TINYINT, максимальный допустимый порядковый номер 127. Для TINYINT UNSIGNED максимум 255. См. раздел 12.2.1.

Для многострочных вставок LAST_INSERT_ID() и mysql_insert_id() фактически возвратят AUTO_INCREMENT от первой из вставленных строк. Это позволяет многострочной вставке быть воспроизведенной правильно на других серверах в репликации.

Чтобы AUTO_INCREMENT стартовала не с 1, установите то значение с CREATE TABLE или ALTER TABLE :

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;

InnoDB

Для информации о AUTO_INCREMENT с InnoDB см. раздел 16.8.5.

MyISAM

  • Для таблиц MyISAM Вы можете определить AUTO_INCREMENT на втором столбце в многостолбцовом индексе. В этом случае произведенное значение для AUTO_INCREMENT вычислено как MAX( auto_increment_column) + 1 WHERE prefix=given-prefix . Это полезно, когда Вы хотите поместить данные в упорядоченные группы.

    CREATE TABLE animals (grp ENUM('fish','mammal','bird') NOT NULL,
                          id MEDIUMINT NOT NULL AUTO_INCREMENT,
                          name CHAR(30) NOT NULL,
                          PRIMARY KEY (grp,id)) ENGINE=MyISAM;
    
    INSERT INTO animals (grp,name) VALUES
           ('mammal','dog'),('mammal','cat'),
           ('bird','penguin'),('fish','lax'),('mammal','whale'),
           ('bird','ostrich');
    SELECT * FROM animals ORDER BY grp,id;
    
    Это в итоге вернет:
    +--------+----+---------+
    | grp    | id | name    |
    +--------+----+---------+
    | fish   |  1 | lax     |
    | mammal |  1 | dog     |
    | mammal |  2 | cat     |
    | mammal |  3 | whale   |
    | bird   |  1 | penguin |
    | bird   |  2 | ostrich |
    +--------+----+---------+
    
    В этом случае (когда столбец AUTO_INCREMENT часть многостолбцового индекса) значения AUTO_INCREMENT снова использованы, если Вы удаляете строку с самым большим AUTO_INCREMENT в любой группе. Это происходит даже для таблиц MyISAM, для которых AUTO_INCREMENT обычно снова не используются.
  • Если столбец AUTO_INCREMENT часть многих индексов, MySQL производит значения последовательности, используя индексирование, которое начинается со столбца AUTO_INCREMENT, если такое есть. Например, если таблица animals имеет индексы PRIMARY KEY (grp, id) и INDEX (id), MySQL проигнорировал бы PRIMARY KEY для того, чтобы произвести значения последовательности. В результате таблица содержала бы единственную последовательность не по grp.

Что еще почитать

Больше информации о AUTO_INCREMENT доступно здесь:

4.7. Применение MySQL и Apache

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

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

LogFormat \
   "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\",  \
   \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
Чтобы загрузить файл системного журнала в этом формате в MySQL, Вы можете использовать запрос вроде этого:
LOAD DATA INFILE '/local/access_log'
     INTO TABLE tbl_name
     FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
Названная таблица должна быть составлена, чтобы иметь столбцы, которые соответствуют тем, которые строка LogFormat пишет в файл системного журнала.

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru