Название книги в оригинале: Гольцман Виктор. MySQL 5.0. Библиотека программиста

A- A A+ White background Book background Black background

На главную » Гольцман Виктор » MySQL 5.0. Библиотека программиста.





Читать онлайн MySQL 5.0. Библиотека программиста. Гольцман Виктор.

Виктор Гольцман

MySQL 5.0. Библиотека программиста

 Сделать закладку на этом месте книги

Введение

 Сделать закладку на этом месте книги

MySQL – это система управления базами данных (СУБД) с открытым кодом. Это высокопроизводительная и масштабируемая СУБД с множеством программных интерфейсов. Она обладает огромными функциональными возможностями и подходит для решения самых разных задач.

Данная книга предназначена для всех, кто желает освоить MySQL. Чтобы начать работу, вам не потребуется никаких специальных знаний – достаточно быть пользователем Windows. Вы узнаете, как установить и запустить MySQL, как построить, администрировать собственную базу данных и оптимизировать ее работу. Вы также узнаете, как работать с данными с помощью команд языка SQL. Разработчики веб-приложений на языках PHP, Perl и Java найдут в этой книге руководство по использованию базы данных MySQL в соответствующих приложениях. В книге приводятся подробные пошаговые инструкции по выполнению всех операций. Кроме того, все основные действия поясняются на примере учебной базы данных, содержащей информацию о клиентах, товарах и заказах торговой компании. Книга состоит из шести глав.

•  Глава 1. Знакомство. Данная глава содержит общую информацию о СУБД MySQL, начальные сведения о реляционных базах данных и этапах проектирования базы данных. Кроме того, в главе подробно описываются установка, настройка и запуск сервера MySQL, а также подключение к нему клиентских приложений.

•  Глава 2. Управление базой данных с помощью SQL. Глава посвящена SQL-командам, обеспечивающим работу с таблицами и их данными. Изучив эту главу, вы сможете управлять структурой таблиц, добавлять, редактировать и получать данные.

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

•  Глава 4. Доступ к базе данных из веб-приложений. Глава содержит три раздела, в которых рассматриваются интерфейсы MySQL с языками программирования PHP, Perl и Java. В каждом из разделов описываются функции подключения к базе данных, ввод и извлечение данных, обработка ошибок взаимодействия с БД, а также примеры веб-приложений, использующих эти функции.

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

•  Глава 6. Оптимизация. В заключительной главе приводятся рекомендации по повышению производительности сервера MySQL.

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

От главы коллектива авторов

Высказать замечания и пожелания, задать вопросы по этой книге вы можете по адресу [email protected] или посетив нашу домашнюю страничку www.sigmaplus.mcdir.ru (там вы найдете также дополнительные материалы по книге, сможете принять участие в форуме или пообщаться в чате).

Александр Жадаев  От издательства

Ваши замечания, предложения и вопросы отправляйте по адресу электронной почты [email protected] (издательство «Питер», компьютерная редакция).

Мы будем рады узнать ваше мнение!

На сайте издательства https://www.piter.com вы найдете подробную информацию о наших книгах.

Глава 1 Знакомство

 Сделать закладку на этом месте книги

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

1.1. Что такое MySQL

 Сделать закладку на этом месте книги

MySQL – это свободно распространяемая СУБД, разработанная компанией MySQL AB (www.mysql.com). MySQL имеет клиент-серверную архитектуру: к серверу MySQL могут обращаться различные клиентские приложения, в том числе с удаленных компьютеров. Рассмотрим важнейшие особенности MySQL, благодаря которым эта программа приобрела популярность.

• MySQL – это СУБД с открытым кодом. Любой желающий может бесплатно скачать программу на сайте разработчика (https://dev.mysql.com/downloads/) и при необходимости доработать ее. Существует множество приложений MySQL, созданных и свободно распространяемых сторонними разработчиками. Однако для применения MySQL в коммерческом приложении необходимо приобрести коммерческую лицензированную версию программы у компании MySQL AB.

• MySQL – кроссплатформенная система. Ее можно использовать практически во всех современных операционных системах, в том числе Windows, Linux, Mac OS, Solaris, HP-UX и др. В этой книге мы рассмотрим работу с MySQL только в ОС Windows.

• MySQL имеет множество программных интерфейсов (API), благодаря которым к базе данных MySQL могут подключаться приложения, созданные с помощью C/C++, Eiffel, Java, Perl, PHP, Python, Tcl, ODBC, NET и Visual Studio. В главе 4 вы узнаете, как обращаться к базе данных MySQL из PHP-, Perl– и Java-приложений.

• MySQL имеет отличные технические характеристики: многопоточность, многопользовательский доступ, быстродействие, масштабируемость (компания-разработчик приводит пример MySQL-сервера, который работает с 60 тыс. таблиц, содержащими приблизительно 5 млрд строк).

• MySQL имеет развитую систему обеспечения безопасности и разграничения доступа на основе системы привилегий (гл. 5).

MySQL представляет собой реляционную СУБД, то есть систему управления реляционными базами данных. Поэтому для построения базы данных в MySQL нам потребуются базовые понятия теории реляционных баз данных. Этим понятиям посвящается следующий раздел.

1.2. Основные сведения о реляционных базах данных

 Сделать закладку на этом месте книги

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

Таблицы

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

Рассмотрим таблицу, содержащую сведения о клиентах компании (табл. 1.1).

Таблица 1.1.

Customers (Клиенты)



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

Каждый столбец таблицы имеет имя и тип данных,  которому соответствуют все значения в столбце. Так, в нашем примере столбцы с именами id и rating – числовые, а с именами name, phone и address – символьные.

По существу, таблица реляционной базы данных представляет собой набор информации об однотипных объектах. При этом каждая строка содержит сведения об одном объекте, а каждый столбец – значения некоторого атрибута этих объектов. Например, строка с идентификационным номером 533 содержит информацию об объекте, у которого атрибут name (имя) имеет значение ООО «Кускус», атрибут phone (телефон) – значение 313-48-48 и т. д.

Далее мы рассмотрим специальные столбцы таблицы – первичный и внешний ключи.

Первичный ключ

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

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

На практике первичным ключом служит специальный столбец, значения которого автоматически задает СУБД. Например, в таблице Customers (Клиенты) (см. табл 1.1) это столбец id (идентификатор). Использовать такой искусственный первичный ключ значительно проще, чем естественный (основанный на атрибутах объекта). Например, в таблице Customers столбец name (имя) не может быть первичным ключом, так как имена клиентов могут совпадать; а первичный ключ из столбцов name (имя) и phone (телефон) был бы слишком громоздким. Дополнительными преимуществами искусственного ключа являются гарантированная уникальность значений (ее обеспечивает СУБД), постоянство значений (может меняться значение атрибута, но не значение искусственного ключа), а также числовой тип данных (поиск по числовым значениям выполняется намного быстрее, чем по символьным).

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

Связи между таблицами. Внешний ключ

Реляционная база данных – это не просто набор таблиц. Объединить разрозненные фрагменты информации в единую структуру данных позволяют связи  между таблицами, посредством которых строка одной таблицы сопоставляется строке (строкам) другой таблицы. Благодаря связям можно извлекать информацию одновременно из нескольких таблиц (например, выводить с помощью одного запроса и сведения о клиенте, и сведения о его заказах), избегать дублирования информации (не требуется в каждом заказе хранить адрес клиента), поддерживать полноту информации (не хранить сведения о заказанном товаре, если в базе данных отсутствует его описание) и многое другое.

Рассмотрим на примере, что такое связь между таблицами. Допустим, у нас есть таблицы A  и B,  и мы хотим их связать. Для этого в каждую строку таблицы A  мы должны поместить некую информацию, позволяющую идентифицировать связанную с ней строку таблицы B. Эта информация называется ссылкой,  а поля таблицы A,  содержащие эту ссылку, – внешними ключами.  Наверное, вы уже сами догадались, что в качестве ссылки используется первичный ключ таблицы B,  поскольку именно его значения позволят однозначно идентифицировать нужную строку таблицы B.  После того как мы во все строки таблицы A  поместим ссылки на строки таблицы B, эти таблицы будут связаны. При этом таблица A  будет называться дочерней,  а таблица B – родительской.  

Существует три типа связей, устанавливаемых между таблицами в базе данных.

• Связь «один ко многим».

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

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

Рассмотрим таблицу, которая содержит сведения о заказах, сделанных клиентами, и является дочерней по отношению к таблице Customers (Клиенты) (табл. 1.2).

Таблица 1.2.

Orders (Заказы)



В таблице Orders внешним ключом является столбец customer_id (клиент), в котором содержатся номера клиентов из таблицы Customers (Клиенты). Таким образом, каждая строка таблицы Orders ссылается на одну из строк таблицы Customers. Например, строка с идентификационным номером 1012 содержит в столбце customer_id (клиент) значение 533: это означает, что заказ № 1012 сделан клиентом ООО «Кускус».

Столбец product_id таблицы Orders также является внешним ключом – он содержит номера товаров из столбца id (идентификатор) таблицы Products (Товары). Таким образом, таблица Orders является дочерней по отношению к таблицам Customers и Products.

• Связь «один к одному».

Такая связь между таблицами означает, что каждой строке одной таблицы соответствует одна строка другой таблицы, и наоборот. Например, если требуется хранить паспортные данные клиентов, можно создать таблицу Passports (Паспорта), связанную отношением «один к одному» с таблицей Customers (Клиенты).

Таблицы, соединенные связью «один к одному», можно объединить в одну. Две таблицы вместо одной используют по соображениям конфиденциальности (например, можно ограничить доступ пользователей к таблице Passports), для удобства (если в единой таблице слишком много столбцов), для экономии дискового пространства (в дополнительную таблицу выносят те столбцы, которые часто бывают пустыми, тогда дополнительная таблица содержит значительно меньше строк, чем основная, и обе они занимают меньше места, чем единая таблица).

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

• Связь «многие ко многим».

Этот тип связи в реляционной базе данных реализуется только с помощью вспомогательной таблицы. Например, если потребуется включить в заказ несколько наименований товаров, связь «многие ко многим» между таблицами Orders (Заказы) и Products (Товары) можно организовать с помощью вспомогательной таблицы Items (Позиции заказа), содержащей столбцы product_ id (номер товара из таблицы Products), qty (количество товаров данного наименования в заказе) и order_id (номер заказа из таблицы Orders). При этом столбцы product_id и qty из таблицы Orders исключаются. Таким образом, таблица Items будет дочерней по отношению к таблицам Orders и Products и каждая строка таблицы Items будет соответствовать одному наименованию товара в заказе.

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

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

Целостность данных

Целостностью данных,  хранимых в СУБД, называется их корректность и непротиворечивость.

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

Целостность сущностей означает, что в каждой таблице есть первичный ключ – уникальный идентификатор строки. Первичный ключ не должен содержать повторяющихся и неопределенных значений. Например, если в таблицу Customers (Клиенты) добавить еще одну строку с идентификатором 533 (притом что одна строка с таким идентификатором уже существует в таблице), то целостность сущностей будет нарушена и невозможно будет определить, кому из этих двух клиентов с одинаковыми идентификаторами принадлежат заказы №№ 1012 и 1014.

Целостность связей означает, что внешний ключ в дочерней таблице не содержит значения, отсутствующие в первичном ключе родительской таблицы. Иными словами, строка дочерней таблицы не должна ссылаться на несуществующую строку родительской таблицы. В отличие от первичного, внешний ключ может содержать неопределенные значения (NULL), и в этом случае целостность не нарушится. Например, в таблицу Orders (Заказы) добавлена строка, содержащая в столбце customer_id значение 999. Здесь нарушится целостность связи между таблицами Customers и Orders: с одной стороны, заказ не является «ничьим», так как в этом случае в столбце customer_id было бы установлено значение NULL, с другой стороны, невозможно выяснить имя и адрес клиента, сделавшего этот заказ.

Как видно из приведенных примеров, если целостность данных нарушена, то с ними невозможно нормально работать. Поэтому поддержание целостности данных является одной из основных функций любой СУБД.

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

• Запрет (RESTRICT): если на строку родительской таблицы ссылается хотя бы одна строка дочерней таблицы, то удаление родительской строки и изменение значения первичного ключа в такой строке запрещаются. Например, не допускается удаление информации о клиенте из таблицы Customers (Клиенты), если у этого клиента есть зарегистрированные заказы, то есть строки в таблице Orders (Заказы), которые ссылаются на строку со сведениями об этом клиенте.

• Каскадное удаление/обновление (CASCADE): при удалении строки из родительской таблицы автоматически удаляются все ссылающиеся на нее строки дочерней таблицы; при изменении значения первичного ключа в строке родительской таблицы автоматически обновляется значение внешнего ключа в ссылающихся на нее строках дочерней таблицы.

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

• Обнуление (SET NULL): при удалении строки и при изменении значения первичного ключа в строке значение внешнего ключа во всех строках, ссылающихся на данную, автоматически становится неопределенным (NULL). Например, при удалении записи о клиенте из таблицы Customers (Клиенты) заказы этого клиента автоматически становятся «ничьими», то есть в соответствующих строках таблицы Orders (Заказы) в столбце customer_id (клиент) устанавливается значение NULL.

В СУБД MySQL способ поддержания целостности связи указывается при создании или изменении структуры дочерней таблицы.

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

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

1.3. Проектирование базы данных

 Сделать закладку на этом месте книги

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

Проектирование включает в себя следующие основные этапы.

• Определение требований к базе данных.

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

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

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

• Проектирование «снизу вверх», от элемента к структуре: вначале определяется, какие именно атрибуты должны храниться в базе данных, затем группы атрибутов объединяются в объекты. Этот метод годится для небольших баз данных, в которых количество атрибутов невелико.

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

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

• Для клиентов: идентификатор, имя (или название организации), номер контактного телефона, адрес, а также рейтинг, используемый для расчета скидки.

• Для товаров: идентификатор, наименование, описание, название склада, где хранится этот вид товара, и адрес склада.

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

• Нормализация.

Нормализация базы данных заключается в минимизации избыточности данных. Нормализация позволяет уменьшить объем БД и устранить потенциальную противоречивость данных (например, если в базе данных одна и та же информация дублируется в нескольких местах, то при ее обновлении есть риск появления разночтений).

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

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

Ответ на вопрос, является ли атрибут атомарным, зависит от функциональных требований к базе данных. Рассмотрим, например, столбец address (адрес) из таблицы Customers (Клиенты) (см. табл. 1.1). Если адрес клиента будет использоваться только целиком, то этот столбец является атомарным. Если же потребуется получать из базы отдельно название города, улицы и т. п., то для приведения таблицы Customers к первой нормальной форме столбец address следует разбить на столбцы city (город), street (улица), building (здание) и т. д.

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

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

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


...

Примечание

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

 

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

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

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

Итак, мы разработали логическую структуру базы данных, и можно переходить к созданию базы данных в СУБД MySQL. Если программа MySQL еще не установлена на вашем компьютере, из следующего раздела вы узнаете, как это сделать.

1.4. Установка и настройка MySQL

 Сделать закладку на этом месте книги

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

Загрузка MySQL

Как упоминалось ранее, дистрибутив MySQL можно бесплатно скачать с сайта компании-разработчика. Windows-версию MySQL вы найдете на веб-странице https://dev.mysql.com/downloads/mysql/5.0.html в одном следующих разделов:

• Windows downloads – здесь находятся ссылки на дистрибутивы MySQL для 32-разрядных операционных систем: Windows Vista/Server 2003/XP/Millennium Edition/2000/98/95;

• Windows x64 downloads – здесь располагаются ссылки на дистрибутивы MySQL для 64-разрядных операционных систем: Windows Vista x64/Server 2003 x64/ XP x64.

В каждом из этих разделов представлены три варианта дистрибутива:

• Essentials – базовый вариант без опциональных компонентов. Включает мастер настройки (Configuration Wizard);

• ZIP/Setup.EXE – полный вариант, включающий опциональные утилиты, документацию и др., а также мастер настройки;

• Without installer – полный вариант, который не включает мастер настройки и требует ручной установки и настройки.

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

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


убрать рекламу






графических утилит MySQL GUI Tools (https://dev.mysql.com/downloads/gui-tools/5.0.html), включающий три программы:

• MySQL Administrator – инструмент администрирования, конфигурирования, мониторинга, запуска/остановки сервера MySQL, управления пользователями и соединениями;

• MySQL Query Browser – инструмент создания, выполнения и оптимизации запросов в графической среде;

• MySQL Migration Toolkit – инструмент для переноса данных в MySQL из других реляционных баз данных (Oracle, Microsoft SQL Server, Microsoft Access, Sybase и др.).


...

Примечание

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

 

Вы скачали необходимые дистрибутивы. Теперь приступим к установке СУБД MySQL 5.0.

Установка сервера MySQL

Чтобы установить на компьютере Windows-версию программы MySQL, выполните следующие действия.

1. Запустите мастер установки (Setup Wizard):

• если вы скачали базовый вариант дистрибутива MySQL, то дважды щелкните на значке файла mysql-essential-5.0.xxx-win32.msi.;

• если вы скачали полный вариант дистрибутива MySQL, то извлеките из архива файл Setup.exe и запустите его, дважды щелкнув на значке файла.

2. В начальном окне мастера установки (рис. 1.1) нажмите кнопку Next (Далее).



Рис. 1.1. Начальное окно мастера установки





























• Если необходимо сконфигурировать MySQL как сервис Windows, установите флажок Install As Windows Service (Установить как сервис Windows). При этом вы можете изменить имя сервиса и указать его автоматический запуск при запуске Windows, установив флажок Launch the MySQL Server automatically (Автоматически запускать сервер MySQL). • Установите флажок Include Bin Directory in Windows PATH (Включить каталог bin в переменную Windows PATH), чтобы при запуске сервера и утилит из командной строки не надо было указывать полный путь к ним (поскольку путь к подкаталогу bin будет добавлен в значение системной переменной Path).


...

Внимание!

Если вы сняли флажок Install As Windows Service (Установить как сервис Windows), следующий пункт пропустите. В этом случае для обеспечения безопасности необходимо вручную установить пароль пользователя root при первом запуске сервера MySQL.

 

Рекомендуется в данном окне установить все три флажка.

Нажмите кнопку Next (Далее).

10. Настройте параметры безопасности MySQL (рис. 1.17).



Рис. 1.17. Настройка параметров безопасности















8. После окончания установки на экране появится информационное окно (см. рис. 1.6). В этом и последующих аналогичных окнах просто нажмите кнопку Next (Далее). В последнем окне нажмите кнопку Finish (Готово). Итак, установка MySQL завершена. Следующий этап – запуск сервера MySQL и подключение к нему. Об этом пойдет речь в следующем разделе.

1.5. Начало работы в MySQL

 Сделать закладку на этом месте книги

Чтобы работать с базой данных, вначале необходимо запустить сервер MySQL и подключиться к нему. Если при настройке сервер MySQL был сконфигурирован как сервис Windows, то он был автоматически запущен по окончании настройки. В противном случае сервер нужно запустить из командной строки (см. подраздел «Запуск и остановка сервера MySQL из командной строки») или с помощью графической утилиты MySQL Administrator (см. подраздел «Запуск и остановка сервера MySQL с помощью MySQL Administrator»).

Подключиться к работающему серверу можно из командной строки (см. подраздел «Подключение к серверу из командной строки») или с помощью графической утилиты MySQL Query Browser (см. подраздел «Подключение к серверу с помощью MySQL Query Browser»).

Запуск и остановка сервера MySQL из командной строки

Запустить сервер MySQL вручную можно одним из двух способов:

• Дважды щелкните на значке файла mysqld-nt.exe, расположенного в подкаталоге bin каталога, где установлена программа MySQL.

• Откройте окно командной строки Windows. Для этого нажмите кнопку Пуск, в меню выберите пункт Выполнить, в появившемся окне Запуск программы в поле Открыть введите команду cmd и нажмите кнопку OK. На экране появится окно командной строки (рис. 1.25).



Рис. 1.25. Окно командной строки

В командной строке введите команду

mysqld-nt  

и нажмите клавишу Enter. Сервер MySQL будет запущен.

Если при настройке сервера путь к подкаталогу bin не был добавлен в значение системной переменной Path, то для запуска сервера необходимо ввести не только имя файла, но и полный путь к нему, например:

C: \Program Files\MySQL\MySQL Server 5.0\bin\mysqld-nt  

Если вы хотите просматривать в окне командной строки диагностические сообщения о работе сервера, вместо mysqld-nt введите

mysqld-nt –console  


...

Внимание!

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

 

Чтобы установить пароль root, откройте новое окно командной строки и введите следующую команду:

mysqladmin -u root password <пароль>  

(или C: \Program Files\MySQL\MySQL Server 5.0\bin\mysqladmin -u root password <пароль>, если путь к подкаталогу bin не был добавлен в значение системной переменной Path при настройке сервера) и нажмите клавишу Enter.

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

mysqladmin -u root -p password <новый пароль>  

После появления приглашения Enter password (Введите пароль) укажите прежний пароль и нажмите клавишу Enter.

Наконец, если необходимо остановить сервер MySQL, выполните команду

mysqladmin -u root -p shutdown  

и в ответ на приглашение Enter password (Введите пароль) введите пароль пользователя root. Нажмите клавишу Enter. Сервер MySQL будет остановлен.

Для запуска и остановки сервера MySQL можно также использовать графическую утилиту MySQL Administrator.

Запуск и остановка сервера MySQL с помощью MySQL Administrator

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

1. Запустите программу MySQL Administrator (Пуск → Все программы → MySQL → MySQL Administrator). На экране появится окно соединения с сервером (рис. 1.26).



Рис. 1.26. Окно соединения с сервером MySQL






...

Внимание!

Если при настройке сервера MySQL вы не указывали пароль пользователя root, то необходимо установить его при первом запуске сервера (иначе кто угодно может управлять сервером под именем root без пароля). В текущей версии MySQL Administrator установка пароля root недоступна, и для выполнения этой операции нужно использовать утилиту командной строки mysqladmin (см. подраздел «Запуск и остановка сервера MySQL из командной строки»).

 

Чтобы остановить сервер MySQL с помощью MySQL Administrator, выполните следующие действия.

1. Запустите программу MySQL Administrator (Пуск → Все программы → MySQL → MySQL Administrator). На экране появится окно соединения с сервером (см. рис. 1.26).

2. В поля окна соединения с сервером введите параметры соединения:

• Server Host (Имя хоста) – значение localhost (локальный компьютер);

• Port (Порт) – номер порта, выбранный при настройке сервера (по умолчанию – 3306);

• Usename (Имя пользователя) – значение root;

• Password (Пароль) – пароль пользователя root. Нажмите кнопку OK.

3. В главном окне MySQL Administrator в левой области щелкните пункт Service Control (Управление сервисом).

4. В правой области окна нажмите кнопку Stop Service (Остановить сервис). Сервер MySQL будет остановлен.

В следующем подразделе вы узнаете, как запустить сервер MySQL с помощью средств администрирования Windows.

Запуск и остановка сервера MySQL с панели управления

Если сервер MySQL был сконфигурирован как сервис Windows с помощью мастера настройки (см. подраздел «Настройка сервера MySQL») или с помощью утилиты MySQL Administrator (см. подраздел «Запуск и остановка сервера MySQL с помощью MySQL Administrator»), то запускать и останавливать его можно с помощью компонента Службы панели управления.

Чтобы вызвать компонент Службы, нажмите кнопку Пуск, в меню выберите пункт Панель управления, затем в панели управления дважды щелкните на значке Администрирование и, наконец, в окне средств администрирования дважды щелкните на значке Службы. На экране появится окно Службы (рис. 1.29) со списком всех локальных служб.



Рис. 1.29. Сервис MySQL в панели управления








...

Внимание!

Шрифт, который по умолчанию используется в MySQL Query Browser для отображения SQL-запросов, не поддерживает русские буквы. Чтобы вводить русские буквы в текстах запросов, необходимо выбрать другой шрифт (например, Arial или Book Antiqua). Для этого в главном окне MySQL Query Browser откройте меню Tools (Сервис) и выберите пункт Options (Параметры). В появившемся окне Options (Параметры) в левой области щелкните пункт General Options (Общие параметры) и в правой области в поле Code Font (Шрифт кода) выберите из списка нужный шрифт. Нажмите кнопку Apply (Сохранить).

 

Чтобы отключиться от сервера, просто закройте окно MySQL Query Browser.

На этом мы заканчиваем знакомство с MySQL и переходим к подведению итогов.

1.6. Резюме

 Сделать закладку на этом месте книги

В этой главе были рассмотрены СУБД MySQL и графические утилиты MySQL Administrator и MySQL Query Browser. Вы освоили достаточно сложную процедуру установки и настройки сервера MySQL, научились управлять сервером и подключаться к нему. Вы также узнали, как устроена реляционная база данных и как спроектировать собственную БД.

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

Глава 2 Управление базой данных с помощью SQL

 Сделать закладку на этом месте книги

Из этой главы вы узнаете, как работать с данными в СУБД MySQL, как определять их структуру, а также как добавлять, изменять и удалять данные. Эти операции выполняет SQL – универсальный язык структурированных запросов, являющийся стандартным средством доступа к реляционным базам данных.

Для выполнения SQL-команд вы можете использовать любое из многочисленных клиентских приложений сервера MySQL. В этой главе не будут рассматриваться приложения сторонних разработчиков. Вы познакомитесь только с приложениями, созданными компанией MySQL AB: утилитой командной строки mysql и графической утилитой MySQL Query Browser.

В обеих утилитах доступны все операции с данными. В MySQL Query Browser удобно работать с базой данных: ее компоненты наглядно представлены, можно непосредственно редактировать данные (без использования SQL-оператора UPDATE), работать с запросами, например строить их с помощью специального инструмента (при этом названия таблиц и столбцов вводить вручную не нужно), сохранять запросы в файле, экспортировать результаты запросов и многое другое. Вы можете узнать о всех возможностях MySQL Query Browser, обратившись к документации на русском языке, найти которую можно по ссылке https://dev.mysql.com/doc/query-browser/ru/index.html.

Вначале вы узнаете, как выполнять SQL-команды в MySQL Query Browser и в командной строке, а в дальнейшем будет рассмотрен только синтаксис SQL-команд.

2.1. Выполнение SQL-команд

 Сделать закладку на этом месте книги

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

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

SET NAMES cp866;  

Результат выполнения этой команды вы видите на рис. 2.1.



Рис. 2.1. Установка кодировки в командной строке







В области запросов вы можете ввести сразу несколько SQL-команд, как показано на рис. 2.4. Текущая команда (на одной из ее строк установлен курсор) выделена белым цветом фона, остальные команды отображены на светло-сером фоне. Чтобы выполнить текущую команду, вы можете нажать либо кнопку Execute, расположенную справа от области запросов, либо комбинацию клавиш Ctrl+Enter. После выполнения команды запрошенные данные выводятся в области результатов, а сообщение о результате выполнения команды – в нижней части этой области. Теперь, когда вы научились вводить SQL-команды, приступим к управлению данными с помощью этих команд. В первую очередь мы рассмотрим команды, предназначенные для работы с базой данных в целом.

2.2. Создание базы данных

 Сделать закладку на этом месте книги

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

Чтобы создать базу данных, выполним команду

CREATE DATABASE <Имя базы данных>;  

Например, команда

CREATE DATABASE SalesDept;  

создает базу данных с именем SalesDept (Отдел продаж).

Если вам по каким-либо причинам нужно для новой базы данных установить кодировку по умолчанию, отличную от кодировки, указанной при настройке MySQL, то при создании базы данных вы можете указать нужную кодировку (character set) и/или правило сравнения (сортировки) символьных значений:

CREATE DATABASE <Имя базы данных>  

CHARACTER SET <Имя кодировки>  

COLLATE <Имя правила сравнения>;  

Например, если вы будете в новую базу импортировать данные, которые находятся в кодировке CP-1251, то укажем эту кодировку при создании базы данных таким образом:

CREATE DATABASE SalesDept  

CHARACTER SET cp1251 COLLATE cp1251_general_ci;  


...

Совет

Чтобы просмотреть список используемых в MySQL кодировок, выполним команду SHOW CHARACTER SET; а чтобы увидеть список правил сравнения символьных значений – команду SHOW COLLATION;. При этом можно использовать оператор LIKE: например, чтобы увидеть все правила сравнения для кодировки CP-1251, выполним команду SHOW COLLATION LIKE %1251 %;. Окончание «_ci» (case insensitive) в названии правил сравнения означает, что при сравнении и сортировке регистр символов не учитывается, окончание «_cs» (case sensitive) – регистр учитывается, окончание «_bin» (binary) – сравнение и сортировка выполняются по числовым кодам символов. Для большинства правил сравнения вы можете найти описание (то есть порядок следования символов, в соответствии с которым будут упорядочиваться текстовые значения) на веб-странице https://www.collation-charts.org/mysql60/.

 

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

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

ALTER DATABASE <Имя базы данных>  

CHARACTER SET <Имя кодировки>  

COLLATE <Имя правила сравнения>;  

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

Чтобы удалить ненужную или ошибочно созданную базу данных, выполните команду

DROP DATABASE <Имя базы данных>;  


...

Внимание!

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

 

Одну из баз, созданных на данном сервере MySQL, вы можете выбрать в качестве текущей базы данных с помощью команды

USE <Имя базы данных>;  

Например,:

USE SalesDept;  

После этого вы можете выполнять операции с таблицами этой базы данных, не добавляя имя базы в виде префикса к имени таблицы. Например, для обращения к таблице Customers (Клиенты) базы данных SalesDept (Отдел продаж) можно вместо SalesDept.Customers писать просто Customers. Указав текущую базу, вы можете обращаться и к таблицам других баз данных, однако использование имени базы данных в виде префикса при этом обязательно. Выбор текущей базы сохраняется до момента отсоединения от сервера или до выбора другой текущей базы данных.

Чтобы увидеть список всех баз, существующих на данном сервере MySQL, выполните команду

SHOW DATABASES;  

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

• INFORMATION_SCHEMA – информационная база данных, из которой вы можете получить сведения о всех остальных базах, о структуре данных в них и о всевозможных объектах: таблицах, столбцах, первичных и внешних ключах, правах доступа, хранимых процедурах, кодировках и др. Эта база данных доступна только для чтения и является виртуальной, то есть она не хранится в виде каталога на диске: вся информация, запрашиваемая из этой БД, предоставляется динамически сервером MySQL.

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

• test – пустая база данных, которую можно использовать для «пробы пера» или просто удалить.

Итак, вы освоили основные операции, выполняемые с базой данных как единым целым: команды CREATE DATABASE (создание), ALTER DATABASE (изменение), DROP DATABASE (удаление), USE (выбор текущей базы данных) и SHOW DATABASES (просмотр списка баз данных). Далее мы рассмотрим операции с таблицами. При этом будем считать, что вы выбрали какую-либо базу данных в качестве текущей и работаете с ее таблицами.

2.3. Работа с таблицами

 Сделать закладку на этом месте книги

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

Создание таблицы

Чтобы создать таблицу, выполните команду, представленную в листинге 2.1.

Листинг 2.1.

Команда создания таблицы

CREATE TABLE <Имя таблицы>  

(<Имя столбца 1> <Тип столбца 1> [<Свойства столбца 1>],  

<Имя столбца 2> <Тип столбца 2> [<Свойства столбца 2>],  

 

[<Информация о ключевых столбцах и индексах>])  

[<Опциональные свойства таблицы>];  

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

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

Предположим, что мы строим базу данных, которую спроектировали в главе 1. Используя команды из предыдущего раздела, мы создали пустую базу данных SalesDept (Отдел продаж) и выбрали ее в качестве текущей. Теперь создадим три таблицы: Customers (Клиенты), Products (Товары) и Orders (Заказы). В листинге 2.2 представлена команда создания таблицы Customers.

Листинг 2.2. Команда создания таблицы Customers

CREATE TABLE Customers  

(id SERIAL,  

name VARCHAR(100),  

phone VARCHAR(20),  

address VARCHAR(150),  

rating INT,  

PRIMARY KEY (id))  

ENGINE InnoDB CHARACTER SET utf8;  

В этой команде использовались параметры: во-первых, название таблицы и, во-вторых, названия и типы столбцов, из которых будет состоять таблица (см. также табл. 1.1 в главе 1). • id – идентификатор записи. Этому столбцу вы назначили тип SERIAL, позволяющий автоматически нумеровать строки таблицы. Ключевое слово SERIAL расшифровывается как BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE. Это означает, что в столбец можно вводить большие целые (BIGINT) положительные (UNSIGNED) числа, при этом автоматически контролируется отсутствие неопределенных и повторяющихся значений (NOT NULL UNIQUE). Если при добавлении строки в таблицу вы не укажете значение для этого столбца, то программа MySQL внесет в этот столбец очередной порядковый номер (AUTO_INCREMENT).


...

Примечание

NULL – это константа, указывающая на отсутствие значения. Если в столбце находится значение NULL, то считается, что никакого определенного значения для этого столбца не задано (поэтому мы также называем NULL неопределенным значением). Не следует путать NULL с пустой строкой («») или числом 0. Значения NULL обрабатываются особым образом: большинство функций и операторов возвращают NULL, если один из аргументов равен NULL. Например, результат сравнения 1 = 1 – истинное значение (TRUE), а результат сравнения NULL = NULL – неопределенное значение (NULL), то есть два неопределенных значения не считаются равными.

 

• Nam – имя клиента, phone – номер телефона и address – адрес. Вы присвоили этим столбцам тип VARCHAR, поскольку они будут содержать символьные значения. В скобках указывается максимально допустимое количество символов в значении столбца.

• Rating – рейтинг. Тип INT означает, что столбец будет содержать обычные целые числа.

В-третьих, вы указали, что столбец id будет первичным ключом таблицы, включив в команду создания таблицы определение PRIMARY KEY (id).

В-четвертых, вы задали для этой таблицы два опциональных параметра. Параметр ENGINE определяет тип таблицы. Таблице Customers вы присвоили тип InnoDB, так как только этот тип обеспечивает поддержание целостности связей между таблицами (более подробно о типах таблиц будет рассказано в пункте «Опциональные свойства таблицы»). Параметр CHARACTER SET определяет кодировку по умолчанию для данных в таблице. Поскольку вы не задали кодировку отдельно для столбцов name, phone и address, данные в этих столбцах будут храниться в кодировке UTF-8, которая назначена в качестве кодировки по умолчанию для таблицы Customers.

Следующий пример, который мы рассмотрим, – команда создания таблицы Products (Товары), представленная в листинге 2.3.

Листинг 2.3.

Команда создания таблицы Products

CREATE TABLE Products  

(id SERIAL,  

description VARCHAR(100),  

details TEXT,  

price DECIMAL(8,2),  

PRIMARY KEY (id))  

ENGINE InnoDB CHARACTER SET utf8;  

Эта команда очень похожа на команду создания таблицы Customers и отличается от нее только названием таблицы и набором столбцов. Столбцы id (номер товара) и description (наименование товара) таблицы Products имеют уже знакомые нам типы. Столбец details (описание) имеет тип TEXT. Этот тип удобно использовать вместо типа VARCHAR, если столбец будет содержать длинные значения: суммарная длина значений всех столбцов с типом VARCHAR ограничена 65 535 байтами для каждой таблицы, а на общую длину столбцов с типом TEXT ограничений нет. Недостатком типа TEXT является невозможность включать такие столбцы во внешний ключ таблицы, то есть создавать связь между таблицами на основе этих столбцов.

Столбец price (цена) имеет тип DECIMAL, предназначенный для хранения денежных сумм и других значений, для которых важно избежать ошибок округления. В скобках мы указали два числа: первое из них определяет максимальное количество цифр в значении столбца, второе – максимальное количес


убрать рекламу






тво цифр после десятичного разделителя. Другими словами, цена товара может содержать до шести цифр в целой части (6 = 8–2) и до двух цифр в дробной части.

И, наконец, последний пример – команда создания таблицы Orders (Заказы), представленная в листинге 2.4.

Листинг 2.4. Команда создания таблицы Orders

CREATE TABLE Orders  

(id SERIAL,  

date DATE,  

product_id BIGINT UNSIGNED NOT NULL,  

qty INT UNSIGNED,  

amount DECIMAL(10,2),  

customer_id BIGINT UNSIGNED,  

PRIMARY KEY (id),  

FOREIGN KEY (product_id) REFERENCES Products (id)  

ON DELETE RESTRICT ON UPDATE CASCADE,  

FOREIGN KEY (customer_id) REFERENCES Customers (id)  

ON DELETE RESTRICT ON UPDATE CASCADE)  

ENGINE InnoDB CHARACTER SET utf8;  

Особенностью таблицы Orders является наличие внешних ключей: столбец product_id (товар) содержит номера товаров из таблицы Products, а столбец customer_id (клиент) – номера клиентов из таблицы Customers (см. также табл. 1.2 в главе 1). Поскольку номера товаров и клиентов являются большими целыми положительными числами, столбцам product_id и customer_id мы назначили тип BIGINT UNSIGNED. Далее, чтобы обеспечить автоматическое поддержание целостности связей (о целостности мы рассказывали в главе 1), мы сообщили программе MySQL, какому первичному ключу соответствует каждый внешний ключ. Так, конструкция FOREIGN KEY (customer_id) REFERENCES Customers (id) означает, что в столбце customer_id могут содержаться только значения из столбца id таблицы Customers и неопределенные значения (NULL), а остальные значения запрещены. Для столбца product_id мы задали аналогичное ограничение и присвоили этому столбцу свойство NOT NULL, чтобы запретить регистрировать заказы с неопределенным товаром. Дополнительно мы указали для каждой из связей правила поддержания целостности (их мы также рассматривали в главе 1). Правило ON DELETE RESTRICT означает, что нельзя удалить запись о клиенте, если у этого клиента есть зарегистрированный заказ, и нельзя удалить запись о товаре, если этот товар был кем-то заказан. Правило ON UPDATE CASCADE означает, что при изменении номера клиента в таблице Customers или номера товара в таблице Products соответствующие изменения вносятся и в таблицу Orders.


...

Примечание

Обратите внимание, что таблицу Orders мы создали в последнюю очередь, так как первичные ключи в таблицах Customers и Products должны быть созданы раньше, чем ссылающиеся на них внешние ключи в таблице Orders. Впрочем, можно было бы создать таблицы без внешних ключей в любой последовательности, а затем добавить внешние ключи с помощью команды ALTER TABLE, которую мы рассмотрим в подразделе «Изменение структуры таблицы».

 

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

Типы данных в MySQL

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

Рассмотрим числовые типы данных.

• BIT[(<Количествобитов>)].

Битовое число, содержащее заданное количество битов. Если количество битов не указано, число состоит из одного бита.

• TINYINT.

Целое число в диапазоне либо от -128 до 127, либо (если указано свойство UNSIGNED) от 0 до 255.

• BOOL или BOOLEAN.

Являются синонимами к типу данных TINYINT(1) (число в скобках – это количество отображаемых цифр, см. примечание ниже). При этом ненулевое значение рассматривается как истинное (TRUE), нулевое – как ложное (FALSE).

• SMALLINT.

Целое число в диапазоне либо от -32 768 до 32 767, либо (если указано свойство UNSIGNED) от 0 до 65 535.

• MEDIUMINT.

Целое число в диапазоне либо от -8 388 608 до 8 388 607, либо (если указано свойство UNSIGNED) от 0 до 16 777 215.

• INT или INTEGER.

Целое число в диапазоне либо от -2 147 483 648 до 2 147 483 647, либо (если указано свойство UNSIGNED) от 0 до 4 294 967 295.

• BIGINT.

Целое число в диапазоне либо от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807, либо (если указано свойство UNSIGNED) от 0 до 18 446 744 073 70 9 551 615.

• SERIAL.

Синоним выражения BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE (большое целое число без знака, принимающее автоматически увеличиваемые уникальные значения; значения NULL запрещены). Используется для автоматической генерации уникальных значений в столбце первичного ключа. Описание свойств UNSIGNED и AUTO_INCREMENT вы найдете в этом подразделе, а свойств NOT NULL и UNIQUE – в пункте «Свойства столбцов».


...

Примечание

Для всех целочисленных типов данных, кроме BOOL (BOOLEAN) и SERIAL, можно в скобках указать количество отображаемых цифр, которое используется совместно с параметром ZEROFILL: если число содержит меньшее количество цифр, то при выводе оно дополняется слева нулями. Например, если столбец таблицы определен как INT(5) ZEROFILL, то значения «1234567» и «12345» отображаются «как есть», а значение «123» – как «00123». Для типа данных BIT в скобках указывается размер числа, то есть максимальное количество хранимых битов.

 

• FLOAT.

Число с плавающей точкой в диапазоне от -3,40282346638 до -1,175494351-38 и от 1,175494351-38 до 3,40282346638 (а также значение 0) с точностью около 7 значащих цифр (точность зависит от возможностей вашего компьютера).

• DOUBLE, DOUBLE PRECISION или REAL.

Число с плавающей точкой в диапазоне от -1,7976931348623157308 до -2,2250738585072014-308 и от 2,2250738585072014-308 до 1,797693134862315738 (а также значение 0) с точностью около 15 значащих цифр (точность зависит от возможностей вашего компьютера).

• FLOAT(<Точность>).

При значении точности от 0 до 24 этот тип данных эквивалентен типу FLOAT, при значении от 25 до 53 – типу DOUBLE.

• DECIMAL, DEC, NUMERIC или FIXED.

Точное (неокругляемое) число с фиксированной точкой. Может содержать до 65 значащих цифр и до 30 цифр после десятичного разделителя (по умолчанию – 10 значащих цифр и 0 после десятичного разделителя).


...

Примечание

Для всех десятичных (нецелочисленных) типов данных, кроме FLOAT(<Точность>), можно в скобках указать точность и шкалу, то есть максимальное количество хранимых значащих цифр и максимальное количество хранимых цифр после десятичного разделителя. Например, если для столбца задан тип данных FLOAT(7,5), это означает, что в столбец нельзя добавить значение с более чем двумя (2 = 7–5) цифрами в целой части и все введенные значения будут округляться до 5 знаков после десятичного разделителя. Для чисел с плавающей точкой можно указать точность до 255 и шкалу до 30, однако указывать слишком большую точность и шкалу не имеет смысла, так как в базе данных сохраняются приближенные значения, которые совпадают с реальными лишь в первых 7 (для типа FLOAT) или 15 (для типа DOUBLE) значащих цифрах, последующие цифры при сохранении могут быть искажены. Для чисел с фиксированной точкой можно указать точность до 65 и шкалу до 30. Если точность и шкала не указаны, то они равны, соответственно, 10 и 0. При сохранении чисел с фиксированной точкой искажений не происходит.

 

Завершая рассмотрение числовых типов данных, обсудим три свойства, которые можно указать для числовых столбцов:

• UNSIGNED – данное свойство означает, что в столбце запрещены отрицательные (со знаком «-») значения. Указывать это свойство можно для любых столбцов с числовым типом данных, кроме BIT, BOOL (BOOLEAN) и SERIAL. Для целочисленных столбцов при добавлении свойства UNSIGNED максимально допустимое значение столбца увеличивается вдвое.

• ZEROFILL – данное свойство означает, что значения при отображении будут дополнены нулями. Целые числа дополняются нулями слева в соответствии с указанным количеством отображаемых цифр, десятичные – слева и справа в соответствии с указанными точностью и шкалой. Например, если столбец определен как DOUBLE(10,5) ZEROFILL, то значение «12.23» отображается как «0012.23000». Кроме того, данное свойство запрещает отрицательные значения, как и свойство UNSIGNED. Указывать свойство ZEROFILL можно для любых столбцов с числовым типом данных, кроме BIT, BOOL (BOOLEAN) и SERIAL.

• AUTO_INCREMENT – данное свойство обеспечивает автоматическую нумерацию строк таблицы. Это означает, что при добавлении в столбец неопределенного (NULL) или нулевого значения оно автоматически заменяется следующим номером, на единицу больше предыдущего (нумерация по умолчанию начинается с единицы, установить другой начальный номер можно с помощью соответствующего свойства таблицы). Указывать это свойство можно для любых столбцов с числовым типом данных, кроме BIT и DECIMAL (DEC, NUMERIC, FIXED). В таблице может быть только один столбец с таким свойством, и для него должен быть создан ключ или индекс (об этом вы узнаете в пункте «Ключевые столбцы и индексы»).

Далее рассмотрим типы данных, используемые при хранении даты и времени.

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

• DATE.

Дата в формате «YYYY-MM-DD», в диапазоне от «0000-01-01» до «9999-12-31».

• DATETIME.

Дата и время в формате «YYYY-MM-DD HH:MM:SS» в диапазоне от «0000–0101 00:00:00» до «9999-12-31 23:59:59».

• TIMESTAMP.

Отметка времени в формате «YYYY-MM-DD HH:MM:SS» в диапазоне от «1970-01-01 00:00:00» до некоторой даты в 2038 г. При добавлении или изменении строки таблицы в столбце с типом TIMESTAMP автоматически устанавливается дата и время выполнения операции (если значение этого столбца не указано явно или указано неопределенное значение). Если нужно, чтобы отметка времени проставлялась только при добавлении строки, после слова TIMESTAMP добавим свойство DEFAULT CURRENT_TIMESTAMP.

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

• TIME.

Время в формате «HH:MM:SS» в диапазоне от «-838:59:59» до «838:59:59».

• YEAR, YEAR(2), YEAR(4).

Год в формате «YYYY» или «YY» (если количество цифр не указано, используется формат «YYYY»). Диапазон значений – от 1901 до 2155, если используется формат «YYYY», или от 70 (соответствует 1970 г.) до 69 (соответствует 2069 г.), если используется формат «YY».

Отмечу, что MySQL воспринимает даты не только в указанном выше формате. Вы можете ввести дату с любым знаком препинания в качестве разделителя, например [email protected]@31 23%59%59, или без разделителя, например 20071231235959. Более того, если в столбец с типом даты или времени вносится символьное или числовое значение в одном из таких форматов, MySQL автоматически преобразует это значение в дату и/или время.

Завершая изучение типов данных, рассмотрим символьные типы.

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

• CHAR(<Количество символов>) или NATIONAL CHAR(<Количество символов>).

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

Тип данных NATIONAL CHAR отличается от CHAR тем, что для столбцов с типом NATIONAL CHAR используется кодировка UTF-8, в то время как для столбцов с типом CHAR можно указать любую кодировку, поддерживаемую MySQL.

• VARCHAR(<Максимальное количество символов>) или NATIONAL VARCHAR(<Максимальное количество символов>).

Символьная строка переменной длины, содержащая не более указанного количества символов. Вы можете указать максимальное количество символов от 0 до 65 535, но не более 65 535 байтов в сумме для всех столбцов таблицы с типом CHAR, VARCHAR, BINARY или VARBINARY. Таким образом, если во всей таблице вы используете однобайтовую кодировку (где каждому символу соответствует 1 байт, например кодировку KOI8-R, CP-866 или CP-1251), то суммарное количество символов, указанное при описании этих столбцов, не должно превышать 65 535. Если же вы используете кодировку UTF-8 (для которой сервер MySQL выделяет до 3 байтов на символ), то суммарное количество символов, указанное при описании этих столбцов, не должно превышать 21 844 (в три раза меньше, чем для однобайтовых кодировок).

Тип данных NATIONAL VARCHAR отличается от VARCHAR тем, что для столбцов с типом NATIONAL VARCHAR используется кодировка UTF-8, в то время как для столбцов с типом VARCHAR можно указать любую кодировку, поддерживаемую MySQL.

• BINARY(<Количество байтов>)

Байтовая (бинарная) строка фиксированной длины. Этот тип аналогичен типу CHAR, только строка содержит не символы, а байты, и значение меньшей длины дополняется справа не пробелами, а нулевыми байтами.

• VARBINARY(<Максимальное количество байтов>)

Байтовая (бинарная) строка переменной длины. Этот тип аналогичен типу VARCHAR, только строка содержит не символы, а байты.

• TINYBLOB

Байтовая (бинарная) строка переменной длины. Максимальная длина – 255 байтов.

• TINYTEXT

Символьная строка переменной длины. Максимальная длина – 255 байтов (не символов!).


...

Примечание

Обратите внимание, что для типов данных TINYTEXT, TEXT, MEDIUMTEXT или LONGTEXT длина значения ограничена максимальным количеством байтов, а не символов. Для однобайтовых кодировок (таких как KOI8-R, CP-866 или CP-1251) длина значения в байтах и в символах одинакова. Однако для многобайтовых кодировок реальное количество символов в значении может быть меньше, чем количество байтов. Так, в кодировке UTF-8 для кодирования символов английского алфавита используется 1 байт на символ, для русского алфавита – 2 байта на символ, поэтому максимальное количество символов русского алфавита, которое можно ввести в такой столбец, приблизительно в два раза меньше, чем максимальное допустимое количество байтов для этого столбца.

 

• BLOB[(<Максимальное количество байтов>)].

Байтовая (бинарная) строка переменной длины. Если количество байтов не указано, то значение столбца ограничено 65 535 байтами. Если количество байтов указано, то создается столбец с типом данных TINYBLOB, BLOB, MEDIUMBLOB или LONGBLOB: выбирается тип данных с наименьшим размером, достаточным для хранения этого количества байтов.

• TEXT[(<Максимальное количество символов>)].

Символьная строка переменной длины. Если количество символов не указано, то значение столбца ограничено 65 535 байтами. Если количество символов указано, то создается столбец с типом данных TINYTEXT, TEXT, MEDIUMTEXT или LONGTEXT: выбирается тип данных с наименьшим размером, достаточным для хранения этого количества символов.

• MEDIUMBLOB.

Байтовая (бинарная) строка переменной длины. Максимальная длина – 16 777 215 байтов.

• MEDIUMTEXT.

Символьная строка переменной длины. Максимальная длина – 16 777 215 байтов.

• LONGBLOB.

Байтовая (бинарная) строка переменной длины. Максимальная длина – не более 4 294 967 295 байтов (4 Гбайт), в зависимости от используемого протокола взаимодействия с сервером MySQL и доступных системных ресурсов.

• LONGTEXT.

Символьная строка переменной длины. Максимальная длина – не более 4 294 967 295 байтов (4 Гбайт), в зависимости от используемого протокола взаимодействия с сервером MySQL и доступных системных ресурсов.

• ENUM(\'<Значение 1>\', \'<Значение 2>\',…).

Строка, содержащая ровно один элемент из заданного списка. Например, если столбец определен как ENUM(\'a\',\'b\'), то допустимыми значениями этого столбца являются значения a, b и NULL (а также пустая строка «», которая может появиться при попытке вставки некорректного значения в данный столбец; о добавлении строк в таблицу и о возможных вариантах обработки некорректных значений пойдет речь в подразделе «Вставка отдельных строк»). В список вы можете включить до 65 535 элементов.

• SET(\'<Значение 1>\', \'<Значение 2>\',…).

Строка, содержащая любой набор элементов из заданного списка (в том числе пустой). Например, если столбец определен как SET(\'a\',\'b\'), то он может содержать значения «» (пустая строка), a, b, a,b и NULL. В список вы можете включить до 64 элементов. Элементы списка не должны содержать запятых. Каждый из элементов может присутствовать в значении столбца только один раз, причем элементы могут следовать только в том порядке, в котором они перечислены в списке. Например, при вставке значений a,b,a,b и b,a они автоматически преобразуются в значение a,b.

В заключение отметим, что в MySQL вы можете указать кодировку отдельно для каждого символьного столбца. А именно, для столбцов с типом CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT, ENUM и SET вы можете задать свойство CHARACTER SET <Имя кодировки> и/или COLLATE <Имя правила сравнения> (подробнее о кодировках и правилах сравнения символьных значений говорилось в разделе «Создание базы данных»).

Например, чтобы имена клиентов хранились в кодировке CP-1251, тогда как кодировкой по умолчанию для таблицы Customers (Клиенты) является UTF-8, столбец name (имя) можно определить следующим образом:

name VARCHAR(100)  CHARACTER SET cp1251 COLLATE cp1251_general_ci  

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

Итак, мы рассмотрели типы данных, которые вы можете назначать столбцам таблицы, а также свойства, специфичные для отдельных типов столбцов: свойства UNSIGNED, ZEROFILL и AUTO_INCREMENT для числовых столбцов и свойства CHARACTER SET и COLLATE – для символьных. Перейдем теперь к свойствам, используемым независимо от типа столбцов.

Свойства столбцов

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

• NOT NULL.

Это свойство указывает, что в данном столбце не допускаются неопределенные значения (NULL).

В качестве примера рассмотрим столбец product_id (товар) таблицы Orders (Заказы) (см. листинг 2.4), который мы определили как

product_id BIGINT UNSIGNED NOT NULL  

Тем самым мы запретили неопределенные номера товаров, поскольку регистрировать заказ с неизвестным товаром не имеет смысла.

Если для столбца задано свойство NOT NULL, то, в частности, NULL не может использоваться в качестве значения по умолчанию для этого столбца. Значение по умолчанию, отличное от NULL, вы можете задать с помощью свойства DEFAULT <Значение>, которое описано ниже. Если же вы задали для столбца свойство NOT NULL, но не задали значение по умолчанию и не указали значение для этого столбца при вставке строки в таблицу, то поведение программы MySQL зависит от того, в каком режиме вы работаете (об этом будет подробно рассказано в подразделе «Вставка отдельных строк»).

• NULL.

Данное свойство указывает, что в столбце разрешены неопределенные значения (NULL). Задавать это свойство имеет смысл только для столбцов с типом TIMESTAMP, которые по умолчанию не допускают неопределенных значений. Остальные типы столбцов допускают неопределенные значения, если только для них не задано свойство NOT NULL.

• DEFAULT <Значение>.

Данное свойство определяет значение по умолчанию для столбца, которое используется, если при вставке строки в таблицу значение столбца не задано явно. Значением по умолчанию может быть только константа; исключение составляют столбцы с типом TIMESTAMP, для которых в качестве значения по умолчанию можно задать переменную величину CURRENT_TIMESTAMP (текущую дату и время). Нельзя установить значение по умолчанию для столбцов с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUM-TEXT, LONGBLOB и LONGTEXT, а также для числовых столбцов, для которых задано свойство AUTO_INCREMENT. Кроме того, нельзя использовать неопределенное значение по умолчанию (NULL), если для столбца задано свойство NOT NULL.

Например, чтобы задать для поля phone (телефон) таблицы Customers (Клиенты) значение по умолчанию, равное пустой строке, можно определить это поле следующим образом:

phone VARCHAR(20) DEFAULT \'\'  

• COMMENT \'Текст комментария\'. Произвольное текстовое описание столбца длиной до 255 символов. Например, описание для поля rating (рейтинг) таблицы Customers (Клиенты) можно задать следующим образом:

rating INT COMMENT \'Рейтинг клиента\'  

Помимо перечисленных свойств, для столбца можно также задать свойства UNIQUE и PRIMARY KEY, однако соответствующие настройки ключевых столбцов и индексов можно указать и после определения всех столбцов таблицы. Мы будем рассматривать только второй вариант создания ключевых столбцов и индексов. Об этом и пойдет речь в следующем пункте. Ключевые столбцы и индексы

После того как определены все столбцы таблицы, можно перечислить через запятую ключевые столбцы и индексы (см. листинги 2.1–2.4). Вы можете использовать следующие конструкции:

• [CONSTRAINT <Имя ключа>] PRIMARY KEY (<Список столбцов>).

Определяет первичный ключ таблицы (о первичных ключах было рассказано в главе 1). В таблице может быть только один первичный ключ, состоящий из одного или нескольких столбцов. Столбцам, входящим в первичный ключ, автоматически присваивается свойство NOT NULL. Ключевое слово CONSTRAINT и имя ключа можно опустить, так как для первичного ключа заданное имя игнорируется и используется имя PRIMARY.

Если в состав первичного ключа входят столбцы с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB и LONGTEXT, необходимо указать количество символов в начале значения столбца; при этом первичный ключ содержит не полные значения столбца, а только начальные подстроки значений. Пример определения первичного ключа:

PRIMARY KEY (id)  

Именно так мы создали первичный ключ для таблиц Customers (Клиенты), Orders (Заказы) и Products (Товары) (см. листинги 2.2–2.4). Если бы мы решили не использовать дополнительный столбец id в таблице Products, а образовать первичный ключ из столбцов description (название) и details (описание), то в команду создания таблицы Products нужно было бы включить следующее определение:

PRIMARY KEY (description,details(10))  

В этом случае в первичный ключ вошли бы столбец description и начальные подстроки значений столбца details длиной 10 символов.

• INDEX [<Имя индекса>] (<Список столбцов>).

Создает индекс для указанных столбцов. Индекс – это вспомогательный объект, позволяющий значительно повысить производительность запросов с условием на значение столбцов, включенных в индекс (подробнее об индексах мы поговорим в главе 6). Например, чтобы создать индекс для быстрого поиска по именам клиентов, в команду создания таблицы Customers (Клиенты) (см. листинг 2.2) можно включить определение

INDEX (name)  

Аналогично первичному ключу, при создании индекса для столбцов с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB и LONGTEXT необходимо указать количество символов в начале значения столбца, по которым будет проведено индексирование.

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

Вместо ключевого слова INDEX можно использовать его синоним – слово KEY.

[CONSTRAINT <Имя ограничения>] UNIQUE [<Имя индекса>] (<Список столбцов>)  

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

UNIQUE (address.phone)  

запрещает добавлять в таблицу Customers (Клиенты) две строки, в которых и адрес, и номер телефона определены и совпадают, но разрешает добавлять строки, в которых адрес совпадает, а номер телефона не определен (то есть столбец phone в обеих строках содержит значение NULL), а также строки, в которых и адрес, и номер телефона не определены.

Для столбцов с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB и LONGTEXT необходимо указать количество символов в начале значения столбца, по которым будет проведено индексирование.

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

Вместо ключевого слова UNIQUE можно использовать его синонимы – выражения UNIQUE INDEX или UNIQUE KEY.

• FULLTEXT [<Имя индекса>] (<Список столбцов>).

Создает полнотекстовый индекс для указанных столбцов. Полнотекстовый индекс обеспечивает ускоренный поиск по значениям символьных столбцов (типы CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT и LONGTEXT) независимо от длины значений. Такой индекс подобен предметному указателю в книге: он представляет собой список всех слов, встречающихся в значениях столбцов, со ссылками на те значения, в которых каждое слово содержится.

Полнотекстовый индекс можно создать только в таблицах c типом MyISAM (см. пункт «Опциональные свойства таблицы»). Для поиска с использованием полнотекстового индекса предназначен оператор MATCH… AGAINST, о котором будет идти речь в главе 3.

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

Вместо ключевого слова FULLTEXT можно использовать его синонимы – выражения FULLTEXT INDEX или FULLTEXT KEY.

• SPATIAL [<Имя индекса>] (<Список столбцов>).

Создает индекс для поиска по пространственным и географическим значениям, которые остаются за рамками нашего рассмотрения.

• [CONSTRAINT <Имя внешнего ключа>].

FOREIGN KEY [<Имя индекса>] (<Список столбцов>)  

REFERENCES <Имя родительской таблицы>  

(<Список столбцов первичного ключа родительской таблицы>)  

[<Правила поддержания целостности связи>]  

Определяет внешний ключ таблицы (внешние ключи мы рассматривали в главе 1). Настроив внешний ключ, мы тем самым создадим связь между данной (дочерней) таблицей и родительской таблицей. Внешние ключи поддерживаются только для таблиц c типом InnoDB (причем и дочерняя, и родительская таблица должны иметь тип InnoDB), для остальных типов таблиц выражение FOREIGN KEY игнорируется.

Столбцы, составляющие внешний ключ, должны иметь типы, аналогичные типам столбцов первичного ключа в родительской таблице. Для числовых столбцов должен совпадать размер и знак, для символьных – кодировка и правило сравнения значений. Столбцы с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB и LONGTEXT не могут входить во внешний ключ.

Имя внешнего ключа и имя индекса указывать не обязательно. Если вы не зададите эти имена, они будут автоматически сгенерированы. Вы можете также указать, какие именно правила поддержания целостности связи необходимо использовать для операций удаления и для операций изменения строк родительской таблицы (все эти правила мы обсуждали в подразделе «Целостность данных» главы 1). Для операций удаления вы можете указать одно из следующих выражений:

• ON DELETE CASCADE – каскадное удаление строк дочерней таблицы (строка родительской таблицы удаляется вместе со всеми ссылающимися на нее строками дочерней таблицы);

• ON DELETE SET NULL – обнуление значений внешнего ключа в соответствующих строках дочерней таблицы;

• ON DELETE RECTRICT или ON DELETE NO ACTION (в MySQL эти выражения являются синонимами) – запрет удаления строк родительской таблицы при наличии ссылающихся на них строк дочерней таблицы.

Если вы не задали правило поддержания целостности для операций удаления, по умолчанию используется правило ON DELETE RECTRICT.

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

• ON UPDATE CASCADE – каскадное обновление значений внешнего ключа дочерней таблицы (вместе со значением первичного ключа в строке родительской таблицы изменяе


убрать рекламу






тся значение внешнего ключа во всех ссылающихся на нее строках дочерней таблицы);

• ON UPDATE SET NULL – обнуление значений внешнего ключа в соответствующих строках дочерней таблицы;

• ON UPDATE RECTRICT или ON UPDATE NO ACTION (в MySQL эти выражения являются синонимами) – запрет изменения значений первичного ключа в строках родительской таблицы при наличии ссылающихся на них строк дочерней таблицы.

Если вы не задали правило поддержания целостности для операций изменения, по умолчанию используется правило ON UPDATE RECTRICT.

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

Пример определения внешнего ключа в таблице Orders (Заказы) (см. листинг 2.4):

FOREIGN KEY (product_id) REFERENCES Products (id)  ON DELETE RESTRICT ON UPDATE CASCADE  

Это выражение означает, что столбец product_id (товар) таблицы Orders является внешним ключом, который ссылается на столбец id (идентификатор) родительской таблицы Products (Товары). При этом запрещается удаление строки таблицы Products, если на нее ссылается хотя бы одна строка таблицы Orders, а изменение значения в столбце id таблицы Products приводит к автоматическому обновлению значений столбца product_id таблицы Orders. Итак, мы изучили индексы и ключи, которые можно настроить при создании таблицы. Наконец, рассмотрим последнюю составляющую команды создания таблицы, а именно опциональные свойства таблицы. Опциональные свойства таблицы

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

• ENGINE <Тип таблицы>.

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

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

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

Таблицы MyISAM не поддерживают объединение нескольких операций в единую транзакцию, поэтому, в частности, невозможно автоматическое поддержание целостности связей между такими таблицами. Однако таблицы MyISAM также часто используются: их преимуществом является высокая скорость выполнения поисковых запросов и меньшая нагрузка на системные ресурсы. Если при настройке сервера MySQL (о ней вы узнали из главы 1) вы выбрали в качестве типа базы данных вариант Multifunctional Database (Многофункциональная база данных) или Transactional Database Only (Транзакционная база данных), либо если вы настраивали сервер в стандартном режиме (в этом случае тип базы данных был задан автоматически), то по умолчанию применяется тип таблиц InnoDB. В этом случае, если требуется создать таблицу с типом MyISAM, добавим в команду создания таблицы выражение ENGINE MyISAM. Если же при настройке вы предпочли вариант Non-Transactional Database Only (Нетранзакционная база данных), то по умолчанию применяется тип таблиц MyISAM, а таблицы типа InnoDB не поддерживаются.

Все таблицы нашего примера (см. листинги 2.2–2.4) были созданы с параметром ENGINE InnoDB. Это дало нам возможность настроить внешние ключи в таблице Orders (Заказы) для поддержания целостности связей этой таблицы с таблицами Customers (Клиенты) и Products (Товары). Вместо ключевого слова ENGINE можно использовать его синоним – слово TYPE.

• AUTO_INCREMENT <Начальное значение>.

Задание этого свойства для таблицы, в которой есть столбец со свойством AUTO_INCREMENT, позволяет начать нумерацию в этом столбце не с единицы, а с указанного вами значения. Например, если номера заказов должны начинаться с 1000, нужно в команду создания таблицы Orders (см. листинг 2.4) включить параметр AUTO_INCREMENT 1000.

• CHARACTER SET <Имя кодировки>.

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

Все таблицы нашего примера (см. листинги 2.2–2.4) были созданы с параметром CHARACTER SET utf8. Поэтому все данные о клиентах и товарах будут храниться в этой кодировке.

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

• COLLATE <Имя правила сравнения>.

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

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

• CHECKSUM 1.

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

• COMMENT \'Текст комментария\'.

Произвольное текстовое описание таблицы длиной до 60 символов. Например, описание для таблицы Customers (Клиенты) можно задать, включив в команду создания таблицы параметр

COMMENT \'Сведения о клиентах\'  

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

Изменение структуры таблицы

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

• Добавить столбец вы можете с помощью команды

ALTER TABLE <Имя таблицы>  

ADD <Имя столбца> <Тип столбца> [<Свойства столбца>]  

[FIRST или AFTER <Имя предшествующего столбца>];  

В этой команде мы указываем имя таблицы, в которую добавляется столбец, а также имя и тип добавляемого столбца (о типах столбцов см. пункт «Типы данных в MySQL»). При необходимости можно также задать свойства добавляемого столбца (см. пункт «Свойства столбцов»). Кроме того, можно определить место нового столбца среди уже существующих: добавляемый столбец может стать первым (FIRST) или следовать после указанного предшествующего столбца (AFTER). Если место столбца не задано, он становится последним столбцом таблицы. Например, чтобы добавить в таблицу Products (Товары) столбец store (название склада, где хранится каждый вид товара), выполните команду

ALTER TABLE Products ADD store VARCHAR(100) AFTER details;  


...

Примечание

Добавить столбец со свойством AUTO_INCREMENT можно только с одновременным созданием индекса или ключа для этого столбца. Например, если бы столбец id не был включен в таблицу Products (Товары) при ее создании, мы могли бы добавить его с помощью команды

ALTER TABLE Products  

ADD id BIGINT AUTO_INCREMENT, ADD PRIMARY KEY (id);  

 

• Добавить первичный ключ вы можете с помощью команды

ALTER TABLE <Имя таблицы>  

ADD [CONSTRAINT <Имя ключа>]  

PRIMARY KEY (<Список столбцов>);  

При добавлении в таблицу первичного ключа мы указываем имя таблицы, в которую нужно добавить ключ, и имена столбцов, которые будут образовывать первичный ключ (эти столбцы должны уже существовать в таблице). Более подробно о первичных ключах было сказано в пункте «Ключевые столбцы и индексы». Например, если бы первичный ключ не был определен при создании таблицы Orders (Заказы), мы могли бы добавить его с помощью команды

ALTER TABLE Orders ADD PRIMARY KEY (id);  

• Добавить внешний ключ вы можете с помощью команды

ALTER TABLE <Имя таблицы>  

ADD [CONSTRAINT <Имя внешнего ключа>]  

FOREIGN KEY [<Имя индекса>] (<Список столбцов>)  

REFERENCES <Имя родительской таблицы>  

(<Список столбцов первичного ключа родительской таблицы>)  

[<Правила поддержания целостности связи>];  

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

ALTER TABLE Orders  

ADD FOREIGN KEY (customer_id) REFERENCES Customers (id)  

ON DELETE RESTRICT ON UPDATE CASCADE);  

Более подробно о внешних ключах говорилось в пункте «Ключевые столбцы и индексы». • Добавить в таблицу обычный индекс вы можете с помощью команды

ALTER TABLE <Имя таблицы>  ADD INDEX [<Имя индекса>] (<Список столбцов>);  

Добавить уникальный индекс – с помощью команды

ALTER TABLE <Имя таблицы>  

ADD [CONSTRAINT <Имя ограничения>]  

UNIQUE (<Список столбцов>);  

Добавить полнотекстовый индекс – с помощью команды ALTER TABLE <Имя таблицы>

ALTER TABLE <Имя таблицы>  ADD FULLTEXT [<Имя индекса>] (<Список столбцов>);  

При добавлении в таблицу индекса мы указываем имя таблицы, в которую нужно добавить индекс, и имена столбцов, включенных в индекс. В случае необходимости можно также задать имя индекса. Более подробно об индексах было сказано в пункте «Ключевые столбцы и индексы». Например, добавить индекс для столбца store (склад) таблицы Products (Товары) можно с помощью команды

ALTER TABLE Products ADD INDEX (store);  

• Изменить столбец таблицы вы можете с помощью следующих команд: – Чтобы полностью изменить описание столбца, выполните команду

ALTER TABLE <Имя таблицы>  

CHANGE <Прежнее имя столбца >  

<Новое имя столбца>  

<Новый тип столбца> [<Свойства столбца>]  

[FIRST или AFTER <Имя предшествующего столбца>];  


...

Внимание!

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

 

В этой команде мы указываем имя таблицы, текущее имя столбца, новое имя столбца (которое может совпадать с текущим), новый тип столбца (который также может совпадать с текущим типом), а также, при необходимости, свойства столбца (старые свойства при выполнении команды CHANGE удаляются). Кроме того, можно определить место столбца среди остальных столбцов таблицы: изменяемый столбец может стать первым (FIRST) или следовать после указанного предшествующего столбца (AFTER).

Например, чтобы переименовать столбец store (склад) таблицы Products (Товары) в warehouse (склад) и изменить его тип на CHAR(100), выполните команду

ALTER TABLE Products CHANGE store warehouse CHAR(100);  

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

ALTER TABLE <Имя таблицы>  

MODIFY <Имя столбца>  

<Новый тип столбца> [<Свойства столбца>]  

[FIRST или AFTER <Имя предшествующего столбца>];  

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

ALTER TABLE <Имя таблицы>  

ALTER <Имя столбца>  

SET DEFAULT <Значение по умолчанию>;  

Например, чтобы установить для столбца warehouse таблицы Products значение по умолчанию Склад № 1, выполните команду

ALTER TABLE Products  ALTER warehouse SET DEFAULT \'Склад № 1\  

Чтобы удалить значение по умолчанию, выполните команду

ALTER TABLE <Имя таблицы>  

ALTER <Имя столбца> DROP DEFAULT;  

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

ALTER TABLE Products ALTER warehouse DROP DEFAULT;  

• Удалить столбец таблицы вы можете с помощью команды

ALTER TABLE <Имя таблицы> DROP <Имя столбца>;  

При удалении столбца он удаляется также из всех индексов, в которые он был включен (в отличие от первичного и внешнего ключа, которые требуется удалить прежде, чем удалять входящие в них столбцы). Если при этом в индексе не остается столбцов, то индекс также автоматически удаляется. Например, для удаления столбца warehouse (склад) из таблицы Products (Товары) выполните команду

ALTER TABLE Products DROP warehouse;  

• Удалить первичный ключ вы можете с помощью команды

ALTER TABLE <Имя таблицы> DROP PRIMARY KEY;  

Например, удалить первичный ключ из таблицы Orders (Заказы) можно с помощью команды

ALTER TABLE Orders DROP PRIMARY KEY;  

• Удалить внешний ключ вы можете с помощью команды

ALTER TABLE <Имя таблицы>  DROP FOREIGN KEY <Имя внешнего ключа>;  

В этой команде необходимо указать имя внешнего ключа. Если вы не задали имя внешнего ключа при его создании, то имя было присвоено автоматически и узнать его можно с помощью команды SHOW CREATE TABLE (см. подраздел «Другие команды для работы с таблицами»). Например, удалить внешний ключ из таблицы Orders можно с помощью команды

ALTER TABLE Orders DROP FOREIGN KEY orders_ibfk_1;  

(здесь orders_ibfk_1 – имя внешнего ключа, автоматически присвоенное ему при создании). • Удалить индекс (обычный, уникальный или полнотекстовый) вы можете с помощью команды

ALTER TABLE <Имя таблицы> DROP INDEX <Имя индекса>;  

В этой команде необходимо указать имя индекса. Если вы не задали имя индекса при его создании, то имя было присвоено автоматически и узнать его можно с помощью команды SHOW CREATE TABLE (см. подраздел «Другие команды для работы с таблицами»). Например, удалить индекс, созданный для поля name (имя) таблицы Customers (Клиенты), можно с помощью команды

ALTER TABLE Customers DROP INDEX name;  

(здесь name – имя индекса: по умолчанию индексу присваивается имя первого индексируемого столбца). • Включить и отключить обновление неуникальных индексов в таблице с типом MyISAM вы можете с помощью следующих команд:

ALTER TABLE <Имя таблицы> DISABLE KEYS;  

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

ALTER TABLE <Имя таблицы> ENABLE KEYS;  

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

ALTER TABLE <Имя таблицы> RENAME <Новое имя таблицы>;  

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

ALTER TABLE <Имя таблицы>  

ORDER BY <Имя столбца 1> [ASC или DESC],  

[<Имя столбца 2> [ASC или DESC],…];  

Упорядочение строк позволяет ускорить последующие операции сортировки по значениям указанных столбцов. Однако порядок строк в таблице может нарушиться после операций добавления и удаления строк. По умолчанию строки таблицы упорядочиваются по возрастанию значений. Вы можете выбрать направление сортировки, указав ключевое слово ASC (по возрастанию) или DESC (по убыванию).

Для таблиц с типом InnoDB, в которых есть первичный ключ или уникальный индекс, не допускающий неопределенных значений (NOT NULL UNIQUE), эта команда игнорируется, поскольку строки таких таблиц автоматически упорядочиваются по значениям этого ключа/индекса.

• Задать опциональные свойства таблицы (см. пункт «Опциональные свойства таблицы») вы можете с помощью команды

ALTER TABLE <Имя таблицы> <Опциональное свойство таблицы>;  

Например, изменить тип таблицы можно с помощью команды

ALTER TABLE <Имя таблицы> ENGINE <Новый тип таблицы>;  

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

ALTER TABLE <Имя таблицы>  

CHARACTER SET <Имя кодировки>  

[COLLATE <Имя правила сравнения>];  

Например, если для таблицы Products (Товары) требуется установить в качестве кодировки по умолчанию кодировку CP-1251, это можно сделать с помощью команды

ALTER TABLE Products CHARACTER SET cp1251;  

После выполнения этой команды существующие столбцы таблицы Products по-прежнему будут иметь кодировку UTF-8. Если же с помощью команды ALTER TABLE будут добавляться новые символьные столбцы, то им будет по умолчанию присваиваться кодировка CP-1251. Если вы хотите не только изменить кодировку, используемую по умолчанию для новых столбцов, но и преобразовать в новую кодировку существующие символьные столбцы таблицы, то нужно использовать команду

ALTER TABLE <Имя таблицы>  

CONVERT TO CHARACTER SET <Имя кодировки>  

[COLLATE <Имя правила сравнения>];  

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

ALTER TABLE Products CONVERT TO CHARACTER SET cp1251;  

все наименования и описания товаров (значения столбцов description и details) преобразуются в кодировку CP-1251. Если же данные в столбце фактически закодированы с помощью одной кодировки, а в описании столбца указана другая кодировка, исправить эту ошибку можно, изменив кодировку только в описании столбца,  без преобразования данных. Это можно сделать, преобразовав тип столбца из символьного в бинарный (то есть тип CHAR преобразовать в тип BINARY, тип VARCHAR – в тип VARBINARY, тип TEXT – в тип BLOB и т. п.), а затем обратно в символьный, уже в правильной кодировке. Для этого выполним последовательно две команды:

ALTER TABLE <Имя таблицы>  

CHANGE <Имя столбца> <Имя столбца> <Бинарный тип данных>;  

ALTER TABLE <Имя таблицы>  

CHANGE <Имя столбца> <Имя столбца> <Исходный тип данных>  

CHARACTER SET <Фактическая кодировка значений>;  

Например, если для столбца details таблицы Products установлен тип TEXT и кодировка UTF-8, а данные в нем фактически находятся в кодировке CP-1251, приведем описание столбца в соответствие с реальной кодировкой с помощью команд

ALTER TABLE Products CHANGE details details BLOB;  

ALTER TABLE Products  

CHANGE details details TEXT CHARACTER SET cp1251;  

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

Другие команды для работы с таблицами

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

Получить детальную информацию о конкретной таблице вы можете с помощью команды

DESCRIBE <Имя таблицы>;  

или

SHOW CREATE TABLE <Имя таблицы>;  

Эти команды вы можете использовать, чтобы, например, узнать имена и порядок следования столбцов таблицы, проверить правильность изменений, внесенных в структуру таблицы с помощью команды ALTER TABLE и т. п. Команда DESCRIBE выводит информацию о столбцах таблицы. Например, чтобы получить информацию о столбцах таблицы Customers (Клиенты), выполним команду

DESCRIBE Customers;  


...

Примечание

Во всех клиентских приложениях, подключенных к серверу MySQL, в результате выполнения одной и той же команды отображаются одни и те же данные. Однако окна разных клиентских приложений выглядят по-разному (сравним, например, рис. 2.2 и рис. 2.4). Поэтому здесь и далее мы будем приводить не изображение окна, а только сами данные, выводимые командой.

 

Результат выполнения этой команды представлен в табл. 2.1.

Таблица 2.1.

Результат выполнения команды DESCRIBE Customers;



Для каждого столбца таблицы команда DESCRIBE отображает следующие характеристики:

• Field – имя столбца;

• Type – тип столбца;

• Null – указывает, допускает ли столбец неопределенные значения (NULL): YES – допускает, NO – не допускает;

• Key – показывает вхождение столбца в ключи и индексы:

– PRI – столбец входит в первичный ключ или, если в таблице нет первичного ключа, в уникальный индекс, не допускающий неопределенных значений;

– UNI, MUL – столбец является первым столбцом индекса;

• Default – значение столбца по умолчанию;

• Extra – дополнительная информация.

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

SHOW CREATE TABLE Customers;  



SHOW TABLES;  



DROP TABLE <Имя таблицы>;  


...

Внимание!

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

 

Итак, вы освоили основные операции, выполняемые с таблицами, а именно: команды CREATE TABLE (создание), ALTER TABLE (изменение), DROP TABLE (удаление), SHOW TABLES (просмотр списка таблиц), DESCRIBE и SHOW CREATE TABLE (просмотр информации о таблице). Теперь мы переходим к работе с отдельными строками.

2.4. Ввод данных в таблицу

 Сделать закладку на этом месте книги

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

Загрузка данных из файла

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

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

1. Запустите стандартную программу Windows Блокнот (Пуск → Все программы → Стандартные → Блокнот).

2. В окне программы Блокнот введите данные, используя для отделения значений друг от друга клавишу Tab, а для перехода на следующую строку – клавишу Enter (рис. 2.5).



Рис. 2.5. Ввод данных в текстовый файл


...

Примечание

Вместо отсутствующего значения необходимо при заполнении файла ввести символы «\N». Тогда в базу данных будет загружено неопределенное значение (NULL).

 

3. Для сохранения файла с данными нажмите комбинацию клавиш Ctrl+S. В стандартном окне Windows Сохранить как выберите папку, в которую нужно поместить файл (например, C: \data). Введите имя файла (например, Customers. txt) и нажмите кнопку Сохранить.

4. Для загрузки данных из созданного файла выполните команду

LOAD DATA LOCAL INFILE \'C:/data/Customers.txt\'  

INTO TABLE Customers  

CHARACTER SET cp1251;  

Обратите внимание, что в пути к файлу необходимо использовать прямую косую черту, а не обратную.

Файл Customers.txt мы создали в формате, принятом по умолчанию в MySQL, поэтому при загрузке потребовалось указать только один дополнительный параметр – кодировку Windows.

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

LOAD DATA [LOCAL] INFILE \'Путь и имя файла\'  

[REPLACE или IGNORE]  

INTO TABLE <Имя таблицы>  

CHARACTER SET <Имя кодировки>  

[  

FIELDS  

[TERMINATED BY <Разделитель значений в строке>]  

[[OPTIONALLY]  

ENCLOSED BY <Символ, в который заключены значения>]  

[ESCAPED BY <Экранирующий символ>]  

]  

[  

LINES  

[STARTING BY <Префикс строки>]  

[TERMINATED BY <Разделитель строк>]  

]  

[IGNORE <Количество строк в начале файла> LINES]  

[(<Список столбцов>)]  

[SET <Имя столбца> = <Выражение>,…];  

В этой команде вы можете использовать следующие параметры.

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

• \'Путь и имя файла\' – введите полный путь к файлу, например C:/Data/ mytable.txt (необходимо использовать прямую косую черту вместо обратной, принятой в Windows).

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

• CHARACTER SET <Имя кодировки> – укажите кодировку данных в файле. Этот параметр используется для корректного преобразования кодировок. Предполагается, что все данные в файле имеют одну и ту же кодировку.


...

Внимание!

Загрузка данных в кодировке UTF-8 может работать некорректно вследствие переменного количества байтов на символ в этой кодировке. Рекомендуем файл с данными в этой кодировке перед загрузкой преобразовать в какую-либо однобайтовую кодировку. Например, откроем файл с помощью программы Блокнот, в меню Файл выберем команду Сохранить как, а затем в стандартном окне Windows Сохранить как в поле Кодировка выберем из списка значение ANSI и нажмем кнопку Сохранить. После этого загрузим этот файл, указав в команде LOAD DATA параметр CHARACTER SET cp1251.

 

• FIELDS – укажите этот параметр, чтобы сообщить программе MySQL, в каком формате заданы значения в файле:

– TERMINATED BY <Разделитель значений в строке> – укажем символ, разделяющий значения в строке файла. Например, если значения разде


убрать рекламу






лены запятыми, укажем параметр TERMINATED BY, если значения разделены символами табуляции – TERMINATED BY \t\', если значения разделены косой чертой – TERMINATED BY /;

– ENCLOSED BY <Символ, в который заключены значения> – укажем символ, которым обрамляются значения. Например, если все значения заключены в одинарные кавычки, укажем ENCLOSED BY \, если в одинарные кавычки заключены только символьные значения, укажем OPTIONALLY ENCLOSED BY \, а если никакие значения не обрамляются никакими символами, укажем ENCLOSED BY или вообще опустим этот параметр;

– ESCAPED BY <Экранирующий символ> – укажем экранирующий символ (его также называют escape-символом). Этот символ сообщает программе MySQL, что следующий за ним символ нужно интерпретировать особым образом. А именно, обычный символ, следующий после экранирующего, будет рассматриваться как специальный символ, а специальный символ, наоборот, – как обычный символ.

Чаще всего экранирующим символом служит обратная косая черта, и в этом случае зададим значение ESCAPED BY \\. Тогда, например, записанное в файле значение «\N» будет прочитано и загружено в базу данных как NULL. Другой пример: если значения в файле разделены запятыми, то экранирующий символ помещается перед запятой, которая должна восприниматься как часть значения, а не как разделитель, то есть последовательность символов «\,» интерпретируется как символ запятой в значении.

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

• LINES – укажите этот параметр, чтобы сообщить программе MySQL, в каком формате заданы строки в файле:

– STARTING BY <Префикс строки> – укажем последовательность символов в начале каждой строки, которая должна игнорироваться программой вместе со всеми предшествующими символами. После префикса должны начинаться значения;

– TERMINATED BY <Разделитель строк> – укажем символ, которым заканчиваются строки. Например, если строки заканчиваются символом перевода строки, укажем параметр TERMINATED BY \n\', если символом возврата каретки – укажем TERMINATED BY \r\', если сочетанием этих символов – укажем TERMINATED BY \r\n\', если нулевым байтом – укажем TERMINATED BY \0.

Если параметр LINES не указан, программа MySQL считает, что строки в файле не имеют префикса и заканчиваются символом перевода строки «\n».

• IGNORE <Количество строк в начале файла> LINES – укажите этот параметр, если первые несколько строк в файле не содержат значений (иными словами, являются заголовком) и при загрузке их нужно пропустить.

• (<Список столбцов>) – перечислите столбцы таблицы, в которые будут загружаться данные. Это необходимо, если файл содержит данные не для всех столбцов таблицы или порядок следования значений в файле отличается от порядка столбцов в таблице.

• SET <Имя столбца> = <Выражение> – вы можете записывать в столбцы не только значения из файла, но и значения, вычисленные с помощью выражений. Для этого создадим одну или несколько переменных, присвоим им считанные из файла значения и запишем в столбец значение выражения, использующего эти переменные. Пусть, например, имеется таблица t1 с числовым столбцом c1 и столбцом с2 с типом TIMESTAMP. В столбец c1 нужно загрузить значение из файла, если это значение не превосходит 1000, либо NULL, если значение в файле больше 1000, а в столбец c2 при этом нужно записать текущую дату и время. Это можно сделать с помощью команды

LOAD DATA INFILE \'С:/DATA/t1.txt\'  

INTO TABLE t1 (@var1)  

SET c1 = IF(@var1< = 1000,@var1,NULL), c2 = CURRENT_TIMESTAMP;  

(о функции IF и о других функциях, используемых в выражениях, рассказывается в главе 3). Далее рассмотрим команду INSERT, с помощью которой также можно добавлять строки в таблицу.

Вставка отдельных строк

Для добавления одной или нескольких строк в таблицу можно использовать команду

INSERT [INTO] <Имя таблицы>  

[(<Список столбцов>)]  

VALUES  

(<Список значений 1>),  

(<Список значений 2>),  

 

(<Список значений N>);  

В команде INSERT используются следующие основные параметры.

• Имя таблицы, в которую добавляются строки.

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


...

Примечание

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

 

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

– набор значений для каждой добавляемой строки заключается в скобки. Набор значений внутри каждой пары скобок должен соответствовать указанному списку столбцов, а если список столбцов не указан, то упорядоченному списку всех столбцов, составляющих таблицу (список столбцов таблицы можно просмотреть с помощью команды DESCRIBE, см. подраздел «Другие команды для работы с таблицами»). Значения внутри набора, а также сами наборы отделяются друг от друга запятыми;

– символьные значения, а также значения даты и времени приводятся в одинарных кавычках. Для числовых значений кавычки необязательны. Десятичным разделителем для чисел с дробной частью служит точка. Время и даты вводятся, соответственно, в формате «YYYY-MM-DD» и «HH:MM:SS»;

– чтобы ввести в столбец неопределенное значение, то необходимо указать вместо значения ключевое слово NULL без кавычек  (слово в кавычках рассматривается как обычная символьная строка);

– вместо значения можно указать ключевое слово DEFAULT без кавычек,  тогда в столбец будет введено значение по умолчанию (если оно задано для этого столбца).

Например, добавьте в таблицу Products (Товары) сведения о продукции компании с помощью команды, представленной в листинге 2.5.

Листинг 2.5.

Команда добавления строк в таблицу Products

INSERT INTO Products (description,details,price)  

VALUES  

(\'Обогреватель Мосбытприбор ВГД 121R\',  

\'Инфракрасный обогреватель. 3 режима нагрева:  

400 Вт, 800 Вт, 1200 Вт\',\'1145.00\'),  

(\'Гриль Мосбытприбор СТ-14\',  

\'Мощность 1440 Вт. Быстрый нагрев. Термостат.  

Цветовой индикатор работы\',\'2115.00\'),  

(\'Кофеварка Мосбытприбор ЕКЛ-1032\',  

\'Цвет: черный. Мощность: 450 Вт.  

Вместительность: 2 чашки\',\'710.00\'),  

(\'Чайник Мосбытприбор МН\',  

\'Цвет: белый. Мощность: 2200 Вт. Объем: 2 л\',\'925.00\'),  

(\'Утюг Мосбытприбор c паром АБ 200\',  

\'Цвет: фиолетовый. Мощность: 1400 вт\',\'518.00\');  

Эта команда добавляет значения в столбцы description (наименование), details (описание) и price (цена) таблицы Products. При этом в столбец id (идентификатор) автоматически вносятся порядковые номера строк, поскольку этот столбец имеет тип данных SERIAL (см. листинг 2.3).

Теперь, когда данные внесены и в таблицу Customers (Клиенты) (в предыдущем подразделе было рассказано, как загрузить в эту таблицу данные из файла), и в таблицу Products, можно заполнять таблицу Orders (Заказы). Напомню, что каждая строка таблицы Orders ссылается на строку таблицы Customers и строку таблицы Products, и в момент добавления строки в таблицу Orders соответствующие строки в таблицах Customers и Products должны уже существовать. Внесите в таблицу Orders сведения о заказах, выполнив команду, представленную в листинге 2.6.

Листинг 2.6. Команда добавления строк в таблицу Orders

INSERT INTO Orders  

VALUES  

(1012,\'2007-12-12\',5,8,\'4500\',533),  

(1013,\'2007-12-12\',2,14,\'22000\',536),  

(1014,\'2008-01-21\',5,12,\'5750\',533);  

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

SHOW VARIABLES LIKE \'sql_mode\  

Эта команда показывает значение переменной sql_mode. Если в значении нет ключевых слов STRICT_TRANS_TABLES и STRICT_ALL_TABLES, это означает, что сервер работает в нестрогом режиме.

В нестрогом режиме вставляемое некорректное значение преобразуется в допустимое, в частности

• некорректная дата заменяется нулевой датой (0000-00-00 00:00:00);

• «лишние» символы в слишком длинном символьном значении отбрасываются (так, значение abc, вставляемое в столбец с типом CHAR(2), сокращается до ab);

• слишком большое число заменяется максимально возможным значением для данного типа столбца;

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

• если вы установили для столбца свойство NOT NULL, но не задали значение по умолчанию, а при вставке строки не указали значение для этого столбца, то в столбец будет добавлено следующее значение:

– для числовых столбцов – 0, а если задано свойство AUTO_INCREMENT, то очередной порядковый номер;

– для столбцов с типом даты и времени – нулевая дата и/или время (0000–0000 00:00:00), а для первого в таблице столбца с типом TIMESTAMP – текущая дата и время;

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

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

SHOW WARNINGS;  


...

Внимание!

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

 

Если в значении переменной sql_mode содержится ключевое слово STRICT_ TRANS_TABLES или STRICT_ALL_TABLES, значит, сервер работает в строгом режиме. Для таблиц с поддержкой транзакций (то есть таблиц с типом InnoDB) эти два режима эквивалентны и действуют одинаково. При попытке вставки некорректного значения операция INSERT полностью отменяется (то есть в таблицу не загружается ни одна из добавляемых строк, даже если некорректное значение обнаружено только в одной из них) и выдается сообщение об ошибке.

Для таблиц, не поддерживающих транзакции (то есть таблиц с типом MyISAM и др.), режимы STRICT_TRANS_TABLES или STRICT_ALL_TABLES функционируют следующим образом:

• если некорректное значение обнаружено в первой из добавляемых строк, операция INSERT полностью отменяется и выдается сообщение об ошибке (то есть результат выполнения такой же, как для таблиц InnoDB);

• если установлен режим STRICT_TRANS_TABLES, а некорректное значение обнаружено в одной из последующих добавляемых строк, то некорректное значение преобразуется в допустимое и генерируется предупреждение (как в нестрогом режиме);

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


...

Внимание!

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

 

Если вы задали для столбца таблицы свойство NOT NULL (тем самым запретив использовать значение NULL в качестве значения по умолчанию), но не задали отличное от NULL значение по умолчанию (свойство DEFAULT), и если вы удалили значение столбца по умолчанию с помощью команды ALTER TABLE, то в строгом режиме считается, что у такого столбца нет значения по умолчанию. Поэтому при добавлении строки в таблицу необходимо явно задать значение для такого столбца, в противном случае операция INSERT полностью отменяется и выдается сообщение об ошибке. Исключение составляют столбцы с типом TIMESTAMP и ENUM, а также числовые столбцы со свойством AUTO_INCREMENT: для них в случае отсутствия явно заданного значения используются такие же значения, что и в нестрогом режиме.

Изменить режим взаимодействия вашего клиентского приложения с сервером вы можете с помощью команды

SET SQL_MODE = \'<Режим>\  

Например, команда

SET SQL_MODE = \'\  

устанавливает нестрогий режим, а команды

SET SQL_MODE = \'STRICT_TRANS_TABLES\  

и

SET SQL_MODE = \'STRICT_ALL_TABLES\  

устанавливают соответствующий строгий режим.

Команда SET SQL_MODE изменяет режим взаимодействия с сервером только для текущего соединения  и не влияет на взаимодействие сервера с другими клиентскими приложениями. Новый режим вступает в силу немедленно после выполнения команды и сохраняется только до момента отключения от сервера.

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

SET GLOBAL SQL_MODE = \'<Режим>\  

Режим, установленный глобально, применяется для всех вновь подключаемых к серверу клиентских приложений; ранее подключенные приложения продолжают работать в прежнем режиме. Чтобы новый режим вступил в силу для вашего приложения, необходимо отключиться от сервера и затем снова подключиться к нему. Глобальный режим сохраняется до момента перезапуска сервера MySQL.


...

Внимание!

В отличие от других клиентских приложений, графическая утилита MySQL Query Browser всегда взаимодействует с сервером в глобальном режиме. Установить для нее режим, отличный от установленного глобально, невозможно: команда SET SQL_MODE, выполненная в MySQL Query Browser, игнорируется. Таким образом, чтобы изменить режим для MySQL Query Browser, нужно изменить режим глобально с помощью команды SET GLOBAL SQL_MODE. При изменении глобального режима новый режим применяется к этой утилите сразу же, без переподключения к серверу.

 

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

2.5. Извлечение данных из таблиц

 Сделать закладку на этом месте книги

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

Простые запросы

Знакомство с запросами начнем с наиболее простой команды, которая выводит все данные, содержащиеся в таблице:

SELECT * FROM <Имя таблицы>;  

Например, в результате выполнения запроса

SELECT * FROM Customers;  

вы получите всю информацию о клиентах (см. рис. 2.2 и 2.4).


...

Примечание

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

 

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

SELECT name,phone,rating FROM Customers;  



SELECT name,phone,rating/1000 FROM CUSTOMERS;  



SELECT 2*2;  

возвращает результат 4 Результат запроса может содержать повторяющиеся строки. Например, клиенты могут иметь одинаковые рейтинги, поэтому запрос

SELECT rating FROM Customers;  



SELECT DISTINCT rating FROM Customers;  



ORDER BY <Имя столбца> [ASC или DESC]  

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

SELECT name,phone,rating FROM Customers  ORDER BY rating DESC, name;  



SELECT name,phone,rating FROM Customers  ORDER BY 3 DESC, 1;  

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

Условия отбора

Чтобы выбрать из таблицы строки, удовлетворяющие какому-либо критерию, добавьте в текст запроса выражение

WHERE <Условие отбора>  

Например, запрос

SELECT name,phone,rating FROM Customers WHERE rating = 1000;  



SELECT name,phone,rating FROM Customers  

WHERE name LIKE \'ООО%\' OR rating>1000  

ORDER BY rating DESC;  



SELECT <Список столбцов> FROM <Список таблиц>  WHERE <Условие отбора>;  

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

SELECT name,address,product_id,qty  

FROM Customers, Orders  

WHERE Customers.id = customer_id AND date = \'2007-12-12\  



SELECT L.name,R.name FROM Customers L, Customers R  WHERE L.rating = R.rating;  



SELECT L.name,R.name FROM Customers L, Customers R  WHERE L.rating = R.rating AND L.name<R.name;  



SELECT name FROM Customers  

WHERE id IN  

(SELECT DISTINCT customer_id FROM Orders  

WHERE product_id = 5);  



SELECT DISTINCT name FROM Customers, Orders  WHERE Customers.id = customer_id AND product_id = 5;  

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

SELECT * FROM Orders  WHERE amount = (SELECT MAX(amount) FROM Orders);  



Объединение результатов запросов

Чтобы объединить несколько запросов в одну SQL-команду и, соответственно, объединить результаты запросов, используется ключевое слово UNION. Запросы, объединяемые с помощью UNION, должны выводить одинаковое количество столбцов, и типы данных столбцов должны быть совместимы. При объединении результатов автоматически удаляются повторяющиеся строки; чтобы запретить удаление повторяющихся строк, вместо слова UNION нужно использовать выражение UNION ALL. Наконец, строки объединенного запроса можно упорядочить с помощью выражения ORDER BY. В качестве примера рассмотрим запрос, выводящий информацию о заказах с наибольшей и наименьшей суммой заказа:

SELECT * FROM Orders  

WHERE amount = (SELECT MAX(amount) FROM Orders)  

UNION  

SELECT * FROM Orders  

WHERE amount = (SELECT MIN(amount) FROM Orders)  

ORDER BY 1;  



INTO OUTFILE \'Путь и имя файла\' [FILEDS …] [LINES …]  

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

При необходимости вы можете также задать параметры FILEDS и LINES, которые имеют тот же смысл, что и параметры FILEDS и LINES команды LOAD DATA (см. подраздел «Загрузка данных из файла»). Если впоследствии файл будет загружаться в базу данных MySQL с помощью команды LOAD DATA, то в команде LOAD DATA нужно будет указать те же самые значения параметров FILEDS и LINES, которые использовались при выгрузке.

Команды SELECT… INTO OUTFILE и LOAD DATA можно использовать для резервного копирования таблиц или для переноса данных на другой сервер MySQL. Например, данные из таблицы Customers (Клиенты), сохраненные в файл с помощью команды

SELECT * from Customers INTO OUTFILE \'C:/data/Customers.txt\  

можно загрузить в таблицу Customers_copy (имеющую такую же структуру, что и таблица Customers) с помощью команды

LOAD DATA INFILE \'C:/data/Customers.txt\'  INTO TABLE Customers_copy;  


...

Внимание!

В случае выгрузки и последующей загрузки символьных данных в кодировке UTF-8 могут возникнуть проблемы, связанные с переменным количеством байтов на символ в этой кодировке. Если вы выгрузили данные из таблицы с кодировкой UTF-8, рекомендуем перед загрузкой преобразовать файл в какую-либо однобайтовую кодировку. Например, откроем файл с помощью программы Блокнот (Пуск → Все программы → Стандартные → Блокнот), в меню Файл выберите команду Сохранить как, а затем в стандартном окне Windows Сохранить как в поле Кодировка выберите из списка значение «ANSI» и нажмите кнопку Сохранить. При загрузке преобразованного файла укажите в команде LOAD DATA параметр CHARACTER SET cp1251 (см. подраздел «Вставка отдельных строк»).

 

Итак, вы освоили команду SELECT, которая предоставляет широкие возможности поиска и отбора данных. Последняя операция, которую мы обсудим в этой главе, – редактирование данных в таблицах.

2.6. Изменение данных

 Сделать закладку на этом месте книги

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

UPDATE <Имя таблицы>  

SET <Имя столбца 1> = <Значение 1>,  

…,  

<Имя столбца N> = <Значение N>  

[WHERE <Условие отбора>]  

[ORDER BY <Имя столбца> [ASC или DESC]]  

[LIMIT <Количество строк>];  

Например, если у клиента по фамилии Крылов изменился номер телефона, то обновить информацию в базе данных можно с помощью команды

UPDATE Customers SET phone = \'444-25-27\' WHERE id = 536;  

В команде UPDATE используются следующие основные параметры:

• имя редактируемой таблицы;

• SET <Имя столбца 1> = <Значение 1>, … , <Имя столбца N> = <Знaчение N> – список столбцов и новых значений для этих столбцов. Более подробную информацию о вставке значений в таблицу и о режимах взаимодействия с сервером MySQL вы можете найти в подразделе «Вставка отдельных строк». Задать новое значение вы можете также с помощью выражения, использующего прежние значения в строке. Например, удвоить рейтинги для всех клиентов можно с помощью команды

UPDATE Customers SET rating = rating*2;  

• WHERE <Условие отбора> – укажите условие отбора, чтобы изменения были применены только к тем строкам таблицы, которые удовлетворяют этому условию. Если условие отбора не задано, изменения будут применены ко всем строкам таблицы. Условия отбора мы рассматривали в подразделе «Условия отбора». В условиях отбора можно использовать вложенный запрос (см. подраздел «Вложенные запросы»), который не должен обращаться к самой модифицируемой таблице.

• ORDER BY <Имя столбца> [ASC или DESC] – при необходимости вы можете указать, в каком порядке применять изменения к строкам таблицы. Обычно порядок применения изменений не влияет на результат выполнения операции. Однако в некоторых случаях последовательность действий может быть важна. Например, если вы установили предельное количество изменяемых строк (см. следующий пункт), то некоторые строки, удовлетворяющие условию отбора, могут остаться неизменными, а какие именно это будут строки – зависит от последовательности применения изменений. Другим подобным случаем является обновление значений первичного ключа или уникального индекса, которые не должны содержать повторяющихся значений, а наличие или отсутствие повторяющихся значений в столбце может зависеть от порядка применения изменений.

• LIMIT <Количество строк> – при необходимости вы можете указать максимальное количество строк таблицы, которые могут быть изменены командой UPDATE. Если это количество измененных строк достигнуто, операция завершается, даже если в таблице еще остались строки, которые удовлетворяют условию отбора и не были изменены.


...

Примечание

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

 

Следующая команда, которую мы рассмотрим, – это команда REPLACE, осуществляющая либо добавление, либо замещение строк таблицы. Она имеет те же параметры, что и команда INSERT (см. подраздел «Вставка отдельных строк»):

REPLACE [INTO] <Имя таблицы>  

[(<Список столбцов>)]  

VALUES  

(<Список значений 1>),  

(<Список значений 2>),  

 

(<Список значений N>);  

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

REPLACE INTO Products  

VALUES  

(3,\'Соковыжималка Мосбытприбор СШ-800\',  

\'Цвет: кремовый. Мощность: 350 Вт\',1299.99);  

мы тем самым заменим в таблице Products (Товары) прежнюю строку с идентификат


убрать рекламу






ором 3, содержавшую информацию о кофеварке (см. листинг 2.5 выше), новой строкой, также имеющей идентификатор 3, но содержащей информацию о соковыжималке.

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

И, наконец, последняя команда, которую мы рассмотрим, – команда удаления строк таблицы:

DELETE FROM <Имя таблицы>  

[WHERE <Условие отбора>]  

[ORDER BY <Имя столбца> [ASC или DESC]]  

[LIMIT <Количество строк>];  

Например, информацию о клиенте по фамилии Петров вы можете удалить из таблицы Customers с помощью команды

DELETE FROM Customers WHERE id = 534;  

Параметры команды DELETE аналогичны соответствующим параметрам команды UPDATE. В результате выполнения этой команды будут удалены строки таблицы, удовлетворяющие условию отбора, а если условие отбора не задано, – все строки таблицы. При этом с помощью параметра LIMIT можно указать предельное количество удаляемых строк, а с помощью параметра ORDER BY – последовательность удаления строк.


...

Примечание

При удалении строк родительской таблицы выполняются проверки целостности связи (см. описание параметров внешнего ключа в пункте «Ключевые столбцы и индексы»).

 

Итак, мы освоили операции изменения и удаления строк таблицы: команды UPDATE (обновление), REPLACE (замещение) и DELETE (удаление). Подведем итоги второй главы.

2.7. Резюме

 Сделать закладку на этом месте книги

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

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

Глава 3 Операторы и функции языка SQL

 Сделать закладку на этом месте книги

В этой главе вы познакомитесь с функциями и операторами, с помощью которых можно создавать выражения – формулы, вычисляющие какое-либо значение (числовое, логическое, символьное и др.). Наиболее часто выражения используются в SQL-запросах: как для вычисления значений, выводимых запросом, так и в условиях отбора. С помощью выражений можно также задавать условия отбора в SQL-командах UPDATE и DELETE, значения, добавляемые в таблицу, в командах INSERT и UPDATE и многое другое.

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

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

3.1. Операторы и функции проверки условий

 Сделать закладку на этом месте книги

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

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

Вначале мы рассмотрим операторы сравнения.

Операторы сравнения

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

• 1 (TRUE) – истинное значение, которое свидетельствует о том, что сравнение верно, условие выполнено;

• 0 (FALSE) – ложное значение, которое свидетельствует о том, что сравнение неверно, условие не выполнено;

• NULL – неопределенное значение, которое свидетельствует о том, что проверить условие невозможно, поскольку один из операндов равен NULL.


...

Примечание

Иногда проверить условие можно несмотря на то, что один из операндов равен NULL (см., например, описание операторов BETWEEN и IN в этом подразделе); в этом случае возвращается значение 1 или 0.

 

Начнем с рассмотрения оператора, проверяющего равенство двух операндов.

Оператор x = y

Оператор «равно» возвращает следующие значения:

• 1 (TRUE) – если х и y  совпадают;

• 0 (FALSE) – если х  и y  различны;

• NULL – если по крайней мере один из операндов равен NULL.

Например, выберите из таблицы Customers (Клиенты) строки, в которых значение в столбце name равно «Крылов»:

SELECT * FROM Customers WHERE name = \'КРЫЛОВ\  



SELECT 100 = NULL, 100< = >NULL, NULL = NULL, NULL< = >NULL;  




...

Примечание

Если x является символьной строкой, то перед сравнением с TRUE или FALSE эта строка преобразуется в число. Для этого отбрасываются все символы, начиная с первого, недопустимого в числовом значении, а начальная подстрока рассматривается как число. Если первый символ в значении – буква или пустая строка («»), то x приравнивается к нулю.

 

Выражениях IS UNKNOWN их IS NULL возвращают 1 (TRUE), еслихравен NULL, и 0 (FALSE) – в остальных случаях.

Например, запрос

SELECT 100 IS TRUE, 0 IS TRUE, \'2007-12-12\' IS TRUE,  \'0000-00-00\' IS TRUE, NULL IS TRUE;  



SELECT 100 IS FALSE, 0 IS FALSE, \'2007-12-12\' IS FALSE,  \'0000-00-00\' IS FALSE, NULL IS FALSE;  



SELECT 100 IS NULL, 0 IS NULL, \'2007-12-12\' IS NULL,  \'0000-00-00\' IS NULL, NULL IS NULL;  




...

Примечание

Если столбец определен как DATE NOT NULL (или DATETIME NOT NULL), то значение этого столбца, равное «0000-00-00» (или «0000-00-00 00:00:00»), рассматривается оператором IS NULL как NULL. Например, если при создании таблицы Orders (Заказы) (см. листинг 2.4 в главе 2) задать для столбца date (дата) свойство NOT NULL, то запрос SELECT * FROM Orders WHERE date IS NULL; выведет строки, в которых дата заказа равна «0000-00-00».

 

Следующие операторы проверяют несовпадение двух операндов.

Операторы x! = y, x <> y

Оператор «не равно» возвращает следующие значения:

• 1 (TRUE) – если х и y  различны;

• 0 (FALSE) – если х  и y  совпадают;

• NULL – если по крайней мере один из операндов равен NULL.

Например, запрос

SELECT * FROM Customers WHERE name! = \'КРЫЛОВ\  



SELECT 100 IS NOT TRUE, 0 IS NOT TRUE,  

\'2007-12-12\' IS NOT TRUE, \'0000-00-00\' IS NOT TRUE,  

NULL IS NOT TRUE;  



SELECT 100 IS NOT FALSE, 0 IS NOT FALSE,  

\'2007-12-12\' IS NOT FALSE, \'0000-00-00\' IS NOT FALSE,  

NULL IS NOT FALSE;  



SELECT 100 IS NOT NULL, 0 IS NOT NULL,  

\'2007-12-12\' IS NOT NULL, \'0000-00-00\' IS NOT NULL,  

NULL IS NOT NULL;  



SELECT * FROM Customers WHERE name<\'КРЫЛОВ\  

возвращает пустой результат, поскольку «Крылов» – наименьшее в алфавитном порядке значение в столбце name (имя) таблицы Customers (Клиенты). Предшествующих ему значений в столбце нет, и, следовательно, ни одна строка не удовлетворяет условию отбора.

Следующий оператор проверяет, не превосходит ли первый операнд второго.

Оператор x < = y

Оператор «меньше либо равно» возвращает следующие значения:

• 1 (TRUE) – если х равно y  или х меньше у;

• 0 (FALSE) – если х больше у;

• NULL – если по крайней мере один из операндов равен NULL.

Например, запрос

SELECT * FROM Customers WHERE name< = \'КРЫЛОВ\  

возвращает результат, представленный в табл. 3.1.

Следующий оператор проверяет, больше ли первый операнд, чем второй.

Оператор x > y

Оператор «больше» возвращает следующие значения:

• 1 (TRUE) – если х больше у;

• 0 (FALSE) – если х равно у  или х меньше у;

• NULL – если по крайней мере один из операндов равен NULL.

Например, запрос

SELECT * FROM Customers WHERE name>\'КРЫЛОВ\  

возвращает результат, представленный в табл. 3.6.

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

Оператор x > = y

Оператор «больше либо равно» возвращает следующие значения:

• 1 (TRUE) – если х  равно у  или х больше у;

• 0 (FALSE) – если х меньше у;

• NULL – если по крайней мере один из операндов равен NULL.

Например, запрос

SELECT * FROM Customers WHERE name> = \'КРЫЛОВ\  



SELECT * FROM Customers  WHERE name BETWEEN \'КРЫЛОВ\' AND \'OOO «Кускус»\  



SELECT * FROM Customers  WHERE name NOT BETWEEN \'КРЫЛОВ\' AND \'ООО «Кускус»;  



SELECT * FROM Customers WHERE rating IN (500,1500,2500);  

возвращает результат, представленный в табл. 3.12.

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

Например, запрос

SELECT * FROM Orders WHERE (date,product_id) IN  

((\'2007-12-12\',1),(\'2007-12-12\',2),  

(\'2007-12-13\',1),(\'2007-12-13\',2));  



SELECT * FROM Customers WHERE rating NOT IN (500,1500);  

возвращает результат, представленный в табл. 3.11.

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

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

Оператор x LIKE y

Оператор сравнения с шаблоном возвращает следующие значения:

• 1 (TRUE) – если х соответствует шаблону у;

• 0 (FALSE) – если х не соответствует шаблону у;

• NULL – если х или у  равен NULL.

В шаблоне можно использовать два специальных подстановочных символа:

• % – на месте знака процента может быть любое количество произвольных символов операнда х;  

• _ – на месте знака подчеркивания может быть ровно один произвольный символ операнда х.  

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

SELECT * FROM Customers WHERE name LIKE \'%\'\'%\'\'%\  




...

Примечание

Более сложные шаблоны вы можете создавать с помощью регулярных выражений. Регулярные выражения представляют собой универсальный язык описания текстов. Информацию о синтаксисе регулярных выражений вы можете найти на веб-странице https://ru.wikipedia.org/wiki/Регулярные_выражения. Для сравнения строки с шаблоном, содержащим регулярные выражения, необходимо вместо оператора LIKE использовать оператор REGEXP.

 

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

Оператор x NOT LIKE y

Оператор NOT LIKE возвращает результат, противоположный результату выполнения оператора LIKE:

• значение 0 (FALSE) – если х соответствует шаблону у;

• значение 1 (TRUE) – если х не соответствует шаблону;

• значение NULL – если х или у  равен NULL.

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

SELECT * FROM Customers WHERE name NOT LIKE \'%»%\  



ALTER TABLE Customers  CONVERT TO CHARACTER SET cp1251 COLLATE cp1251_general_ci;  

В этом случае запрос

SELECT name, STRCMP(name,\'крылов\') FROM Customers;  



ALTER TABLE Customers  

CONVERT TO CHARACTER SET cp1251 COLLATE cp1251_general_cs;  

SELECT name, STRCMP(name,\'крылов\') FROM Customers;  



ALTER TABLE Customers  

CONVERT TO CHARACTER SET cp1251 COLLATE cp1251_bin;  

SELECT name, STRCMP(name,\'крылов\') FROM Customers;  



ALTER TABLE Orders DROP FOREIGN KEY orders_ibfk_1;  

Затем изменим тип таблицы Products на MyISAM:

ALTER TABLE Products ENGINE MyISAM;  

И наконец, создадим полнотекстовый индекс для столбца description:

ALTER TABLE Products ADD FULLTEXT (description);  

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

SELECT * FROM Products  WHERE MATCH (description) AGAINST (\'Чайник Мосбытприбор\');  



SELECT * FROM Products  

WHERE MATCH (description)  

AGAINST (\'-Чайник +Мосбытприбор\' IN BOOLEAN MODE);  



Еще один режим полнотекстового поиска – расширенный режим. Он отличается от обычного тем, что в результат запроса, помимо строк, отвечающих заданному критерию поиска, включаются строки, найденные по принципу схожести с несколькими первыми строками, наиболее релевантными исходному критерию. Расширенный режим полезен при поиске «наугад», когда заранее неясно, по какому критерию искать нужную строку. Для поиска в логическом режиме необходимо включить в выражение MATCH… AGAINST… параметр WITH QUERY EXPANSION:

SELECT * FROM Products  

WHERE MATCH (description)  

AGAINST (\'Чайник Мосбытприбор\' WITH QUERY EXPANSION);  

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

Операторы сравнения с результатами вложенного запроса

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

EXISTS

Оператор EXISTS возвращает значение 1 (TRUE), если результат подзапроса содержит хотя бы одну строку, и значение 0 (FALSE), если подзапрос выдает пустой результат.

Например, получить список товаров, заказанных по крайней мере одним клиентом, можно с помощью запроса

SELECT * FROM Products  

WHERE EXISTS  

(SELECT * FROM Orders  

WHERE product_id = Products.id  

AND customer_id IS NOT NULL);  



SELECT * FROM Customers WHERE NOT EXISTS  

(SELECT * FROM Products WHERE NOT EXISTS  

(SELECT * FROM Orders  

WHERE product_id = Products.id  

AND customer_id = Customers.id));  

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

В нашей базе данных нет ни одного клиента, который бы заказал все наименования товаров (см. листинги 2.5 и 2.6), поэтому рассмотренный нами запрос возвращает пустой результат.

Далее мы рассмотрим операторы IN и NOT IN применительно к вложенным запросам.

IN и NOT IN Операторы IN и NOT IN, с которыми вы познакомились в подразделе «Операторы сравнения», позволяют проверить, содержится ли некоторое значение в результате подзапроса. Рассмотрим еще один пример использования оператора IN.

SELECT * FROM Customers WHERE \'2007-12-12\' IN  (SELECT date FROM Orders WHERE Customers.id = customer_id);  

Для каждого клиента, то есть строки таблицы Customers, вложенный запрос выдает даты заказов этого клиента. Если дата «2007-12-12» есть среди этих дат, то строка таблицы Customers включается в результат запроса. Таким образом, запрос выводит информацию о тех клиентах, которые сделали заказ 12 декабря 2007 г. Результат этого запроса представлен в табл. 3.11.

Вложенный запрос, результат которого обрабатывается с помощью оператора IN, может возвращать несколько столбцов, но в этом случае и значение слева от оператора должно быть составным с таким же количеством компонентов (составные значения мы рассмотрели в пункте «Оператор х IN (<Список значений>)».

Далее мы разберем ключевые слова ANY и SOME.

ANY, SOME Ключевое слово ANY («какой-либо») используется совместно с операторами сравнения, описанными в подразделе «Операторы сравнения». При использовании ANY результат сравнения будет верным, если он верен хотя бы для одного из значений, выданных подзапросом. Другими словами, результатом вычисления выражения

x <Оператор сравнения> ANY (<Вложенный запрос>)  

может быть одно из следующих значений:

• 1 (TRUE) – если среди выданных подзапросом значений есть хотя бы одно значение y, для которого выполнено условие x  <Оператор сравнения> y  ;

• 0 (FALSE) – если среди выданных подзапросом значений нет ни одного такого значения y, для которого выражение x  <Оператор сравнения> y  истинно (TRUE) или не определено (NULL), в том числе, если подзапрос возвращает пустой результат;

• NULL – если среди выданных подзапросом значений нет ни одного такого значения y, для которого выражение x  <Оператор сравнения> y  истинно TRUE), но в то же время есть одно или несколько значений y,  для которых это выражение не определено (NULL).

Например, вывести информацию о клиентах, которые сделали хотя бы один заказ на сумму более 5000, можно с помощью запроса

SELECT * FROM Customers WHERE 5000 < ANY  (SELECT amount FROM Orders WHERE Customers.id = customer_id);  

Для каждого клиента вложенный подзапрос получает из таблицы Orders (Заказы) суммы заказов (столбец amount) этого клиента. Затем эти суммы сравниваются с величиной 5000, и запись о клиенте попадет в результат запроса, если хотя бы одна из этих сумм превышает 5000. Таким образом, запрос возвращает результат, представленный в табл. 3.11. Отметим, что вложенный запрос может быть только правым  операндом для оператора сравнения: например, рассмотренный выше запрос нельзя переписать в виде

SELECT * FROM Customers WHERE  

ANY (SELECT amount FROM Orders  

WHERE Customers.id = customer_id)  

> 5000;  

Ключевое слово SOME является синонимом ключевого слова ANY. Далее мы рассмотрим ключевое слово ALL. ALL Ключевое слово ALL («все»), как и ANY, используется совместно с операторами сравнения, описанными в подразделе «Операторы сравнения». При использовании ALL результат сравнения будет верным, если он верен для всех  значений, выданных подзапросом. Другими словами, результатом вычисления выражения

x <Оператор сравнения> ALL <Вложенный запрос>  

может быть одно из следующих значений:

• 1 (TRUE) – если условие х <Оператор сравнения> у  выполнено для всех у,  выданных подзапросом, а также в случае, если подзапрос возвращает пустой результат;

• 0 (FALSE) – если среди выданных подзапросом значений есть такое значение у, для которого выражение х <Оператор сравнения> у  ложно (FALSE);

• NULL – в остальных случаях.

Например, запрос

SELECT * FROM Customers WHERE 5000 < ALL  (SELECT amount FROM Orders WHERE Customers.id = customer_id);  

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

SELECT * FROM Customers  

WHERE 5000 < ALL  

(SELECT amount FROM Orders  

WHERE Customers.id = customer_id)  

AND EXISTS  

(SELECT amount FROM Orders  

WHERE Customers.id = customer_id);  

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

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

Логические операторы

Логические операторы позволяют построить сложное условие отбора на основе операторов сравнения. Операнды логических операторов рассматриваются как логические значения: TRUE, FALSE и NULL. При этом число 0 и нулевая дата и/или время («0000-00-00 00:00:00») считаются ложными значениями (FALSE), а отличные от нуля числа и даты – истинными значениями (TRUE) (более подробно об этом рассказывалось в пункте «Оператор х IS у, где у  – TRUE, FALSE, UNKNOWN или NULL»). Начнем с изучения оператора AND.

Оператор x AND y

Оператор AND («и») возвращает следующие значения:

• 1 (TRUE) – если оба операнда – истинные значения;

• 0 (FALSE) – если один или оба операнда – ложные значения;

• NULL – в остальных случаях.

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

Например, запрос

SELECT * FROM Customers  WHERE name LIKE \'ООО%\' AND rating>1000;  

не выводит ни одной строки. В таблице Customers (Клиенты) есть имена, начинающиеся с «ООО», и рейтинги, превышающие 1000, но ни одна из строк не удовлетворяет обоим этим условиям одновременно.

Пара символов && является синонимом оператора AND. Следующий оператор, который мы рассмотрим, – это оператор OR.

Оператор x OR y

Оператор OR («или») возвращает следующие значения:

• 1 (TRUE) – если один или оба операнда – истинные значения;

• 0 (FALSE) – если оба операнда – ложные значения;

• NULL – в остальных случаях.

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

Например, запрос

SELECT * FROM Customers  WHERE name LIKE \'ООО%\' OR rating>1000;  

выводит строки таблицы Customers (Клиенты), в которых имя начинается с «ООО», а также строки, в которых рейтинг больше 1000 (см. табл. 3.6). Пара символов | |является синонимом оператора OR. Следующий оператор, который мы рассмотрим, – это оператор XOR. Оператор x XOR y

Оператор XOR («исключающее или») возвращает следующие значения:

• 1 (TRUE) – если один из операндов – истинное значение, а другой – ложное;

• 0 (FALSE) – если оба операнда либо истинные значения, либо ложные;

• NULL – если хотя бы один из операндов равен NULL.

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

Например, запрос

SELECT * FROM Customers  WHERE name LIKE \'ООО%\' XOR rating>500;  

выводит строки таблицы Customers, в которых имя начинается с «ООО», а также те строки, в которых рейтинг больше 500, за исключением тех строк, в которых эти условия выполняются одновременно (см. табл. 3.15). Наконец, рассмотрим последний логический оператор – NOT. Оператор NOT x

Оператор NOT («не», то есть «отрицание») возвращает следующие значения:

• 1 (TRUE) – если операнд – ложное значение;

• 0 (FALSE) – если операнд – истинное значение;

• NULL – если операнд равен NULL.

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

Например, запрос

SELECT * FROM Customers  WHERE NOT (name LIKE \'ООО%\' OR rating>1000);  

выводит те строки таблицы Customers, для которых условие name LIKE \'ООО% OR rating>10 0 0 не выполнено и которые, следовательно, не были выведены запросом из пункта «Оператор х OR у». Таким образом, запрос возвращает результат, представленный в табл. 3.1.

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

Операторы и функции, основанные на сравнении

В этом подразделе я кратко расскажу об операторах и функциях, которые, как и операторы из подраздела «Операторы сравнения», сравнивают две или несколько величин, однако возвращают не логическое значение (TRUE, FALSE или NULL), а один из своих аргументов (или порядковый номер аргумента). Рассмотрим эти функции.

• LEAST( a  1, a  2,…, an  )

Данная функция возвращает наименьший из своих аргументов (либо NULL, если один из аргументов равен NULL). Например, выражение LEAST(000 "Кускус",\'Петров\',\'Крылов\') возвра


убрать рекламу






щает значение «Крылов». Отметим, что в функции LEAST() можно указать только фиксированное количество аргументов. Например, невозможно получить первое в алфавитном порядке имя клиента с помощью запроса SELECT LEAST(name) FROM Customers; вместо этого необходимо использовать групповую функцию MIN() (о ней вы узнаете в разделе «Групповые функции»).

• GREATEST( a  1, a  2,…, an  ).

Данная функция возвращает наибольший из своих аргументов (либо NULL, если по крайней мере один из аргументов равен NULL). Например, выражение GREATEST (ООО «Кускус», Петров, Крылов) возвращает значение «Петров». Как и в функции LEAST(), в функции GREATEST() можно указать только фиксированное количество аргументов. Например, невозможно получить последнее в алфавитном порядке имя клиента с помощью запроса SELECT GREATEST(name) FROM Customers; вместо этого необходимо использовать групповую функцию MAX() (см. раздел «Групповые функции»).

• INTERVAL( a  , b  1, b  2,…, bn  ), где b  1 < b  2 < … < bn.  

Функция INTERVAL возвращает порядковый номер наибольшего из чисел b.,  не превосходящих числа a:  

•  bi  ≤ a  < bi  +1 – функция возвращает номер i  ;

•  a  < b  1 – функция возвращает значение 0:

•  a  > bn  – функция возвращает значение n  ;

•  a  равно NULL – функция возвращает значение -1.

Все аргументы этой функции являются целыми числами (если вы укажете аргумент с другим типом данных, он будет преобразован в целочисленное значение). Чтобы функция возвращала корректный результат, необходимо, чтобы значения bi  были упорядочены, то есть выполнялось условие b1 < b2 <… < bn.  Например, выражение INTERVAL(1500, 1000, 2000, 3000) возвращает значение 1.

• GOALESCE ( a  1, a  2,…, an  )

Данная функция возвращает первый из аргументов, который отличен от NULL (а если все аргументы равны NULL, то возвращает значение NULL). Например, выражение COALESCE(NULL,1/0,\'TeKCT\') возвращает значение «Текст», поскольку это первый аргумент, отличный от NULL (при делении на 0 результатом является NULL).

• IF(a,b,c).

Данная функция проверяет, является ли истинным логическое значение или выражение a.  Если a  истинно (то есть является числом, датой или временем, отличным от нулевых), то функция возвращает значение b,  а если a  ложно или равно NULL, функция возвращает значение c.  Например, если требуется удвоить те рейтинги клиентов, которые превышают 1000, это можно сделать с помощью команды

UPDATE Customers  SET rating = IF(rating>1000,rating*2,rating);  

• IFNULL(a,b). Данная функция возвращает значение a,  если это значение отлично от NULL, и значение b, если a  равно NULL. Например, если требуется всем клиентам, чей рейтинг не указан (равен NULL), присвоить рейтинг 500, это можно сделать с помощью команды

UPDATE Customers SET rating = IFNULL(rating,500);  

• NULLIF(a,b). Данная функция возвращает значение NULL, если a  = b, и значение a  в противном случае. Например, если требуется выполнить операцию, обратную операции из предыдущего пункта, то есть всем клиентам с рейтингом 500 присвоить неопределенный рейтинг, это можно сделать с помощью команды

UPDATE Customers SET rating = NULLIF(rating,500);  

• CASE x WHEN a1 THEN b1.

[WHEN a2 THEN b2]  

 

[WHEN an THEN bn]  

[ELSE b0]  

END  

или

CASE WHEN x1 THEN b1  

[WHEN x2 THEN b2]  

 

[WHEN xn THEN bn]  

[ELSE b0]  

END  

Оператор CASE обеспечивает последовательную проверку списка условий и возвращает значение в зависимости от того, какое из условий выполнено. В первом варианте значение выражения х сравнивается со значениями a1, a2,…, an  :

• если х = ai  , то оператор возвращает значение bi;  

• если значение выражения х  не совпало ни с одним из a,  то оператор возвращает значение b0  , заданное с помощью параметра ELSE;

• если значение выражения х  не совпало ни с одним из ai  , а параметр ELSE не задан, то оператор возвращает значение NULL.

Во втором варианте последовательно проверяется истинность логических выражений хi:  

• если хi  истинно, то оператор возвращает значение bi;  

• если ни одно из выражений хi  не является истинным, то оператор возвращает значение b0  , заданное с помощью параметра ELSE;

• если ни одно из выражений хi  не является истинным, а параметр ELSE не задан, то оператор возвращает значение NULL.

Например, запрос

SELECT date,customer_id,amount,  

CASE WHEN amount< = 5000 THEN \'Малый\'  

WHEN amount BETWEEN 5000 AND 15000 THEN \'Средний\'  

WHEN amount>15000 THEN \'Крупный\'  

END  

FROM Orders  

ORDER BY customer_id,amount DESC;  



3.2. Групповые функции

 Сделать закладку на этом месте книги

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

Перечень групповых функций

Для вычисления обобщающего значения столбца таблицы предназначены следующие функции.

SUM()

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

Например, запрос

SELECT SUM(rating) FROM Customers;  



SELECT SUM(DISTINCT rating) FROM Customers;  



SELECT SUM(amount) FROM Orders WHERE customer_id = 533;  



SELECT AVG(rating) FROM Customers;  



SELECT AVG(DISTINCT rating) FROM Customers;  



SELECT * FROM Customers  WHERE rating > (SELECT AVG(rating) FROM Customers);  

выводит информацию о клиентах, чей рейтинг выше среднего (см. результат запроса в табл. 3.12). Вложенный запрос возвращает средний рейтинг клиента (см. табл. 3.26), а внешний – отбирает строки таблицы Customers, в которых значение столбца rating больше значения, возвращенного подзапросом. Отметим, что в данном случае вложенный запрос возвращает единственное  значение, поэтому с оператором «больше» нет необходимости использовать ключевое слово ANY или ALL (о них рассказывалось в подразделе «Операторы сравнения с результатами вложенного запроса»).

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

MAX()

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

Например, запрос

SELECT MAX(rating) FROM Customers;  



SELECT * FROM Customers  WHERE rating = (SELECT MAX(rating) FROM Customers);  

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

Далее мы рассмотрим функцию нахождения минимального значения столбца.

MIN()

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

Например, запрос

SELECT MIN(rating) FROM Customers;  



SELECT * FROM Customers  WHERE rating = (SELECT MIN(rating) FROM Customers);  

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

Далее мы рассмотрим функцию подсчета количества значений.

COUNT()

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

Например, запрос

SELECT COUNT(rating) FROM Customers;  



SELECT COUNT(DISTINCT rating) FROM Customers;  



SELECT COUNT(*) FROM Customers;  

будет больше, чем значение, выводимое запросом

SELECT COUNT(rating) FROM Customers;  

(разность этих значений совпадает с количеством строк, в которых значение в столбце rating равно NULL).

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

Например, запрос

SELECT * FROM Customers  

WHERE 2 < = (SELECT COUNT(*) FROM Orders  

WHERE Customers.id = customer_id);  



SELECT VAR_POP(rating) FROM Customers;  



SELECT VAR_SAMP(rating) FROM Customers;  



SELECT STDDEV_POP(rating) FROM Customers;  



SELECT STDDEV_SAMP(rating) FROM Customers;  



SELECT GROUP_CONCAT(name) FROM Customers;  



SELECT GROUP_CONCAT(DISTINCT name  ORDER BY name ASC SEPARATOR \\') FROM Customers;  



Параметр GROUP BY

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

Например, запрос

SELECT customer_id, SUM(amount) FROM Orders  GROUP BY customer_id;  



SELECT GROUP_CONCAT(name),rating FROM Customers  GROUP BY rating;  



SELECT customer_id, SUM(amount) FROM Orders  GROUP BY customer_id WITH ROLLUP;  



SELECT customer_id, COUNT(amount) FROM Orders  

WHERE amount>5000  

GROUP BY customer_id;  



SELECT customer_id, SUM(amount) FROM Orders  

GROUP BY customer_id  

HAVING SUM(amount)> = 20000;  



3.3. Числовые операторы и функции

 Сделать закладку на этом месте книги

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

Арифметические операторы

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

•  а  + b.  

Оператор сложения. Возвращает сумму операндов a  и b.  

•  а – b.  

Оператор вычитания. Возвращает разность операндов a  и b.  

При использовании с одним операндом меняет его знак, например – (3 + 2) = -5.

•  а  * b.  

Оператор умножения. Возвращает произведение операндов a  и b.  

•  а  / b.  

Оператор деления. Возвращает частное от деления a  на b.  

•  а  DIV b.  

Оператор деления c остатком, или целочисленного деления. Возвращает целую часть частного от деления a  на b.  Например,:

• 7 DIV 2 = 3,

• (-7) DIV 2 = -3,

• 7 DIV (-2) = -3,

• (-7) DIV (-2) = 3.

• a % b.  

Оператор вычисления остатка. Возвращает остаток от целочисленного деления a  на b: величину a  % b  = a – b x (a  DIV b). Например,:

• 7 % 2 = 1,

• (– 7) % 2 = -1,

• 7 % (-2) = 1,

• (-7) % (-2) = -1.

В следующем подразделе мы рассмотрим алгебраические функции.

Алгебраические функции

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

• ABS(x).

Возвращает абсолютную величину (модуль) числа x. Например, ABS(10) = ABS(-10) = 10.

• CEIL(x), CEILING(x).

Функция округления в большую сторону. Возвращает наименьшее из целых чисел, которые больше или равны x. Например,:

• CEIL(12345.6789) = 12346,

• CEIL(-12345.6789) = -12345.

• CRC32(\'Символьное значение\').

Функция вычисляет контрольную сумму для последовательности символов с помощью алгоритма CRC32. Подробнее об алгоритмах CRC вы можете прочитать здесь: https://ru.wikipedia.org/wiki/CRC32. Например, CRC32(\'Beк живи – век учись\') = 4171076480.

• EXP(x).

Экспонента. Возвращает ex  (экспоненту числа x).

• FLOOR(x).

Функция округления в меньшую сторону. Возвращает наибольшее из целых чисел, не превосходящих x.  Например,:

• FLOOR(12345.6789) = 12345,

• FLOOR(-12345.6789) = -12346.

• LN(x), LOG(x).

Возвращает Inx  (натуральный логарифм числа x). Таким образом, LN(EXP(y)) = y.  

• LOG10(x).

Возвращает log10x (логарифм числа x  по основанию 10). Например, LOG10(100) = 2.

• LOG2(x).

Возвращает log2x (логарифм числа x  по основанию 2). Например, LOG2(16) = 4.

• LOG(a,x).

Возвращает logax (логарифм числа x  по основанию a). Например, LOG(2,16) = LOG2(16) = 4.

• MOD(a,b).

Синоним выражения a  % b, возвращает остаток от целочисленного деления a  на b.  

• PI().

Возвращает число π = 3,14159….

• POW(x,y), POWER(x,y).

Функция возведения в степень. Возвращает xy.  

Например, POW(2, 10) = 1024.

• RAND().

Возвращает случайное число в интервале от 0 до 1.

• RAND(x).

Возвращает псевдослучайное число в интервале от 0 до 1, при этом целое число x  используется как начальное значение генератора псевдослучайных чисел. Возвращаемое значение при этом предопределено, например, RAND(2 0) всегда возвращает значение 0,1588826125104 7.

• ROUND(x).

Функция округления до целого. Возвращает целое число, ближайшее к x.

• ROUND(x, n).

Функция округления. Если n  > 0, возвращает ближайшее к x  число с n  знаками после разделителя. Если n  = 0, возвращает ближайшее к x  целое число: ROUND(x,0) = ROUND(x). Если n  < 0, возвращает ближайшее к x  целое число, заканчивающееся на n  нулей. Например,:

ROUND(12345.6789,2) = 12345.68,

ROUND(12345.6789,0) = 12346,

ROUND(12345.6789,-2) = 12300,

ROUND(-12345.6789,2) = -12345.68.

• SIGN(x).

Функция получения знака. Возвращает значение 1, если x  > 0, значение 0, если х = 0, и значение – 1, если x  < 0.

• SQRT(x).

Возвращает √x (квадратный корень из x).

• TRUNCATE(x, n).

Функция отбрасывания «лишних» цифр. Если n  > 0, возвращается число, состоящее из целой части числа x  и n  его первых знаков после разделителя. Если n  = 0, возвращается целая часть x. Если n  < 0, возвращается число, в котором последние n  цифр заменены нулями. Например,:

TRUNCATE(12345.6789,2) = 12345.67,

TRUNCATE(12345.6789,0) = 12345,

TRUNCATE(12345.6789,-2) = 12300,

TRUNCATE(-12345.6789,2) = -12345.67.

В следующем подразделе мы рассмотрим алгебраические функции.

Тригонометрические функции

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

• SIN(x).

Возвращает синус угла величиной в x  радиан.

• COS(x).

Возвращает косинус угла величиной в x  радиан.

• TAN(x).

Возвращает тангенс угла величиной в x  радиан.

• COT(x).

Возвращает котангенс угла величиной в x  радиан.

• ASIN(x).

Возвращает арксинус числа x,  то есть величину угла (в радианах, от – π / 2 до π / 2), синус которой равен x.

• ACOS(x).

Возвращает арккосинус числа x,  то есть величину угла (в радианах, от 0 до π), косинус которой равен x.  

• ATAN(x).

Возвращает арктангенс числа x,  то есть величину угла (в радианах, от – π / 2 до π / 2), синус которой равен x.

• ATAN2(x,y), ATAN(x,y).

Возвращает величину угла (в радианах, от – π до π) между векторами с координатами (1,0) и (x,y), иными словами, величину угла между осью абсцисс и прямой, соединяющей точки (0,0) и (x,y)  на координатной плоскости. Совпадает с ATAN(y/x), если x  > 0.

• DEGREES(x).

Возвращает градусную меру угла, радианная мера которого равна x  радиан. Например, DEGREES(PI()) = 180.

• RADIANS(x).

Возвращает радианную меру угла, градусная мера которого равна x  градусов. Например, RADIANS(18 0) = 3,1415926535898.

Итак, мы обсудили основные числовые функции. Далее мы кратко рассмотрим функции, оперирующие значениями даты и времени.

3.4. Функции даты и времени

 Сделать закладку на этом месте книги

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

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

Функции получения текущей даты и времени

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

• CURDATE(), CURRENT_DATE(), current_date.

Возвращают текущую дату.

• CURTIME(), CURRENT_TIME(), current_time.

Возвращают текущее время.

• NOW(), CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP, LOCALTIME(), LOCALTIME, LOCALTIMESTAMP(), LOCALTIMESTAMP.

Возвращают текущую дату и время.

• SYSDATE().

Возвращает текущую дату и время Windows. В отличие от остальных функций, которые возвращают дату и/или время начала выполнения SQL-команды, функция SYSDATE() возвращает время своего вызова. Таким образом, если в одной SQL-команде функция SYSDATE() вызывается несколько раз, то возвращаемые ею значения могут быть различны.

• UTC_DATE(), UTC_DATE.

Возвращает текущую дату по UTC в формате «YYYY-MM-DD» (или, в зависимости от контекста, «YYYYMMDD»).


...

Примечание

UTC – универсальное скоординированное время, аналог гринвичского времени, основанный на атомном отсчете времени.

 

• UTC_TIME(), UTC_TIME.

Возвращает текущее время по UTC в формате «HH:MM:SS» (или, в зависимости от контекста, HHMMSS).

• UTC_TIMESTAMP(), UTC_TIMESTAMP.

Возвращает текущую дату и время по UTC в формате «YYYY-MM-DD HH:MM:SS» (или, в зависимости от контекста, «YYYYMMDDHHMMSS»).

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

Функции получения компонентов даты и времени

Рассмотрим функции, получающие в качестве аргумента дату и/или время и возвращающие один из компонентов аргумента.

• DATE(\'<Дaтa и время>\').

Функция DATE() получает в качестве аргумента дату или дату и время и возвращает дату, отсекая время. Например, DATE (2007-12-12 12:30:00) возвращает значение 2007-12-12.

• TIME(\'<Дaтa и время>\').

Функция TIME() получает в качестве аргумента время либо дату и время и возвращает время, отсекая дату. Например, TIME (2007-12-12 12:30:00) возвращает значение 12:30:00.

• DAY (\'<Дата или дата и время>\'), DAYOFMONTH (\'<Дата или дата и время>\').

Функции DAY() и DAYOFMONTH() получают в качестве аргумента дату или дату и время и выделяют из нее число (номер дня в месяце). Например, DAY(2007-12–12) возвращает значение 12.

• DAYNAME(\'<Дата или дата и время>\').

Функция DAYNAME() получает в качестве аргумента дату или дату и время и возвращает наименование дня недели, которым является эта дата. Например, DAYNAME(2007-12-12) возвращает значение Wednesday, поскольку 12 декабря 2007 г. – среда.

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

SET LC_TIME_NAMES=\'ru_RU\  

или

SET GLOBAL LC_TIME_NAMES=\'ru_RU\  

(о том, как действуют команды SET и SET GLOBAL, рассказывалось в подразделе «Вставка отдельных строк», когда речь шла об установке значения переменной sql_mode).


...

Примечание

Чтобы установить для отображения дат украинский или белорусский язык, присвойте переменной lc_time_names значение uk_UA или, соответственно, be_BY.

 

• DAYOFWEEK(\'<Дата или дата и время>\').

Функция DAYOFWEEK() получает в качестве аргумента дату или дату и время и вычисляет порядковый номер дня недели, которым является эта дата (1 – воскресенье, 2 – понедельник и т. д.). Например, DAYOFWEEK(2007-12-12) возвращает значение 4, и это означает, что 12 декабря 2007 г. – среда.

• WEEKDAY(\'<Дата или дата и время>\').

Функция WEEKDAY() получает в качестве аргумента дату или дату и время и вычисляет порядковый номер дня недели, которым является эта дата (0 – понедельник, 1 – вторник и т. д.). Например, DAYOFWEEK(2007-12-12) возвращает значение 2, и это означает, что 12 декабря 2007 г. – среда.

• DAYOFYEAR(\'<Дата или дата и время>\').

Функция DAYOFYEAR() получает в качестве аргумента дату или дату и время и вычисляет для нее порядковый номер дня в году. Например, DAYOFYEAR(2007-12-12) возвращает значение 34 6.

• LAST_DAY(\'<Дата или дата и время>\').

Функция LAST_DAY() получает в качестве аргумента дату или дату и время и возвращает дату, соответствующую последнему дню в месяце, которому принадлежит исходная дата. Например, LAST_DAY(2007-12-12) возвращает значение 2007-12-31, поскольку последнее число декабря – 31.

• WЕЕK (\'<Дата или дата и время>\' [,Правило нумерации]).

Функция WEEK() получает в качестве аргумента дату или дату и время и возвращает номер недели в году. По умолчанию неделя считается начинающейся с воскресенья, и первой неделей считается та неделя, воскресенье которой принадлежит данному году, а для дней, предшествующих первой неделе, номер недели равен 0. Например, WEEK(2007-12-31) = 52 и WEEK(2008-01-01) = 0.

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

• 0 – неделя считается начинающейся с воскресенья, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен 0. Например, WEEK(\'2008-01-01\',0) = 0.

• 1 – неделя считается начинающейся с понедельника, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен 0. Например, WEEK(\'2008-01-01\',1) = 1.

• 2 – неделя считается начинающейся с воскресенья, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году. Например, WEEK(\'2008-01-01\',2) = 52.

• 3 – неделя считается начинающейся с понедельника, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году. Например, WEEK(\'2008-01-01\',3) = 1.

• 4 – неделя считается начинающейся с воскресенья, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен 0. Например, WEEK(\'2008-01-01\',4) = 1.

• 5 – неделя считается начинающейся с понедельника, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен 0. Например, WEEK(\'2008-01-01\',5) = 0.

• 6 – неделя считается начинающейся с воскресенья, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году. Например, WEEK(\'2008-01-01\',6) = 1.

• 7 – неделя считается начинающейся с понедельника, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году. Например, WEEK(\'2008-01-01\',7) = 53.

• WEEKOFYEAR(\'<Дата или дата и время>\').

Является синонимом WEEKOFYEAR(<Дата или дата и время>,3).

• MONTHNAME(\'<Дата или дата и время>\').

Функция MONTHNAME() получает в качестве аргумента дату или дату и время и возвращает наименование месяца, которому принадлежит эта дата. Например, MONTHNAME(\'2007-12-12\') возвращает значение December. О том, как настроить вывод дат на русском языке, рассказывалось при описании функции DAYNAME().

• MONTH(\'<Дата или дата и время>\').

Функция MONTH() получает в качестве аргумента дату или дату и время и возвращает номер месяца, которому принадлежит эта дата. Например, MONTH(\'2007-12-12\') возвращает значение 12.

• QUARTER(\'<Дата или дата и время>\').

Функция QUARTER() получает в качестве аргумента дату или дату и время и возвращает номер квартала, которому принадлежит эта дата. Например, QUARTER(\'2007-12-12\') возвращает значение 4.

• YEAR(\'<Дата или дата и время>\').

Функция YEAR() получает в качестве аргумента дату или дату и время и возвращает номер года, которому принадлежит эта дата. Например, YEAR(\'2007-12–12\') возвращает значение 2007.

• YEARWEEK(\'<Дата или дата и время>\' [,Правило нумерации]).

Функция YEA


убрать рекламу






RWEEK() получает в качестве аргумента дату или дату и время и возвращает номер года и номер недели в году в формате YYYYWW. По умолчанию неделя считается начинающейся с воскресенья, и первой неделей считается та неделя, воскресенье которой принадлежит данному году, а дни, предшествующие первой неделе, считаются относящимися к последней неделе предыдущего года. Например, YEARWEEK(\'2007-12-31\') = YEARWEEK(\'2008-01-01\') = 200752, и это означает, что обе даты относятся к 52-й неделе 2007 г.

Вы можете также задать параметр, определяющий правило нумерации недель. Этот параметр аналогичен соответствующему параметру функции WEEK(), о которой мы рассказывали выше, однако для тех дат, для которых функция WEEK() возвращает значение 0, функция YEARWEEK() возвращает номер предыдущего года и номер последней недели предыдущего года. Например, WEEK(\'2008-01-01\',5) = 200753.

• HOUR(\'<Время или дата и время>\').

Функция HOUR() получает в качестве аргумента время или дату и время и выделяет из нее часы. Например, HOUR(\'12:30:00\') возвращает значение 12.

• MINUТЕ(\'<Время или дата и время>\').

Функция MINUTE() получает в качестве аргумента время или дату и время и выделяет из нее минуты. Например, MINUTE(\'12:30:00\') возвращает значение 30.

• SECOND(\'<Время или дата и время>\').

Функция SECOND() получает в качестве аргумента время или дату и время и выделяет из нее секунды. Например, SECOND(\'12:30:00\') возвращает значение 0.

• EXTRACT(\'<Наименование периода>\' FROM \'<Дата и/или время>\'). Функция EXTRACT() – наиболее общая из функций получения компонентов даты и времени. Первым ее аргументом является наименование компонента или диапазона компонентов, которые нужно выделить из даты:

• DAY – число (номер дня в месяце);

• WEEK – номер недели в году;

• MONTH – номер месяца;

• QUARTER – номер квартала;

• YEAR – номер года;

• HOUR – часы;

• MINUTE – минуты;

• SECOND – секунды;

• YEAR_MONTH – номер года и номер месяца;

• DAY_HOUR – число и часы;

• DAY_MINUTE – число, часы и минуты;

• DAY_SECOND – число, часы, минуты и секунды;

• HOUR_MINUTE – часы и минуты;

• HOUR_SECOND – часы, минуты и секунды;

• MINUTE_SECOND – минуты и секунды.

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

Например, EXTRACT(WEEK FROM \'2007-12-31\') возвращает, как и WEEK(\'2007-12–31\'), значение 52, а EXTRACT(DAY_MINUTE FROM \'2007-12-31 12:30:00\') возвращает значение 311230 (31 число, 12 часов и 30 минут).

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

Функции сложения и вычитания дат

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

• ADDDATE(\'<Дата или дата и время>\',<Количество дней>) или ADDDATE(\'<Дата или дата и время>\',<Временной интервал>). Функция возвращает дату или дату и время, сдвинутые относительно указанной даты на указанное количество дней или на указанный временной интервал. Для задания интервала можно использовать один из следующих основных форматов:

• INTERVAL \'<Количество секунд>\' SECOND

• INTERVAL \'<Количество минут>\' MINUTE

• INTERVAL \'<Количество часов>\' HOUR

• INTERVAL \'<Количество дней>\' DAY

• INTERVAL \'<Количество недель>\' WEEK

• INTERVAL \'<Количество месяцев>\' MONTH

• INTERVAL \'<Количество кварталов>\' QUARTER

• INTERVAL \'<Количество лет>\' YEAR

• INTERVAL \'<Количество минут>:<Количество секунд>\' MINUTE_SECOND

• INTERVAL \'<Количество часов>:<Количество минут>:<Количество секунд>\' HOUR_SECOND

• INTERVAL \'<Количество часов>:<Количество минут>\' HOUR_MINUTE

• INTERVAL \'<Количество дней> <Количество часов>:<Количество минут>:<Количество секунд>\' DAY SECOND

• INTERVAL \'<Количество дней> <Количество часов>:<Количество минут>\' DAY_MINUTE

• INTERVAL \'<Количество дней> <Количество часов>\' DAY_HOUR

• INTERVAL \'<Количество лет>-<Количество месяцев>\' YEAR MONTH

Например, функция ADDDATE(\'2007-12-12\',28) добавляет 28 дней к 12 декабря 2007 г. и возвращает результат 2008-01-09, а функция ADDDATE(\'2007-12-12\',INTERVAL \'28 12:30\' DAY_MINUTE) добавляет 28 дней, 12 часов и 30 минут к 12 декабря 2007 г. и возвращает результат 2008-01-09 12:30:00.

• DATE_ADD(\'<Дата или дата и время>\',\'<Временной интервал>\').

Синоним ADDDATE(\'<Дата или дата и время>\',\'<Временной интервал>\').

• ADDTIME(<Время или дата и время>,<Добавляемое время>).

Функция возвращает сумму своих аргументов. Например, функция ADDTIME (\'2007-12-12 12:30:00\',\'15:50:00\') добавляет 15 часов 50 минут к 12 часам 30 минутам 12 декабря 2007 г. и возвращает результат 2007-12-13 04:20:00.

• SUBDATE(\'<Дата или дата и время>\',<Количество дней>) или SUBDATE(\'<Дата или дата и время>\',\'<Временной интервал>\').

Функция SUBDATE() аналогична функции ADDDATE(), только указанное количество дней или указанный временной интервал не добавляются к дате, а вычитаются из нее, иными словами, дата сдвигается в прошлое, а не в будущее. Например, функция SUBDATE(\'2007-12-12\',INTERVAL \'28 12:30\' DAY_MINUTE) вычитает 28 дней, 12 часов и 30 минут из 12 декабря 2007 г. и возвращает результат 2007-11-13 11:30:00.

• DATE_SUB(\'<Дата или дата и время>\',\'<Временной интервал>\')

Синоним SUBDATE(\'<Дата или дата и время>\',\'<Временной интервал>\').

• SUBTIME(<Время или дата и время>,<Вычитаемое время>).

Функция возвращает разность своих аргументов. Например, функция SUBTIME(\'2007-12-12 12:30:00\',\'15:50:00\') вычитает 15 часов 50 минут из 12 часов 30 минут 12 декабря 2007 г. и возвращает результат 2007-12-11 20:40:00.

• DATEDIFF(\'<Дата или дата и время>\',\'<Дата или дата и время>\').

Функция DATEDIFF() возвращает разность в днях между первой и второй датой (время при этом не учитывается). Если первая дата предшествует второй, результат будет отрицательным. Например, DATEDIFF(\'2007-12-12 12:30:00\',\'2007-12-31\') возвращает значение –19.

• TIMEDIFF(\'<Время или дата и время>\',\'<Время или дата и время>\').

Функция TIMEDIFF() возвращает разность своих аргументов в формате времени. Если первый момент предшествует второму, результат будет отрицательным. Например, функция TIMEDIFF(\'2007-12-12 12:30:00\',\'2007-12-31 15:50:00\') возвращает значение –459:20:00. Это означает, что 12 декабря 2007 г. 12 часов 30 минут отстоит в прошлое от 31 декабря 2007 г. 15 часов 50 минут на 459 часов 20 минут.

• PERIOD_ADD(<Период в формате YYMM или YYYYMM>,<Количество месяцев>).

Функция PERIOD_ADD() возвращает результат добавления к указанному периоду указанное количество месяцев. Обратите внимание, что оба аргумента этой функции – числа и возвращаемый результат – также число. Например, PERIOD_ADD(200712,3) возвращает значение 200803, поскольку через три месяца после декабря 2007 г наступит март 2008 г.

• PERIOD_DIFF(<Период в формате YYMM или YYYYMM>,<Период в формате YYMM или YYYYMM>).

Функция PERIOD_DIFF() возвращает разность в месяцах между первым и вторым периодом. Обратите внимание, что оба аргумента этой функции – числа. Например, PERIOD_DIFF(200712,200803) возвращает значение – 3.

• TIMESTAMP(\'<Дата или дата время>\',\'<Время>\').

Функция TIMESTAMP() возвращает сумму своих аргументов в формате даты и времени. Например, функция TIMESTAMP(\'2007-12-12 12:30\',\'15:50\') добавляет 15 часов 50 минут к 12 часам 30 минутам 12 декабря 2007г. и возвращает результат 2007-12-13 04:20:00.

• TIMESTAMPADD(<Тип периода>,<Длина периода>,<Дата или дата и время>).

Функция TIMESTAMPADD() возвращает дату или дату и время сдвинутые относительно указанной даты на указанный период. Первым аргументом является тип периода:

DAY —число(номерднявмесяце;

WEEK —номернеделивгоду

MONTH —номермесяца

QUARTER —номерквартала

YEAR —номергода

HOUR —часы

MINUTE —минуты

SECOND —секунды

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

Например, функция TIMESTAMPADD(HOUR,15,\'2007-12-12 12:30:00\') добавляет15 часов к 12 часам 30 минутам 12 декабря 2007г. и возвращает результат 2007-12-13 03:30:00.

• TIMESTAMPDIFF(<Тип периода>,<Дата или дата и время>,<Дата или дата и время>).

Функция TIMESTAMPDIFF() возвращает количество указанных периодов, прошедших между первым и вторым моментом. Первый аргумент может приниматьте же значения, что и первый аргумент функции TIMESTAMPADD(). Если вторая дата предшествует первой, результат будет отрицательным. Например, TIMESTAMPDIFF(WEEK, 2007-12-12 12:30:00, 2007-12-31)возвращает значение 2, и это означает, что 12 декабря и 31 декабря 2007 г. разделяют две недели.

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

Функции преобразования форматов дат

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

• DATE_FORMAT(\'<Дата или дата и время>\', \'<Формат>\').

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

• %a – сокращенное наименование дня недели (Sun, Mon и т. д.). О том, как настроить вывод дат на русском языке («Пнд», «Втр» и т. д.), рассказывалось при описании функции DAYNAME().

• %b – сокращенное наименование месяца (Jan, Feb и т. д.). О том, как настроить вывод дат на русском языке (Янв, Фев и т. д.), говорилось при описании функции DAYNAME().

• %c – номер месяца (0-12).

• %D – число (номер дня в месяце) с английским суффиксом (0th, 1st, 2nd, и т. д.).

• %d – число месяца (00–31).

• %e – число месяца (0-31).

• %H – часы (00–23).

• %h, %I – часы (01–12).

• %i – минуты (0 0–5 9).

• %j – номер дня в году (0 01-3 6 6).

• %k – часы (0-23).

• %l – часы (1-12).

• %M – наименование месяца (January, February и т. д.). О том, как настроить вывод дат на русском языке (Января, Февраля и т. д.), говорилось при описании функции DAYNAME().

• %m – номер месяца (00–12).

• %p – AM (обозначение первой половины суток) или PM (обозначение второй половины суток).

• %r – время в 12-часовом формате (HH:MM:SS AM или PM).

• %S, %s – секунды (0 0–5 9).

• %T – время в 24-часовом формате (HH:MM:SS).

• %U – номер недели в году (0 0-53), первым днем недели считается воскресенье, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен 0.

• %u – номер недели в году (0 0-53), первым днем недели считается понедельник, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен 0.

• %V – номер недели в году (01–53), первым днем недели считается воскресенье, первая неделя года – целиком находящаяся в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году.

• %v – номер недели в году (01–53), первым днем недели считается понедельник, первая неделя года – та, более трех дней которой находится в этом году, для дней, предшествующих первой неделе, номер недели равен номеру последней недели в предыдущем году.

• %W – наименование дня недели (Sunday, Monday и т. д.). О том, как настроить вывод дат на русском языке (Понедельник, Вторник и т. д.), было сказано при описании функции DAYNAME().

• %w – номер дня недели (0 – воскресенье, 1 – понедельник и т. д.).

• %X – номер года, к которому относится текущая неделя (первым днем недели считается воскресенье, первая неделя года – целиком находящаяся в этом году, неделя, предшествующая первой неделе года, относится к предыдущему году), в формате YYYY.

• %x – номер года, к которому относится текущая неделя (первым днем недели считается понедельник, первая неделя года – та, более трех дней которой находится в этом году, неделя, предшествующая первой неделе года, относится к предыдущему году), в формате YYYY.

• %Y – номер года в формате YYYY.

• %y – номер года в формате YY.

• %% – знак процента.

Например, функция DATE_FORMAT(\'2007-12-12 12:30:00\', %e %M %Y г. %k часов %i минут\') возвращает значение 12 December 2007 г. 12 часов 30 минут или 12 Декабря 2007 г. 12 часов 30 минут, в зависимости от установленного языка вывода дат.

• TIME_FORMAT(\'<Время или дата и время>\', \'<Формат>\').

Функция TIME_FORMAT() возвращает время, преобразованное к указанному формату. Формат может включать те из перечисленных выше параметров, которые предназначены для отображения часов, минут и секунд. Например, функция TIME_FORMAT(\'2007-12-12 12:30:00\', \'%k часов %i минут\') возвращает значение 12 часов 30 минут.

• STR_TO_DATE(\'<Строка>\', \'<Формат>\').

Функция STR_TO_DATE() получает в качестве аргумента строку, содержащую дату и/или время, и строку формата, и возвращает дату и/или время, полученные из строки в соответствии с указанным форматом. Функции STR_TO_DATE() и DATE_FORMAT() взаимно обратны: если дата была преобразована в строку некоторого формата с помощью функции DATE_FORMAT(), то с помощью функции STR_TO_DATE(), указав тот же формат, можно получить исходную дату, и наоборот. Например, STR_TO_DATE(\'12 December 2007 г. 12 часов 30 минут\',\'%e %M %Y г. %k часов %i минут\') = STR_TO_DATE(DATE_FORMAT(\'2007-12-12 12:30:00\',\'%e %M %Y г. %k часов %i минут\'), \'%e %M %Y г. %k часов %i минут\') = 2007-12-12 12:30:00. Однако названия месяцев и дней недели на русском языке функция STR_TO_DATE() обрабатывает некорректно.

• GET_FORMAT(<DATE, TIME или DATETIME>,<\'EUR\', \'ISO\', \'JIS\', \'USA\' или \'INTERNAL\'>).

Функция GET_FORMAT() возвращает строку формата даты и/или времени, которую затем можно использовать в функции DATE_FORMAT(). Первый аргумент функции указывает, какой формат нужно получить: формат даты, времени или даты и времени. Второй аргумент задает стандарт, которому соответствует возвращаемый формат. Например, функция GET_FORMAT(DATETIME,\'EUR\') возвращает значение %Y-%m-%d %H.%i.%s».

• MAKEDATE(<Номер года>,<Номер дня в году>).

Функция MAKEDATE() получает в качестве аргументов номер года и номер дня в году и возвращает дату, соответствующую этому году и дню. Например, функция MAKEDATE(2007,346) возвращает значение 2007-12-12.

• MAKETIME(<Часы>,<Минуты>,<Секунды>).

Функция MAKETIME() получает в качестве аргументов час, минуту и секунду и возвращает соответствующее время. Например, функция MAKETIME(12,30,0) возвращает значение 12:30:00.

• FROM_DAYS(<Количество дней>).

Функция FROM_DAYS() получает в качестве аргумента количество дней от Р. Х. и возвращает дату, соответствующую этому дню. Например, функция FROM_DAYS(733387) возвращает значение 2007-12-12.

• TO_DAYS(<Дата или дата и время>).

Функция TO_DAYS() получает в качестве аргумента дату или дату и время и возвращает количество дней от Р. Х., соответствующее этой дате. Например, функция TO_DAYS(\'2007-12-12 12:30:00\') возвращает значение 733387.

• SEC_TO_TIME(<Количество секунд>).

Функция SEC_TO_TIME() получает в качестве аргумента количество секунд и возвращает соответствующее количество часов, минут и секунд в формате времени. Например, функция SEC_TO_TIME(45000) возвращает значение 12:30:00.

• TIME_TO_SEC(<Время или дата и время>).

Функция TIME_TO_SEC() получает в качестве аргумента время или дату и время и возвращает количество секунд, соответствующее времени (дата при этом игнорируется). Например, функция TIME_TO_SEC(\'2007-12-12 12:30:00\') возвращает значение 45 000.

• FROM_UNIXTIME(<Unix-время>[,\'<Формат>\']).

Функция FROM_UNIXTIME() получает в качестве аргумента Unix-время – количество секунд, прошедших с 1 января 1970 г., и возвращает соответствующую дату и время. Например, функция FROM_UNIXTIME(1197451800) возвращает значение 2007-12-12 12:30:00. При необходимости вы можете задать формат возвращаемой даты и/или времени, используя параметры, которые мы перечислили при описании функции DATE_FORMAT().

• UNIX_TIMESTAMP(<Дата>).

Если аргумент функции UNIX_TIMESTAMP() не задан, то она возвращает текущее Unix-время. Если задан аргумент – дата, дата и время либо число в формате YYYYMMDD, YYMMDD, YYYYMMDDHHMMSS или YYMMDDHHMMSS, то функция UNIX_TIMESTAMP() возвращает Unix-время, соответствующее указанной дате. Например, функция UNIX_TIMESTAMP(20071212123000) возвращает значение 1197451800.

• TIMESTAMP(\'<Дата или дата время>\').

Если задан только один аргумент функции TIMESTAMP(), то она возвращает этот аргумент, преобразованный в формат даты и времени. Например, TIMESTAMP(\'2007-12-12\') возвращает значение 2007-12-12 00:00:00.

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

3.5. Символьные функции

 Сделать закладку на этом месте книги

Рассмотрим символьные функции, которые вы можете использовать в выражениях.

• BIT_LENGTH(\'<Строка>\').

Функция BIT_LENGTH() возвращает длину строки в битах. Например, функция BIT_LENGTH(\'Крылов\') возвращает значение 48 при использовании однобайтовой кодировки и значение 96 при использовании кодировки UTF-8.

• CHAR_LENGTH(\'<Строка>\'), CHARACTER_LENGTH(\'<Строка>\').

Возвращают количество символов в строке. Например, функция CHAR_LENGTH(\'Крылов\') возвращает значение 6.

• LENGTH(\'<Строка>\'), OCTET_LENGTH(\'<Строка>\').

Возвращают длину строки (в байтах). Например, функция LENGTH(\'Крылов\') возвращает значение 6 при использовании однобайтовой кодировки и значение 12 при использовании кодировки UTF-8.

• CHAR(<Код 1>,<Код 2>,…,<Код N> [USING <Кодировка>]).

Функция CHAR() получает в качестве аргументов коды символов и возвращает строку, состоящую из этих символов. При необходимости можно явно указать кодировку, сопоставляющую коды символам. Например, функции CHAR(53402,53632,53643,53435,53438,53426 USING utf8) и CHAR(138,224,235,171,174,162 USING cp866) возвращают значение Крылов.

• ORD(\'<Строка>\').

Функция ORD() возвращает числовой код первого символа в строке. Например, функция ORD(CHAR(53402,53632,53643,53435,53438,53426 USING utf8)) возвращает значение 53402.

• CONCAT(\'<Строка 1>\',\'<Строка 2>\',…, \'<Строка N>\').

Функция CONCAT() возвращает результат объединения своих аргументов. Например, функция CONCAT(\'ООО “Кускус”\',\'Петров\',\'Крылов\') возвращает значение ООО «Кускус»ПетровКрылов.

• CONCAT_WS(\'Разделитель\',\'<Строка 1>\',\'<Строка 2>\',…,\'<Строка N>\').

Функция CONCAT_WS() возвращает результат объединения своих аргументов, при этом первый аргумент используется как разделитель. Например, функция CONCAT_WS(\',\',\'ООО “Кускус”\',\'Петров\',\'Крылов\') возвращает значение ООО «Кускус»,Петров,Крылов.

• REPEAT(\'<Строка>\',\'Количество экземпляров, не менее 1\').

Функция REPEAT(\'<Строка>\',<Количество экземпляров>) возвращает строку, в которую исходная строка входит указанное количество раз. Например, функция REPEAT(\'Трижды\',3) возвращает значение ТриждыТриждыТрижды.

• REVERSE(\'<Строка>\').

Функция REVERSE() возвращает строку, в которой символы исходной строки расположены в обратном порядке. Например, функция REVERSE(\'наоборот\') возвращает значение торобоан.

• SPACE(<Количество пробелов>).

Функция SPACE() возвращает строку, состоящую из указанного количества пробелов. Например, функция SPACE(1) возвращает значение «.».

• ELT(k,\'<Строка 1>\',\'<Строка 2>\',…, \'<Строка N>\').

Функция ELT() возвращает строку с порядковым номером k. Например, функция ELT(2,\'ООО «Кускус»\',\'Петров\',\'Крылов\') возвращает значение Петров.

• FIELD(\'<Строка-образец>\',\'<Строка 1>\',\'<Строка 2>\',…,\'<Строка N>\').

Функция FIELD() возвращает порядковый номер строки, совпадающей с образцом, и 0, если ни одна из строк 1, 2, …, N не совпадает с образцом. Например, функция FIELD(\'Петров\',\'ООО «Кускус»\',\'Петров\', \'Крылов\') возвращает значение 2.

• FIND_IN_SET(\'<Строка-образец>\',\'<Строка-контейнер>\').

Функция FIND_IN_SET() получает в качестве аргумента строку-образец (эта строка не должна содержать запятых) и строку-контейнер вида <Подстрока 1>,<Подстрока 2>,…,<Подстрока N> и возвращает порядковый номер подстроки, совпадающей с образцом, и 0, если ни одна из подстрок 1, 2, …,N не совпадает с образцом или строка-контейнер пустая. Например, функция FIND_IN_SET(\'Петров\',\'ООО «Кускус»,Петров,Крылов\') возвращает значение 2.

• EXPORT_SET(<Число>,\'<Подстрока для бита 1>\',\'<Подстрока для бита 0>\'[,\'<Разделитель>\'[,<Количество бит>]]).

Функция EXPORT_SET() преобразует число в строку, заменяя каждый бит (0 или 1) соответствующей подстрокой, и возвращает полученную строку. Биты рассматриваются в обратном порядке, то есть справа налево. При необходимости можно задать разделитель подстрок (если разделитель не задан, используется запятая), а также максимальное количество битов, которые будут обработаны (недостающие биты рассматриваются как нулевые, «лишние» биты игнорируются, а если количество битов не задано, используется значение 64). Например, функция EXPORT_SET(25,\'Да\',\'Нет\',\':\',7) возвращает значение Да:Нет:Нет:Да:Да:Нет:Нет, поскольку 25 записывается в двоичной системе счисления как 11001.

• MAKE_SET(<Число>,\'<Подстрока 0>\',\'<Подстрока 1>\',…, \'<Подстрока N>\').

Функция MAKE_SET() преобразует число в строку: подстрока с порядковым номером k добавляется в строку, если k-й бит равен 1. Биты рассматриваются в обратном порядке, то есть справа налево. Разделителем подстрок служит запятая. Например, функция MAKE_SET(6,\'Я согласен получать новости компании\',\'Я согласен участвовать в опросах\',\'Я согласен участвовать в тестировании продукта\') возвращает значение Я согласен участвовать в опросах, Я согласен участвовать в тестировании продукта, поскольку 6 записывается в двоичной системе счисления как 110.

• INSERT(\'<Строка>\',<Позиция>,<Длина подстроки>,\'<Замещающая подстрока>\').

Функция INSERT() возвращает строку, в которой подстрока, начинающаяся с указанной позиции и состоящая из указанного количества символов, заменена заданной подстрокой. Например, функция INSERT(\'ООО “Кускус”\',6,3,\'Кискис\') заменяет подстроку Кус строки ООО «Кускус» подстрокой Кискис и возвращает значение ООО «Кискискус».

• REPLACE(\'<Строка>\',\'<Замещаемая подстрока>\',\'<Замещающая подстрока>\').

Функция REPLACE() возвращает строку, в которой вместо замещаемой подстроки подставлена замещающая. Например, функция REPLACE(\'Не имей сто рублей, а имей сто друзей\',\'сто\',\'тысячу\') возвращает значение Не имей тысячу рублей, а имей тысячу друзей.

• SUBSTR(\'<Строка>\',<Позиция>[,<Длина>]), SUBSTRING(\'<Строка>\',<Позиция>[,<Длина>]), SUBSTR(\'<Строка>\' FROM <Позиция>[ FOR <Длина>]), SUBSTRING(\'<Строка>\' FROM <Позиция>[ FOR <Длина>]).

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

Например:

– функция SUBSTR(\'Семь чудес света\',6) возвращает значение чудес света;

– функция SUBSTR(\'Семь чудес света\',6,5) возвращает значение чудес;

– функция SUBSTR(\'Семь чудес света\',-5) возвращает значение света.

• MID(\'<Строка>\',<Позиция>,<Длина>).

Синоним функции SUBSTRING(\'<Строка>\',<Позиция>,<Длина>).

• SUBSTRING_INDEX(\'<Строка>\',\'<Подстрока>\',<Порядковый номер вхождения>).

Если заданный порядковый номер вхождения больше 0, то функция SUBSTRING_INDEX() находит в исходной строке вхождение указанной подстроки с этим порядковым номером (считая от начала строки) и возвращает часть исходной строки, предшествующую этому вхождению. Если же заданный порядковый номер вхождения меньше 0, то вхождения отсчитываются от конца строки и возвращается часть исходной строки, которая следует за этим вхождением. Например, функция SUBSTRING_INDEX(\'Семь чудес света\',\' \',2) возвращает значение Семь чудес (подстроку, предшествующую второму пробелу), а функция SUBSTRING_INDEX(\'Семь чудес света\',\' \',-2) возвращает значение чудес света (подстроку, следующую за вторым пробелом).

• LEFT(\'<Строка>\',<Длина подстроки>).

Функция LEFT() возвращает начальную подстроку исходной строки, состоящую из указанного количества символов. Например, функция LEFT(\'Генератор\',3) возвращает значение Ген.

• RIGHT(\'<Строка>\',<Длина подстроки>).

Функция RIGHT() возвращает подстроку, состоящую из указанного количества последних символов исходной строки. Например, функция RIGHT(\'Генератор\',3) возвращает значение тор.

• LOCATE(\'<Подстрока>\',\'<Строка>\'[,<Позиция>]).

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

• LOCATE(\'сто\',\'Не имей сто рублей, а имей сто друзей\') возвращает значение 9, а функция LOCATE(\'сто\',\'Не имей сто рублей, а имей сто друзей\',20) возвращает значение 28. Регистр символов учитывается только в случае, если хотя бы одна из строк – байтовая (бинарная).

• INSTR(\'<Строка>\',\'<Подстрока>\'), POSITION(\'<Подстрока>\' IN\'<Строка>\').

Синонимы функции LOCATE(\'<Подстрока>\',\'<Строка>\'). Обратите внимание, что порядок аргументов у функций INSTR и LOCATE разный.

• LCASE(\'<Строка>\'), LOWER(\'<Строка>\').

Возвращают строку, приведенную к нижнему регистру. Например, функция LCASE(\'Крылов\') возвращает значение крылов.

• UCASE(\'<Строка>\'), UPPER(\'<Строка>\').

Возвращают строку, приведенную к верхнему регистру. Например, функция UCASE(\'Крылов\') возвращает значение КРЫЛОВ.

• LOAD_FILE(\'<Путь и имя файла>\').

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

• LPAD(\'<Строка>\',<Длина>,\'<Символы заполнения>\').

Функция LPAD() возвращает строку указанной длины, полученную из исходной строки путем добавления символов заполнения в начале строки (в случае если количество символов в исходной строке меньше указанного) или отбрасывания «лишних» символов (в случае если количество символов в исходной строке больше указанного). Например, функция LPAD(\'Крылов\',9,\'+-\') возвращает значение +–+Крылов, а функция LPAD(\'ООО “Кускус”\',9,\'+-\') возвращает значение ООО «Куск.

• RPAD(\'<Строка>\',<Длина>,\'<Символы заполнения>\').

Функция RPAD() аналогична функции LPAD(), только символы заполнения добавляются в конце строки. Например, функция RPAD(\'Крылов\',9,\'+-\') возвращает значение Крылов+–+, а функция RPAD(\'ООО “Кускус”\',9,\'+-\') возвращает значение ООО «Куск.

• LTRIM(\'<Строка>\').

Функция LTRIM() возвращает строку, полученную из исходной путем удаления начальных пробелов. Например, функция LTRIM(\' Крылов \') возвращает значение Крылов .

• RTRIM(\'<Строка>\').

Функция RTRIM() возвращает строку, полученную из исходной путем удаления пробелов в конце строки. Например, функция RTRIM(\' Крылов \') возвращает значение Крылов.

• TRIM([[LEADING, TRAILING или BOTH] [\'<Символы заполнения>\']FROM ]\'<Строка>\').

Функция TRIM(\'<Строка>\') возвращает строку, полученную из исходной путем удаления начальных пробелов и пробелов в конце строки. Если необходимо удалить другой символ или последовательность символов, их нужно указать в параметре <Символы заполнения>. Если требуется удалить символы заполнения только в начале строки, укажем параметр LEADING, если только в конце – параметр TRAILING. Например, функция TRIM(\'+-\' FROM \'+-+Крылов-+-+-\') возвращает значение +Крылов–.

• FORMAT(<Число>


убрать рекламу






;,<Количество цифр после запятой>).

Функция FORMAT() округляет число до заданного количества цифр после десятичного разделителя или, наоборот, дополняет число нулями справа до заданного количества цифр после десятичного разделителя, и возвращает это число в виде строки, используя запятую как разделитель тысяч. Например, функция FORMAT(12345.6789,2) возвращает строку 12,345.68.

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

3.6. Резюме

 Сделать закладку на этом месте книги

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

Глава 4 Доступ к базе данных из веб-приложений

 Сделать закладку на этом месте книги

Данная глава посвящена использованию базы данных MySQL в веб-приложениях, написанных на языках PHP, Perl и Java. При этом мы будем считать, что этими языками программирования вы владеете, и будем рассматривать только операции взаимодействия с базой данных: подключение и отключение, получение и внесение информации. В первую очередь мы рассмотрим совместную работу MySQL и приложений PHP.

4.1. Интерфейс с PHP

 Сделать закладку на этом месте книги

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

Выбор платформы

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

Для разработки и тестирования ваших первых PHP/MySQL-приложений необходимо превратить в веб-сервер ваш собственный компьютер. При этом вам потребуется следующее программное обеспечение:

• программа, выполняющая функции веб-сервера (обычно это Apache);

• интерпретатор языка PHP;

• СУБД MySQL.

Все эти три программы являются свободно распространяемыми. В настоящее время разработано множество интегрированных пакетов, которые упрощают установку этих программ и автоматически выполняют их настройку для совместной работы. Перечень популярных интегрированных пакетов вы можете найти на странице https://ru.wikipedia.org/wiki/LAMP. Мы будем использовать пакет XAMPP, который дополнительно включает интерпретатор языка Perl. Скачать пакет XAMPP вы можете на сайте разработчика (https://www.apachefriends.org). В следующем подразделе мы рассмотрим установку пакета XAMPP.

Установка пакета XAMPP

Чтобы установить Windows-версию пакета XAMPP, включающего программы Apache, PHP, Perl и MySQL, выполните следующие действия.

1. Скачайте дистрибутив пакета. Для этого на веб-странице https://www.apachefriends.org/en/xampp-windows.html в разделе XAMPP Windows [Basic package] щелкните на ссылке Installer.

2. После загрузки файла xampp-win32-xxx-installer.exe запустите его, дважды щелкнув на его значке.

3. Выберите язык установки English (рис. 4.1). Нажмите кнопку OK.



Рис. 4.1. Выбор языка установки













Итак, вы установили пакет XAMPP и можете приступать к созданию PHP-приложений. Об этом и пойдет речь в следующем подразделе.

Тестирование PHP

Чтобы проверить корректность функционирования интерпретатора PHP, создадим простейшее PHP-приложение. Для этого выполните следующие действия.

1. Запустите стандартную программу Windows Блокнот (Пуск → Все программы → Стандартные → Блокнот).

2. Введите в окне программы Блокнот следующий код (рис. 4.8):





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

Подготовительные действия

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

mysql_connect(«<Имя хоста>»,  «<Имя пользователя>»,»<Пароль>»);  

Эта функция возвращает указатель на соединение  либо значение FALSE, если соединение установить не удалось.

В качестве примера рассмотрим PHP-приложение, которое выполняет подключение к серверу MySQL и выводит диагностическое сообщение. Создайте в папке htdocs корневой папки XAMPP файл output.php, содержащий следующий код (листинг 4.1).

Листинг 4.1. Подключение к серверу MySQL

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Подключение к базе данных</h1>  

<?php  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

print(“Подключение выполнено успешно”);  

?>  

</body>  




...

Совет

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

 

Следующий шаг – выбор текущей базы данных с помощью функции

mysql_select_db(«<Имя базы данных>»[,  <Указатель на соединение>]);  


...

Примечание

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

 

Функция mysql_select_db() аналогична команде USE <Имя базы данных>, о которой было рассказано в разделе «Создание базы данных» главы 2. Добавьте в сценарий output.php вызов этой функции (листинг 4.2).

Листинг 4.2.

Выбор текущей базы данных

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Подключение к базе данных</h1>  

<?php  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

if(!mysql_select_db(«SalesDept»))  

die(“База данных отсутствует. Приносим свои извинения”);  

print(“База данных выбрана успешно”);  

?>  

</body>  

После обновления страницы https://localhost/output.php вы увидите либо сообщение «Операция выполнена успешно», либо сообщение «База данных отсутствует. Приносим свои извинения». В последнем случае необходимо проверить, существует ли база данных с таким именем на сервере MySQL и есть ли у пользователя username право доступа к этой базе.

После подключения к серверу MySQL и выбора текущей базы данных можно приступать к работе с данными. В первую очередь необходимо установить кодировку, чтобы избежать проблем с отображением символов русского алфавита. Как мы знаем из главы 2, указать серверу кодировку, которую использует клиентское приложение, можно с помощью команды SET NAMES <Кодировка>;.

Файл output.php мы сохранили в кодировке Windows (CP-1251), поэтому именно ее и нужно установить.

Для отправки SQL-команды на сервер MySQL используется функция

mysql_query(«<Текст команды>»[, <Указатель на соединение>]);  

Добавьте в сценарий output.php вызов этой функции (листинг 4.3). Листинг 4.3. Установка кодировки

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Подключение к базе данных</h1>  

<?php  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

if(!mysql_select_db(«SalesDept»))  

die(“База данных отсутствует. Приносим свои извинения”);  

//Устанавливаем кодировку CP-1251  

mysql_query(“SET NAMES cp1251”);  

print(“Операция выполнена успешно”);  

?>  

</body>  

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

Выполнение запроса к базе данных

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

Как было упомянуто выше, для выполнения SQL-команды PHP-приложением предназначена функция

mysql_query(«<Текст команды>»[, <Указатель на соединение>])  

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

mysql_fetch_assoc(<Указатель на результат запроса>)  

или

mysql_fetch_array(<Указатель результат запроса>)  

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

Проиллюстрируем работу этой функции на примере вывода списка товаров, то есть данных из таблицы Products (Товары). Добавим в сценарий output.php вызов функций mysql_query() и mysql_fetch_assoc() (листинг 4.4).

Листинг 4.4. Получение информации и отображение ее на странице

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Список товаров</h1>  

<!– Выводим список товаров –>  

<table>  

<!– Выводим заголовок списка товаров –>  

<tr>  

<th>Наименование</th>  

<th>Описание</th>  

<th>Цена</th>  

</tr>  

<?php  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

if(!mysql_select_db(«SalesDept»))  

die(“База данных отсутствует. Приносим свои извинения”);  

//Устанавливаем кодировку CP-1251  

mysql_query(“SET NAMES cp1251”);  

//Получаем список товаров  

$qresult = mysql_query(«SELECT * FROM Products»);  

if(!$qresult) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Очередную строку из результата запроса (информацию о товаре)  

// записываем в ассоциативный массив $product  

while ($product=mysql_fetch_assoc($qresult))  

{  

//выводим элементы массива $product с именами description (наименование), //  

details (описание) и price (цена)  

print «\n<tr><td>{$product[«description»]}</td>  

<td>{$product[«details»]}</td>  

<td>{$product[«price»]}</td></tr>\n»;  

}  

?>  

</table>  

</body>  





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

Функция mysql_fetch_array() возвращает как ассоциативный массив, так и массив с числовыми индексами. Таким образом, вы можете обращаться к значению, хранящемуся в строке, используя либо имя столбца, либо порядковый номер столбца в результате запроса. Например, код, представленный в листинге 4.4, можно переписать следующим образом (листинг 4.5).

Листинг 4.5. Получение информации и отображение ее на странице

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Список товаров</h1>  

<!– Выводим список товаров –>  

<table>  

<!– Выводим заголовок списка товаров –>  

<tr>  

<th>Наименование</th>  

<th>Описание</th>  

<th>Цена</th>  

</tr>  

<?php  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

if(!mysql_select_db(«SalesDept»))  

die(“База данных отсутствует. Приносим свои извинения”);  

//Устанавливаем кодировку CP-1251  

mysql_query(“SET NAMES cp1251”);  

//Получаем список товаров  

$qresult = mysql_query(«SELECT * FROM Products»);  

if(!$qresult) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Очередную строку из результата запроса (информацию о товаре)  

// записываем в массив $product  

while ($product=mysql_fetch_array($qresult))  

{  

//выводим элементы массива $product с номерами 1, 2, 3  

print «\n<tr><td>{$product[1]}</td>  

<td>{$product[2]}</td>  

<td>{$product[3]}</td></tr>\n»;  

}  

?>  

</table>  

</body>  

Результат выполнения приложения при этом не изменится.

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

Обработка ошибок

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

mysql_error([<Указатель на соединение>])  

и

mysql_errno([<Указатель на соединение>])  

Функция mysql_error() возвращает описание ошибки, произошедшей при выполнении последней SQL-команды (или пустую строку, если команда была выполнена успешно). Функция mysql_errno() возвращает код ошибки, произошедшей при выполнении последней SQL-команды (или 0, если команда была выполнена успешно).

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

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

error_reporting(0)  

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

error_log(«<Текст сообщения>»,  <Тип сообщения>,»<Адрес доставки>»)  

Дополните сценарий output.php обработкой ошибок (листинг 4.6). Листинг 4.6. Обработка ошибок

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Список товаров</h1>  

<!– Выводим список товаров –>  

<table>  

<!– Выводим заголовок списка товаров –>  

<tr>  

<th>Наименование</th>  

<th>Описание</th>  

<th>Цена</th>  

</tr>  

<?php  

//Отключаем вывод системных сообщений об ошибках  

error_reporting(0);  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

//В случае ошибки формируем сообщение, записываем его в файл  

//и отправляем по электронной почте  

if(!mysql_select_db(“SalesDept”))  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mysql_errno().» «.mysql_error().»\r\n»;  

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка доступа к базе данных. Приносим свои извинения”);  

}  

//Устанавливаем кодировку CP-1251  

mysql_query(«SET NAMES cp1251»);  

//Получаем список товаров  

$qresult = mysql_query(«SELECT * FROM Products»);  

//Проверяем результат выполнения запроса; в случае ошибки формируем //  

сообщение, записываем его в файл и отправляем по электронной почте  

if(!$qresult)  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mysql_errno().» «.mysql_error().»\r\n»;  

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка доступа к базе данных. Приносим свои извинения”);  

}  

//Очередную строку из результата запроса (информацию о товаре)  

// записываем в ассоциативный массив $product  

while ($product=mysql_fetch_assoc($qresult))  

{  

//выводим элементы массива $product с именами description (наименование), //  

details (описание) и price (цена)  

print «\n<tr><td>{$product[«description»]}</td>  

<td>{$product[«details»]}</td>  

<td>{$product[«price»]}</td></tr>\n»;  

}  

?>  

</table>  

</body>  

Если при выполнении запроса произойдет ошибка, например окажется, что таблица Products (Товары) была удалена, то сообщение вида 2008.06.15 14:22:53 1146 Table \'salesdept.products\' doesn\'t exist будет записано в файл mysqlerror.log, находящийся в папке htdocs корневой папки XAMPP, и отправлено на адрес [email protected] (тип сообщения 3 соответствует записи в файл, тип 1 – отправке по электронной почте). На веб-странице при этом отобразится нейтральное сообщение: «Ошибка доступа к базе данных. Приносим свои извинения».

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

Ввод данных в базу

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

В качестве примера рассмотрим форму саморегистрации нового клиента, где клиент указывает свое имя, телефон и адрес. Создадим в папке htdocs корневой папки XAMPP файл input.php, содержащий следующий код (листинг 4.7).

Листинг 4.7. Форма ввода данных

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Пожалуйста, заполните следующие поля:</h1>  

<!– Создаем форму для ввода данных –>  

<!– Обрабатывать введенные данные будет сценарий save.php –>  

<form method=»post» action=»save.php»>  

<table>  

<!– Создаем поле для ввода имени заказчика –>  

<tr>  

<td>Ваше имя:</td>  

<td><input type=»text» name=»CustomerName» value=»»></td>  

</tr>  

<!– Создаем поле для ввода телефона заказчика –>  

<tr>  

<td>Телефон:</td>  

<td><input type=»text» name=»CustomerPhone» value=»(495)»></td>  

</tr>  

<!– Создаем поле для ввода адреса заказчика –>  

<tr>  

<td>Адрес:</td>  

<td><input type=»text» name=»CustomerAddress» value=»»></td>  

</tr>  

</table>  

<br>  

<!– Создаем кнопку для подтверждения данных –>  

<input type=»submit» value=»Отправить»>  

</form>  

</body>  

</html>  



Создавая эту форму, я указал, что при ее подтверждении (то есть при нажатии кнопки Отправить) введенные пользователем значения полей будут переданы в сценарий save.php по методу POST. В сценарии save.php мы будем использовать уже известные нам PHP-функции:

• функции подключения к серверу MySQL и выбора базы данных, которые мы рассматривали в подразделе «Подготовительные действия»;

• функцию mysql_query(), которая обеспечивает выполнение SQL-команды на сервере MySQL. Если SQL-команда не предполагает получение данных из базы (такими командами являются, например, команды INSERT, UPDATE, DELETE), то функция возвращает значение TRUE в случае успешного выполнения команды и значение FALSE в случае ошибки;

• функции обработки ошибок, о которых вы узнали в подразделе «Обработка ошибок».

Итак, создадим в папке htdocs корневой папки XAMPP файл save.php, содержащий следующий код (листинг 4.8).

Листинг 4.8. Сохранение данных в базе

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<?php  

//Отключаем вывод системных сообщений об ошибках  

error_reporting(0);  

//Получаем данные из формы input.php  

$phone=$_POST[«CustomerPhone»];  

//Если номер телефона не введен, то связаться с клиентом невозможно.  

//Предлагаем клиенту вернуться к заполнению формы  

if(empty($phone) or ($phone == «(495)»))  

{  

print “<h3>Пожалуйста, введите номер телефона</h3>”;  

print “<input type=\'button\' value=\'Вернуться к редактированию данных\'  

onClick=\'history.go(-1)\'”;  

}  

//Если номер телефона введен, продолжаем обработку данных  

else  

{  

//Получаем из формы имя и адрес клиента  

$name=$_POST[«CustomerName»];  

$address=$_POST[«CustomerAddress»];  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

//В случае ошибки формируем сообщение, записываем его в файл  

//и отправляем по электронной почте  

if(!mysql_select_db(“SalesDept”))  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mys


убрать рекламу






ql_errno().» «.mysql_error().»\r\n»;
 

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка доступа к базе данных. Приносим свои извинения”);  

}  

//Устанавливаем кодировку CP-1251  

mysql_query(«SET NAMES cp1251»);  

//Записываем данные о заказчике в таблицу Customers (Клиенты)  

$qresult = mysql_query(«INSERT INTO Customers (name,phone,address)  

VALUES  

(\'».$name.»\',\'».$phone.»\',\'».$address.»\')»);  

//Проверяем результат выполнения команды; в случае ошибки формируем //  

сообщение, записываем его в файл и отправляем по электронной почте  

if(!$qresult)  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mysql_errno().» «.mysql_error().»\r\n»;  

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка при сохранении данных. Приносим свои извинения”);  

}  

print “<h3>Поздравляем! Регистрация завершена успешно</h3>”;  

}  

?>  

</body>  

</html>  

Если, например, в форме были введены значения полей Иванов, 157400 и Москва, а/я 255, то вызов функции

$qresult = mysql_query(«INSERT INTO Customers  

(name,phone,address)  

VALUES  

(\'».$name.»\',\'».$phone.»\',\'».$address.»\')»);  

после подстановки значений переменных $name, $phone и $address будет выглядеть следующим образом:

$qresult = mysql_query(«INSERT INTO Customers  

(name,phone,address)  

VALUES  

(\'Иванов\',\'157400\',\'Москва, а/я 225\')»);  



Мы почти завершили создание приложения, которое записывает информацию в базу данных. Однако нужно сделать важное дополнение, связанное с некорректным сохранением значений, содержащих спецсимволы. Предположим, например, что пользователь вводит на веб-странице в поле Ваше имя значение д\'Артаньян. Тогда вызов PHP-функции

mysql_query(“INSERT INTO Customers (name,phone,address)  

VALUES  

(\'”.$name.”\',\'”.$phone.”\',\'”.$address.”\')”);  

приведет к попытке выполнения некорректной SQL-команды

INSERT INTO Customers  

(name,phone,address)  

VALUES (\'д\'Артаньян\',\'Телефон\',\'Адрес\');  

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

mysql_real_escape_string(«<Строка>»[,  <Указатель на соединение>]);  

Функция mysql_real_escape_string() экранирует строку, полученную в качестве аргумента, то есть перед каждым специальным символом в этой строке (например, перед одинарной кавычкой) помещает обратную косую черту. Например, если в качестве аргумента передана строка д\'Артаньян, то функция возвращает значение д\\'Артаньян. Таким образом, при вызове PHP-функции

mysql_query(“INSERT INTO Customers (name,phone,address)  

VALUES  

(\'”.mysql_real_escape_string($name).”\',  

\'”.mysql_real_escape_string($phone).”\',  

\'”.mysql_real_escape_string($address).”\')”);  

будет выполнена корректная SQL-команда

INSERT INTO Customers  

(name,phone,address)  

VALUES (\'д\\'Артаньян\',\'Телефон\',\'Адрес\');  

Кроме того, в ряде случаев функция mysql_real_escape_string() позволяет обезопасить PHP-приложение от SQL-инъекций,  то есть предотвратить выполнение SQL-команд, которые недобросовестный пользователь может ввести в текстовые поля на веб-странице.

Исправим сценарий save.php, добавив вызов функции mysql_real_escape_string() (листинг 4.9).

Листинг 4.9. Сохранение данных в базе

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<?php  

//Отключаем вывод системных сообщений об ошибках  

error_reporting(0);  

//Получаем данные из формы input.php  

$phone=$_POST[“CustomerPhone”];  

//Если номер телефона не введен, то связаться с клиентом невозможно.  

//Предлагаем клиенту вернуться к заполнению формы  

if(empty($phone) or ($phone == «(495)»))  

{  

print “<h3>Пожалуйста, введите номер телефона</h3>”;  

print “<input type=\'button\' value=\'Вернуться к редактированию данных\'  

onClick=\'history.go(-1)\'”;  

}  

//Если номер телефона введен, продолжаем обработку данных  

else  

{  

//Получаем из формы имя и адрес клиента  

$name=$_POST[«CustomerName»];  

$address=$_POST[«CustomerAddress»];  

//Соединяемся с сервером MySQL  

$connection = mysql_connect(«localhost»,»username»,»userpassword»);  

if(!$connection) die(“Ошибка доступа к базе данных.  

Приносим свои извинения”);  

//Выбираем базу данных SalesDept (Отдел продаж)  

//В случае ошибки формируем сообщение, записываем его в файл  

//и отправляем по электронной почте  

if(!mysql_select_db(“SalesDept”))  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mysql_errno().» «.mysql_error().»\r\n»;  

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка доступа к базе данных. Приносим свои извинения”);  

}  

//Устанавливаем кодировку CP-1251  

mysql_query(«SET NAMES cp1251»);  

//Записываем данные о заказчике в таблицу Customers (Клиенты)  

$qresult = mysql_query(«INSERT INTO Customers (name,phone,address)  

VALUES  

(\'».mysql_real_escape_string($name).»\',  

\'».mysql_real_escape_string($phone).»\',  

\'».mysql_real_escape_string($address).»\')»);  

//Проверяем результат выполнения команды; в случае ошибки формируем //  

сообщение, записываем его в файл и отправляем по электронной почте  

if(!$qresult)  

{  

$err_message=date(«Y.m.d H:i:s»).»  

«.mysql_errno().» «.mysql_error().»\r\n»;  

error_log($err_message,3,»/mysqlerror.log»);  

error_log($err_message,1,»[email protected]»);  

die(“Ошибка при сохранении данных. Приносим свои извинения”);  

}  

print “<h3>Поздравляем! Регистрация завершена успешно</h3>”;  

}  

?>  

</body>  

</html>  

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

Итоги

В разделе 4.1 «Интерфейс с PHP» вы познакомились с примерами PHP-приложений, использующих базу данных MySQL. Все они имеют сходную структуру:

• подключение к серверу MySQL;

• выбор базы данных;

• установка кодировки;

• выполнение SQL-команды (ввод, изменение или получение данных);

• обработка ошибки.

При этом мы рассмотрели только самые необходимые для взаимодействия с MySQL функции языка PHP. Полный список этих функций вы можете найти в Руководстве по PHP на странице https://www.php.net/manual/ru/ref.mysql.php.

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

4.2. Интерфейс с Perl

 Сделать закладку на этом месте книги

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

Выбор платформы для развертывания Perl-приложения аналогичен выбору платформы для PHP-приложения: вы можете воспользоваться хостингом с поддержкой Perl и MySQL либо установить на своем компьютере веб-сервер Apache и интерпретатор языка Perl. При этом все замечания и рекомендации из подраздела «Выбор платформы» остаются в силе.

В последующих примерах мы будем использовать пакет XAMPP, установку которого мы описывали в подразделе «Установка пакета XAMPP». Кроме того, нам потребуются дополнительные модули Perl DBI (Database Interface – интерфейс к базе данных) и Perl CGI (Common Gateway Interface – стандартный интерфейс между сценарием и веб-сервером). Об их установке вы узнаете из следующего подраздела.

Установка дополнительных модулей Perl

Чтобы установить модули Perl DBI и Perl CGI, выполните следующие действия.

1. Скачайте дистрибутив пакета Perl Add-Ons. Для этого на веб-странице https://www.apachefriends.org/en/xampp-windows.html найдите раздел XAMPP for Windows Add-Ons и в подразделе Perl щелкните на ссылке Installer.

2. После загрузки файла xampp-win32-perl-addon-xxx-xxx-installer. exe запустите его, дважды щелкнув на его значке.

3. Выберите язык установки Russian (рис. 4.15) и нажмите кнопку OK.



Рис. 4.15. Выбор языка установки







Итак, дополнительные модули Perl установлены. Теперь мы можем приступить к созданию приложений Perl.

Тестирование Perl

Чтобы проверить корректность функционирования интерпретатора Perl, создайте простейшее Perl-приложение. Для этого выполните следующие действия.

1. Запустите стандартную программу Windows Блокнот (Пуск → Все программы → Стандартные → Блокнот).

2. В окне программы Блокнот введите следующий код (рис. 4.19):




...

Внимание!

В первой строке любого сценария Perl после символов #! необходимо указать путь к интерпретатору Perl: «<Путь к корневой папке XAMPP>\perl\bin\perl.exe». Вывод текста или HTML-кода нужно предварять строкой print «Content-type: text/html; charsert = windows-1251\n\n»;, которая указывает тип выводимой информации.

 

3. Для сохранения файла нажмите комбинацию клавиш Ctrl+S. В стандартном окне Windows Сохранить как откройте корневую папку XAMPP, а в ней – папку cgi-bin. Введите имя файла: test.pl и нажмите кнопку Сохранить.

4. Запустите Internet Explorer (Пуск → Все программы → Internet Explorer) или любой другой браузер. В адресной строке браузера введите следующий адрес: https:// localhost/cgi-bin/test.pl. Появление текста «Работа с MySQL» (рис. 4.20) на вебстранице означает, что Perl-приложения выполняются нормально.



Рис. 4.20. Результат выполнения приложения

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

Подключение к базе данных

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

use DBI;  

Для подключения к базе данных используется метод

connect(«DBI:mysql:database=<Имя базы данных>;host=<Имя  

хоста>[;port=<Номер порта>]»,»Имя  

пользователя»,»Пароль»[,<Режим обработки ошибок>]);  

Метод connect() создает соединение с базой данных и возвращает дескриптор соединения  – указатель на объект, отвечающий за взаимодействие с базой данных и реализующий все методы работы с БД. Если установить соединение не удалось, метод connect() возвращает значение undef.


...

Примечание

Необязательный параметр port по умолчанию принимает значение 3306. Режим обработки ошибок мы обсудим в подразделе «Обработка ошибок».

 

Например, вызов метода my $dbh = DBI —»

my $dbh = DBI ->  

connect(«DBI:mysql:database=SalesDept;host=localhost»,  

“username”,”userpassword”);  

осуществляет подключение к серверу MySQL, работающему на локальном компьютере, используя имя пользователя username и пароль userpassword. При этом база данных SalesDept выбирается в качестве текущей. Дескриптор соединения сохраняется в переменной $dbh.


...

Совет

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

 

После окончания работы с базой данных отключимся от нее с помощью метода disconnect();

Рассмотрим пример приложения, которое подключается к базе данных и выводит диагностическое сообщение. Создайте в папке cgi-bin корневой папки XAMPP файл connect.pl и введите в него код, представленный в листинге 4.10.

Листинг 4.10.

Подключение к базе данных

#!»C:\Program Files\xampp\perl\bin\perl.exe»  

print «Content-type: text/html; charset=windows-1251\n\n»;  

#Подключаем модуль DBI  

use DBI;  

#Подсоединяемся к базе данных  

my $dbh = DBI -> connect(“DBI:mysql:database=SalesDept;host=localhost”,  

“username”,”userpassword”);  

if(!$dbh)  

{  

print(“Ошибка доступа к базе данных. Приносим свои извинения”);  

}  

else  

{  

print “Подключение выполнено успешно”;  

}  

#Отсоединяемся от базы данных  

$dbh->disconnect();  



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

Ввод данных в базу

В этом подразделе приводятся сведения о том, как создать приложение, которое записывает в базу введенные пользователем данные. Вначале рассмотрим метод, позволяющий выполнить SQL-команду, не предполагающую получения данных из базы (например, INSERT, UPDATE или DELETE):

do(«<Текст команды>»[,  <Неиспользуемый параметр>,<Привязываемые параметры>])  

Метод do() возвращает количество строк, с которыми была выполнена операция, значение -1, если количество строк неизвестно, и значение undef в случае ошибки.


...

Примечание

Если SQL-команда была выполнена успешно, но не произвела действий с одной строкой, то метод do() возвращает значение E0E, которое рассматривается как числовое значение 0 и как логическое значение TRUE.

 

Единственным обязательным параметром метода do() является текст SQL-команды, которую необходимо выполнить. Например, установить кодировку можно следующим образом:

$dbh -> do(«SET NAMES cp1251»);  


...

Совет

Установка кодировки перед началом работы с данными позволяет избежать некорректного отображения и сохранения в базе данных символов русского алфавита. Была выбрана кодировка Windows (CP-1251), так как именно в ней был создан сценарий input.pl.

 

Привязка параметров используется в случае, когда необходимо выполнить динамическую  SQL-команду, содержащую переменные величины. В тексте команды эти величины нужно заменить символами? а их значения передать в качестве параметров метода do(). Например, пусть имя, телефон и адрес клиента хранятся, соответственно, в переменных $name, $phone и $address. Записать эти данные в базу можно с помощью вызова метода

$dbh – > do(«INSERT INTO Customers (name,phone,address)  

VALUES (?,?,?)»,  

undef,$name,$phone,$address);  

Перед выполнением SQL-команды INSERT вместо знаков вопроса будут подставлены значения переменных $name, $phone и $address (неиспользуемому параметру было присвоено значение undef). При этом интерпретатор Perl автоматически вставляет кавычки там, где это необходимо, экранирует спецсимволы и т. п.

В качестве примера использования метода do() рассмотрим форму саморегистрации нового клиента, в которой клиент может ввести свое имя, телефон и адрес. Помимо метода do(), для создания такого приложения нам потребуется дополнительный модуль Perl CGI и функция param(), которая возвращает список значений, введенных пользователем в поля формы. Функция param() позволяет объединить вывод формы и обработку введенных данных в одном сценарии: если функция вернула непустое значение, значит, нужно обработать введенные пользователем данные, а если пустое – отобразить форму для ввода данных. Если же в качестве аргумента функции param() указывается имя поля формы, то функция вернет значение из этого поля.

Итак, в папке cgi-bin корневой папки XAMPP создайте файл input.pl, содержащий код, представленный в листинге 4.11.

Листинг 4.11. Ввод данных

#!”C:\Program Files\xampp\perl\bin\perl.exe”  

print “Content-type: text/html; charset=windows-1251\n\n”;  

#Подключаем модуль DBI  

use DBI;  

#Подключаем модуль CGI  

use CGI \':all\  

#Если список значений формы пуст, выводим форму  

if(!param())  

{  

print «  

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h1>Пожалуйста, заполните следующие поля:</h1>  

<!– Создаем форму для ввода данных –>  

<!– Обрабатывать введенные данные будет этот же сценарий – input.pl –>  

<form method=\'post\' action=\'input.pl\'>  

<table>  

<!– Создаем поле для ввода имени заказчика –>  

<tr>  

<td>Ваше имя:</td>  

<td><input type=\'text\' name=\'CustomerName\' value=\'\'></td>  

</tr>  

<!– Создаем поле для ввода телефона заказчика –>  

<tr>  

<td>Телефон:</td>  

<td><input type=\'text\' name=\'CustomerPhone\' value=\'(495)\'></td>  

</tr>  

<!– Создаем поле для ввода адреса заказчика –>  

<tr>  

<td>Адрес:</td>  

<td><input type=\'text\' name=\'CustomerAddress\' value=\'\'></td>  

</tr>  

</table>  

<br>  

<!– Создаем кнопку для подтверждения данных –>  

<input type=\'submit\' value=\'Отправить\'>  

</form>  

</body>  

</html>”;  

}  

#Если список значений формы непуст, сохраняем эти значения  

else  

{  

#Подсоединяемся к базе данных  

my $dbh = DBI ->  

connect(«DBI:mysql:database=SalesDept;host=localhost»,  

«username»,»userpassword»);  

if (!$dbh)  

{  

print «Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Устанавливаем кодировку CP-1251  

$dbh->do(«SET NAMES cp1251»);  

#Записываем данные о клиенте в таблицу Customers (Клиенты)  

#param(\'CustomerName\'), param(\'CustomerPhone\') и param(\'CustomerAddress\') –  

#значения, полученные из полей формы с именами  

#CustomerName, CustomerPhone и CustomerAddress  

my $insert = $dbh -> do(«INSERT INTO Customers (name,phone,address)  

values (?, ?, ?)»,  

undef,  

param(\'CustomerName\'), param(\'CustomerPhone\'), param(\'CustomerAddress\'));  

if(!$insert)  

{  

print “Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Отсоединяемся от базы данных  

$dbh->disconnect();  

#Выводим итоговое сообщение  

print «<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<h3>Поздравляем! Регистрация завершена успешно</h3>  

</body>  

</html>”;  

}  





Если же при подключении к базе данных или при выполнении SQL-команды произошла ошибка, вы увидите на странице сообщение «Ошибка доступа к базе данных. Приносим свои извинения». Чтобы получить подробную информацию об ошибке, откройте корневую папку XAMPP, в ней – папку apache, затем папку logs. В папке logs откройте с помощью программы Блокнот файл error.log. В одной из последних строк этого файла вы найдете описание ошибки.

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

Обработка ошибок

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

• PrintError. Если этому параметру присвоено значение 1, то при возникновении ошибки выводится сообщение об ошибке;

• RaiseError. Если этому параметру присвоено значение 1, то при возникновении ошибки выводится сообщение об ошибке и сценарий завершает работу.

Чтобы реализовать собственный алгоритм обработки ошибок, отключите системную обработку ошибок, присвоив обоим параметрам значение 0, например:

my $dbh = DBI -> connect(«DBI:mysql:database=SalesDept;host=localhost»,  

“username”,”userpassword”,  

{PrintError=>0,RaiseError=>0});  

Для получения информации о возникшей ошибке предназначены методы

errstr()  

и

err()  

Метод errstr() возвращает описание ошибки, произошедшей при выполнении последней SQL-команды, или значение undef, если команда была выполнена успешно. Метод mysql_errno() возвращает код ошибки, произошедшей при выполнении последней SQL-команды, или undef, если команда была выполнена успешно.

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

Приведу пример обработки возникшей ошибки – запись ошибки в файл:

my $dbh = DBI -> connect(«DBI:mysql:database=SalesDept;host=localhost»,  

«username»,»userpassword»,  

{PrintError=>0,RaiseError=>0});  

if(!$dbh)  

{  

#Формируем сообщение об ошибке  

my $logmessage = localtime.”  

«.DBI->err().» «.DBI->errstr().»\n»;  

#Открываем log-файл  

my $res = open(my $log, «>>», «mysqlerror.log»);  

if(!$res)  

{  

print “Ошибка при открытии журнала”;  

die();  

};  

#Записываем в файл сообщение об ошибке  

print $log $logmessage;  

#Закрываем файл  

$res = close $log;  

if(!$res)  

{  

print “Ошибка при закрытии журнала”;  

die();  

}  

#Выводим сообщение об ошибке на странице  

print “Ошибка доступа к базе данных.  

Приносим свои извинения”;  

#Завершаем работу  

die();  

}  

Если при подключении к базе данных произойдет ошибка, в файл mysqlerror. log, находящийся в папке cgi-bin, будет записано сообщение, содержащее дату и время, номер и описание ошибки. Например, если база данных SalesDept (Отдел продаж) была удалена, в файле появится запись вида Sat Jun 28 11:15:00 2008 1049 Unknown database \'salesdept\'.

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

Выполнение запроса к базе данных

Для поиска информации в базе данных необходимо последовательно вызвать методы

prepare(«<Текст запроса>»)  

и

execute()  

Метод prepare() обеспечивает подготовку запроса для последующего выполнения и возвращает дескриптор команды  – указатель на объект, реализующий все операции, связанные с запросом: выполнение запроса, обработку результатов запроса и др. Далее вызывается метод execute() дескриптора команды, который выполняет запрос и возвращает значение TRUE в случае успеха или значение undef в случае ошибки. Например, чтобы получить все данные из таблицы Products (Товары), выполните команды

my $query = $dbh->prepare(«SELECT * FROM Products»);  $query -> execute();  

В переменной $query хранится дескриптор команды.


...

Примечание

Если требуется выполнить динамический запрос, содержащий переменные величины, вы можете воспользоваться привязкой параметров, о которой было сказано в подразделе «Ввод данных в базу». А именно, в тексте команды эти величины нужно заменить символами? а их значения передать в качестве параметров метода execute(). Например, получить список товаров, цена которых не превосходит значения переменной $max_price, можно следующим образом:

 

my $query = $dbh->prepare(SELECT * FROM Products  

WHERE price <= ?);  

$query -> execute($max_price);  

Для получения доступа к значениям в результате запроса вы можете использовать метод

fetchrow_hashref([<Регистр>])  

или

fetchrow_arrayref()  

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

finish()  

Рассмотрим работу с запросом на примере вывода списка товаров, то есть данных из таблицы Products (Товары). Создайте в папке cgi-bin корневой папки XAMPP файл input.pl, содержащий код, представленный в листинге 4.12. Листинг 4.12. Получение информации и отображение ее на странице

#!»C:\Program Files\xampp\perl\bin\perl.exe»  

print «


убрать рекламу






Content-type: text/html; charset=windows-1251\n\n»;
 

use DBI;  

#Подсоединяемся к базе данных  

my $dbh = DBI -> connect(«DBI:mysql:database=SalesDept;host=localhost»,  

«username»,»userpassword»);  

if(!$dbh)  

{  

print «Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Устанавливаем кодировку CP-1251  

$dbh->do(«SET NAMES cp1251»);  

#Выполняем запрос к базе данных  

my $query = $dbh->prepare(«SELECT * FROM Products»);  

my $qresult = $query -> execute();  

if(!$qresult)  

{  

print “Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Создаем строку для вывода результатов запроса  

my $pagecontent=””;  

#Для каждой строки из результата запроса  

#записываем данные в хеш и сохраняем ссылку на хеш  

#в переменной $product  

while(my $product = $query -> fetchrow_hashref(«NAME_uc»))  

{  

#Выводим элементы хеша  

#с индексами DESCRIPTION, DETAILS и PRICE  

$pagecontent.=»<tr><td>».$product->{DESCRIPTION}.»</td>».  

«<td>».$product->{DETAILS}.»</td>».  

«<td>».$product->{PRICE}.»</td></tr>\n»;  

}  

#Освобождаем ресурсы  

$query -> finish();  

#Отсоединяемся от базы данных  

$dbh->disconnect();  

#Выводим полученные данные  

print “  

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<!– Выводим заголовок списка товаров –>  

<h1>Список товаров</h1>  

<table>  

<tr>  

<th>Наименование</th>  

<th>Описание</th>  

<th>Цена</th>  

</tr>  

«.$pagecontent.»  

</table>  

</body>  

</html>  

“;  



Отметим, что если в результате запроса присутствуют несколько столбцов с одинаковыми именами (это возможно в случае получения информации из нескольких таблиц), то метод fetchrow_hashref() предоставляет доступ только к последнему из этих столбцов. Кроме того, порядок элементов в хеше может отличаться от порядка столбцов в таблице; в этом легко убедиться, если вывести значения всех полей с помощью цикла foreach:

while(my $product = $query->fetchrow_hashref(«NAME_uc»))  

{  

print «<p>»  

foreach my $field_name (keys %$product)  

{  

print «$product->{$field_name}\t»;  

}  

print “</p>”  

}  

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

#!»C:\Program Files\xampp\perl\bin\perl.exe»  

print «Content-type: text/html; charset=windows-1251\n\n»;  

use DBI;  

#Подсоединяемся к базе данных  

my $dbh = DBI -> connect(«DBI:mysql:database=SalesDept;host=localhost»,  

«username»,»userpassword»);  

if(!$dbh)  

{  

print «Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Устанавливаем кодировку CP-1251  

$dbh->do(«SET NAMES cp1251»);  

#Выполняем запрос к базе данных  

my $query = $dbh->prepare(«SELECT * FROM Products»);  

my $qresult = $query -> execute();  

if(!$qresult)  

{  

print “Ошибка доступа к базе данных. Приносим свои извинения”;  

die();  

}  

#Создаем строку для вывода результатов запроса  

my $pagecontent=””;  

#Для каждой строки из результата запроса  

#записываем данные в массив и сохраняем ссылку на массив  

#в переменной $product  

while(my $product = $query -> fetchrow_arrayref())  

{  

#Выводим элементы массива с номерами 1, 2, 3  

$pagecontent.=»<tr><td>».$product->[1].»</td>».  

«<td>».$product->[2].»</td>».  

«<td>».$product->[3].»</td></tr>\n»;  

}  

#Освобождаем ресурсы  

$query -> finish();  

#Отсоединяемся от базы данных  

$dbh->disconnect();  

#Выводим полученные данные  

print “  

<html>  

<head>  

<title>Работа с MySQL</title>  

</head>  

<body>  

<!– Выводим заголовок списка товаров –>  

<h1>Список товаров</h1>  

<table>  

<tr>  

<th>Наименование</th>  

<th>Описание</th>  

<th>Цена</th>  

</tr>  

«.$pagecontent.»

</table>

</body>

</html>

“;

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

Итоги

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

• подключение к базе данных и отключение от нее;

• выполнение SQL-команд как получающих информацию из базы данных (методы prepare() и execute()), так и не получающих ее (метод do());

• обработка ошибок.

Ознакомиться с полным списком функций модуля Perl DBI вы можете, перейдя по странице https://dbi.perl.org/ на ссылку Manual pages.

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

4.3. Интерфейс с Java

 Сделать закладку на этом месте книги

В этом разделе рассмотрим разработку Java-сервлетов, использующих базу данных MySQL для хранения и поиска информации. Вы узнаете, как создать и настроить среду разработки сервлетов, а также научитесь использовать для взаимодействия с MySQL функции JDBC (Java Database Connectivity – интерфейс доступа к базам данных из приложений Java).

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

Среда разработки сервлетов

Для создания сервлетов необходимы следующие программы:

• Java Development Kit (JDK) – пакет поддержки разработок в среде Java;

• дополнительная библиотека servlet-api.jar (или servlet.jar), необходимая для компиляции сервлетов, но не входящая в состав Java Development Kit;

• контейнер сервлетов – программа, обеспечивающая загрузку и выполнение сервлетов;

• программа, выполняющая функции веб-сервера.

Широко известным контейнером сервлетов является Tomcat – свободно распространяемая программа с открытым кодом. Tomcat может выполнять функции веб-сервера либо использоваться совместно с веб-сервером Apache. В состав Tomcat входит и библиотека servlet-api.jar.

Кроме того, чтобы сервлеты могли взаимодействовать с базой данных, необходимо установить и подключить JDBC-драйвер. В качестве такого драйвера был выбран MySQL Connector/J.

Итак, наша среда разработки будет состоять из Java Development Kit, Tomcat и MySQL Connector/J. В следующем подразделе вы узнаете, как установить и настроить эти компоненты.

Подготовка к работе

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

Установка Java Development Kit

Для установки Java Development Kit выполните следующие действия.

1. Чтобы скачать дистрибутив JDK с сайта компании-разработчика, откройте вебстраницу https://java.sun.com/javase/downloads/index.jsp и в разделе JDK 6 Update X щелкните на кнопке Download (Скачать).

2. На открывшейся веб-странице выберите вариант дистрибутива (рис. 4.25):

• если вы работаете в 32-разрядной операционной системе (Windows Vista/ Server 2003/XP/Millennium Edition/2000/98/95), то в поле Plaltform (Платформа) выберите из списка значение Windows;

• если вы работаете в 64-разрядной операционной системе (Windows Vista x64/Server 2003 x64/XP x64), то в поле Plaltform (Платформа) выберите из списка значение Windows x64.

3. Установите флажок I agree to the Java SE Development Kit 6 License Agreement (Я согласен с условиями лицензионного соглашения) и нажмите кнопку Continue (Продолжить).



Рис. 4.25. Выбор варианта дистрибутива













Для возврата в окно Переменные среды нажмите кнопку OK.

2. Настройте путь к дополнительным библиотекам Java. Для этого щелкните на имени переменной CLASSPATH и нажмите кнопку Изменить. К существующему значению переменной добавьте пути к файлам servlet-api.jar и mysql-connector-java-xxx-bin.jar. Обратите внимание, что в значении переменной CLASSPATH необходимо указывать не только папки, в которых находятся файлы, но и имена файлов с расширениями (например, C: \Program Files\Tomcat\lib\ servlet-api.j ar;C: \Program Files\Tomcat\lib\mysql-connector-java-xxx-bin.jar). Пути к файлам разделяются точкой с запятой.

Для возврата в окно Переменные среды нажмите кнопку OK.

3. Создайте переменную CATALINA_HOME. Для этого в блоке Системные переменные нажмите кнопку Создать. В появившемся окне Новая системная переменная

введите имя переменной – CATALINA_HOME и значение – путь к корневой папке Tomcat, например C: \Program Files\Tomcat.

Для возврата в окно Переменные среды нажмите кнопку OK.

• Аналогичным образом создайте переменную JAVA_HOME. В значении этой переменной укажите путь к корневой папке Java, например C: \Program Files\Java\jdk1.6.0_0 6.

Итак, вы завершили настройку среды разработки сервлетов. Теперь можно создать первый сервлет.

Создание и запуск сервлета

Создание сервлета включает три основных этапа:

• написание кода;

• компиляция сервлета;

• размещение и регистрация сервлета в контейнере.

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

Рассмотрим порядок создания сервлета на примере простейшего сервлета.

1. Запустите стандартную программу Windows Блокнот (Пуск → Все программы → Стандартные → Блокнот).

2. В окне программы Блокнот введите код, представленный в листинге 4.14.

Листинг 4.14. Простейший сервлет

import java.io.*;  

import javax.servlet.*;  

import javax.servlet.http.*;  

public class test extends HttpServlet {  

public void service(HttpServletRequest request,  

HttpServletResponse response) throws IOException, ServletException {  

response.setContentType(«text/html;charset=windows-1251»);  

PrintWriter out = response.getWriter();  

out.println(«Мой первый сервлет»);  

}  

}  



5. Скомпилируйте сервлет, выполнив в окне командной строки команду

javac test.java  

В результате компиляции в папке, где находится файл test.java, будет создан файл test.class. Этот файл и есть созданный нами сервлет.


...

Внимание!

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

 

6. Скопируйте файл test.class в папку <Корневая папка Tomcat>\webapps\ROOT\

WEB-INF\classes, например C: \Program Files\Tomcat\webapps\ROOT\WEB-INF\classes (если исходный файл test.java был создан в этой папке, то файл test.class уже находится в нужной папке и копирование не требуется).


...

Внимание!

Обратите внимание на регистр символов: важно, чтобы папка для размещения сервлетов называлась именно classes (не CLASSES и не Classes).

 

7. Откройте для редактирования (например, с помощью программы Блокнот) файл web.xml, находящийся в папке <Корневая папка Tomcat>\webapps\ROOT\WEB-INF.

В этом файле для каждого нового сервлета необходимо добавить в элемент web-app вложенные элементы servlet и servlet-mapping (листинг 4.15).

Листинг 4.15.

Файл web.xml

<?xml version=”1.0” encoding=”ISO-8859-1”?>  

<web-app …<Дополнительные атрибуты>…>  

<servlet>  

<servlet-name><Имя сервлета 1></servlet-name>  

<servlet-class><Класс сервлета 1></servlet-class>  

</servlet>  

<servlet-mapping>  

<servlet-name><Имя сервлета 1></servlet-name>  

<url-pattern><Адрес сервлета 1></url-pattern>  

</servlet-mapping>  

<servlet>  

<servlet-name><Имя сервлета 2></servlet-name>  

<servlet-class><Класс сервлета 2>test</servlet-class>  

</servlet>  

<servlet-mapping>  

<servlet-name><Имя сервлета 2></servlet-name>  

<url-pattern><Адрес сервлета 2></url-pattern>  

</servlet-mapping>  

 

</web-app>  

Элемент servlet должен содержать произвольное имя сервлета и имя класса, заданное в коде сервлета (см., например, листинг 4.14). Элемент servlet-mapping должен содержать то же самое имя сервлета и URL-адрес, по которому будет доступен этот сервлет.

Например, после добавления сервлета test файл web.xml примет следующий вид (листинг 4.16).

Листинг 4.16. Пример файла web.xml

<?xml version=”1.0” encoding=”ISO-8859-1”?>  

<web-app …<Дополнительные атрибуты>…>  

<servlet>  

<servlet-name>test</servlet-name>  

<servlet-class>test</servlet-class>  

</servlet>  

<servlet-mapping>  

<servlet-name>test</servlet-name>  

<url-pattern>/servlet/test</url-pattern>  

</servlet-mapping>  

</web-app>  





Итак, вы научились создавать собственные сервлеты и запускать их. Отмечу, что при изменении ранее созданного сервлета его необходимо перекомпилировать (см. пп. 5–6), а затем перезапустить Tomcat, используя файлы shutdown.bat и startup.bat в папке bin корневой папки Tomcat.

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

Подключение к базе данных

В данном разделе мы рассмотрим простой сервлет, который подключается к базе данных и выводит диагностическое сообщение. Чтобы создать такой сервлет, необходимо импортировать пакеты java.sql.*.

Соединение с базой данных описывается объектом класса Connection. Для создания такого объекта предназначен метод

public static Connection getConnection(“jdbc:mysql://<Имя  

хоста>[:<Имя порта>]/<Имя базы данных>[<Параметры>]”)  

throws SQLException  

класса DriverManager. Параметры соединения задаются в формате

?<Имя параметра>=<Значение>&<Имя параметра>=<Значение>…  

Важнейшими параметрами соединения являются user (имя пользователя), password (пароль) и characterEncoding (кодировка).

Если при подключении к базе данных произошла ошибка, метод getConnection() сгенерирует исключение SQLException, о котором подробно будет рассказано в подразделе «Обработка ошибок».

Например, вызов метода

Connection dbh =  

DriverManager.getConnection(«jdbc:mysql://localhost/SalesDept»  

+ «?user=username»  

+ «&password=userpassword»  

+ «&characterEncoding=cp1251»);  

осуществляет подключение к серверу MySQL, работающему на локальном компьютере, используя имя пользователя username и пароль userpassword, устанавливает для взаимодействия с сервером кодировку CP-1251 и выбирает базу данных SalesDept (Отдел продаж) в качестве текущей. Созданному соединению соответствует объект dbh класса Connection.


...

Совет

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

 

Создайте теперь сервлет Connect с исходным кодом, представленным в листинге 4.17.

Листинг 4.17.

Подключение к базе данных

import java.io.*;  

import javax.servlet.*;  

import javax.servlet.http.*;  

import java.sql.*;  

public class Connect extends HttpServlet {  

public void service(HttpServletRequest request,  

HttpServletResponse response) throws IOException, ServletException {  

response.setContentType(“text/html;charset=windows-1251”);  

PrintWriter out = response.getWriter();  

try {  

//Подсоединяемся к базе данных  

Connection dbh =  

DriverManager.getConnection(«jdbc:mysql://localhost/SalesDept»  

+»?user=username&password=userpassword&characterEncoding=cp1251»);  

//Обрабатываем испключение  

} catch (SQLException ex) {  

out.println(“Ошибка доступа к базе данных. Приносим свои извинения”);  

return;  

}  

out.println(«Подключение выполнено успешно»);  

}  

}  



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

Выполнение простых SQL-команд. Обработка результатов запроса

Для выполнения SQL-команд, не имеющих подстановочных параметров, предназначен класс Statement. Объект класса Statement создается с помощью метода

Statement createStatement() throws SQLException  

класса Connection. Например, вызов метода

Statement query = dbh.createStatement();  

создает объект query, соответствующий SQL-команде. Если SQL-команда не предполагает получение данных из базы (такими командами являются, например, команды INSERT, UPDATE, DELETE), то для ее выполнения используется метод

int executeUpdate(«<Текст команды>») throws SQLException  

класса Statement. Метод executeUpdate() возвращает количество строк, с которыми была выполнена операция. Для выполнения SQL-запроса используется метод

ResultSet executeQuery(«<Текст запроса>») throws SQLException  

класса Statement. Метод executeQuery() возвращает объект класса ResultSet, содержащий набор полученных запросом данных. Важным элементом результирующего набора является курсор  – указатель на текущую строку.

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

• boolean next() throws SQLException

Переводит курсор на следующую строку. При первом вызове устанавливает курсор на первую строку. Если строки результирующего набора исчерпаны, возвращает значение FALSE.

• Методы вида get^rn данных>(<Имя или номер столбца>) возвращают значение, находящееся в текущей строке в указанном столбце. В зависимости от типа данных столбца вы можете использовать следующие функции:

• для числовых столбцов:

boolean getBoolean(<Имя или номер столбца>)  

throws SQLException  

int getInt(<Имя или номер столбца>)  

throws SQLException  

long getLong(<Имя или номер столбца>)  

throws SQLException  

float getFloat(<Имя или номер столбца>)  

throws SQLException  

double getDouble(<Имя или номер столбца>)  

throws SQLException  

BigDecimal getBigDecimal(<Имя или номер столбца>)  

throws SQLException  

• для столбцов с типом даты и/или времени:

Date getDate(<Имя или номер столбца>)  

throws SQLException  

Timestamp getTimestamp(<Имя или номер столбца>)  

throws SQLException  

Time getTime(<Имя или номер столбца>)  

throws SQLException  

• для символьных типов данных:

String getString(<Имя или номер столбца>)  

throws SQLException  

byte[] getBytes(<Имя или номер столбца>)  

throws SQLException  

Рассмотрим сервлет, который выполняет простой запрос для получения данных из таблицы Products (Товары) и выводит сведения о товарах на веб-странице (листинг 4.18). Листинг 4.18. Получение информации и отображение ее на странице

import java.io.*;  

import javax.servlet.*;  

import javax.servlet.http.*;  

import java.sql.*;  

public class Output extends HttpServlet {  

public void service(HttpServletRequest request,  

HttpServletResponse response) throws IOException, ServletException {  

response.setContentType(«text/html;charset=windows-1251»);  

PrintWriter out = response.getWriter();  

//Создаем строку для вывода результата запроса  

String pagecontent = «»;  

try {  

//Подсоединяемся к базе данных  

Connection dbh =  

DriverManager.getConnection(«jdbc:mysql://localhost/SalesDept»  

+»?user=username&password=userpassword&characterEncoding=cp1251»);  

//Создаем объект для SQL-команд  

Statement query = dbh.createStatement();  

//Выполняем запрос к базе данных  

ResultSet qresult = query.executeQuery(«SELECT * FROM Products»);  

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

//description (наименование), details (описание) и price (цена)  

while (qresult.next()) {  

pagecontent +=  

«<tr><td>» + qresult.getString(«description») + «</td>» +  

«<td>» + qresult.getString(«details») + «</td>» +  

«<td>» + qresult.getBigDecimal(«price») + «</td></tr>\n»;  

}  

//Обрабатываем исключение  

} catch (SQLException ex) {  

out.println(“Ошибка доступа к базе данных. Приносим свои извинения”);  

return;  

}  

//Выводим полученные данные  

out.println(«<html>»);  

out.println(«<head>»);  

out.println(«<title>Работа с MySQL</title>»);  

out.println(«</head>»);  

out.println(«<body>»);  

out.println(“<!– Выводим заголовок списка товаров –>”);  

out.println(“<h1>Список товаров</h1>”);  

out.println(«<table>»);  

out.println(«<tr>»);  

out.println(«<th>Наименование</th>»);  

out.println(«<th>Описание</th>»);  

out.println(«<th>Цена</th>»);  

out.println(«</tr>»);  

out.println(pagecontent);  

out.println(«</table>»);  

out.println(«</body>»);  

out.println(“</html>”);  

}  

}  



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

while (qresult.next()) {  

pagecontent +=  

«<tr><td>» + qresult.getString(2) + «</td>» +  

«<td>» + qresult.getString(3) + «</td>» +  

«<td>» + qresult.getBigDecimal(4) + «</td></tr>\n»;  

}  

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

Выполнение параметризованных SQL-команд

Для выполнения динамических SQL-команд, содержащих подстановочные параметры, предназначен класс PreparedStatement. Объект класса PreparedStatement создается с помощью метода

PreparedStatement prepareStatement(«<Шаблон SQL-команды>»)  throws SQLException  

класса Connection. Места вставки подстановочных значений в шаблоне SQL-команды обозначаются символами \'?\'. Например, вызов метода

PreparedStatement insert =  

dbh.prepareStatement(“INSERT INTO Customers  

(name,phone,address) VALUES (?,?,?)”);  

создает объект insert класса PreparedStatement, соответствующий параметризованной SQL-команде. Параметрами команды являются имя, телефон и адрес клиента, сохраняемые в базе данных. Для присвоения значений параметрам используются методы вида

void set<Тип данных>(<Порядковый номер парам


убрать рекламу






етра в шаблоне>,
 

<Значение параметра>)  

throws SQLException  

Например, если переменные name, phone и address содержат, соответственно, имя, телефон и адрес клиента, то подставить их значения в команду insert можно с помощью вызова методов

insert.setString(1,name);  

insert.setString(2,phone);  

insert.setString(3,address);  


...

Примечание

Если подставляемые значения содержат спецсимволы, то методы set<Тип данных>() автоматически экранируют их.

 

После того как нужные значения подставлены в SQL-команду, ее можно выполнить путем вызова метода

int executeUpdate() throws SQLException  

или

ResultSet executeQuery() throws SQLException  

класса PreparedStatement. Метод executeUpdate() предназначен для выполнения команд, не предполагающих получение данных из базы (например, INSERT, UPDATE, DELETE) и возвращает количество строк, с которыми была выполнена операция. Метод executeQuery() предназначен для выполнения запросов к базе данных и возвращает объект класса ResultSet, содержащий результирующий набор данных. О том, как извлечь конкретные значения из этого объекта, было рассказано в подразделе «Выполнение простых SQL-команд. Обработка результатов запроса». Рассмотрим пример сервлета, который выполняет параметризованную SQL-команду, а именно: сохраняет в базе сведения, введенные пользователем в веб-форме. Помимо функций JDBC, для создания такого сервлета нам потребуется метод

public java.util.Enumeration getParameterNames()  

класса HttpServletRequest. Напомним, что метод service() получает в качестве параметра объект класса HttpServletRequest, который содержит все параметры HTTP-запроса к Java-серверу. Метод getParameterNames() этого объекта возвращает список имен полей формы, заполненной пользователем. Если этот список пуст, значит, нужно отобразить форму ввода данных, а если нет – обработать введенные данные. Кроме того, мы будем использовать метод

public java.lang.String getParameter(«<Имя поля формы>»)  

класса HttpServletRequest для получения значения, введенного пользователем в поле формы, и метод

public void setCharacterEncoding(<Кодировка>)  throws java.io.UnsupportedEncodingException  





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

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

Обработка ошибок

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

public String getMessage()  

возвращает описание ошибки, а метод

public int getErrorCode()  

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

public void log(«<Текст сообщения>»)  

класса HttpServlet:

 

try {  

//Операции с базой данных  

 

//Обрабатываем исключение  

} catch (SQLException ex) {  

out.println(«Ошибка доступа к базе данных.»);  

out.println(«Приносим свои извинения»);  

//Записываем сообщение об ошибке в log-файл  

log(ex.getErrorCode() + « « +ex.getMessage());  

return;  

}  

 

Например, если модифицировать таким образом сервлет Input (см. листинг 4.19), то в случае отсутствия в базе данных таблицы Customers (Клиенты) в log-файл будет записано следующее сообщение:

28.06.2008 11:15:00 org.apache.catalina.core.ApplicationContext log  INFO: Input: 1146 Table \'salesdept.customers\' doesn\'t exist  


...

Примечание

При запуске сервлета в созданной нами среде разработки сервлетов сообщение об ошибке будет записано в файл <Корневая папка Tomcat>\logs\localhost.<Текущая дата>.log. При использовании хостинга с поддержкой сервлетов уточните имя и местоположение log-файла у провайдера хостинга.

 

Итак, вы узнали, каким образом исключение SQLException позволяет организовать обработку ошибок, возникших при обращении к базе данных. В завершение кратко обобщим основные сведения, рассмотренные в разделе 4.3 «Интерфейс с Java».

Итоги

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

• метод getConnection() класса DriverManager для подключения к базе данных, установки кодировки и выбора текущей базы данных;

• методы createStatement() и prepareStatement() класса Connection для создания объектов, отвечающих за выполнение SQL-команды на сервере MySQL;

• методы set<Тип данных>() класса PreparedStatement для подстановки значений в параметризованный запрос;

• методы executeUpdate() классов Statement и PreparedStatement для выполнения SQL-команд изменения данных;

• методы executeQuery() классов Statement и PreparedStatement для выполнения SQL-запросов;

• методы next() и get<Тип данных>() класса ResultSet для получения отдельных значений из результата запроса;

• методы getMessage() и getErrorCode() класса SQLException для обработки ошибок взаимодействия с базой данных.

Разумеется, возможности интерфейса JDBC не исчерпываются перечисленными функциями. Полную информацию о JDBC вы найдете на странице https://java.sun.com/javase/6/docs/technotes/guides/jdbc/.

Подведем теперь итоги главы.

4.4. Резюме

 Сделать закладку на этом месте книги

В данной главе вы познакомились с возможностями популярных языков веб-программирования – PHP, Perl и Java – по интеграции с базой данных MySQL. Хотя мы ограничились рассмотрением только самых необходимых функций, позволяющих подключаться к базе данных и выполнять SQL-команды, с помощью этих функций вы можете создавать широкий спектр динамических веб-приложений.

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

Глава 5 Администрирование и безопасность

 Сделать закладку на этом месте книги

В предыдущих главах вы изучали функциональные возможности СУБД MySQL – те возможности работы с данными, которые необходимы для решения ваших бизнес-задач. В этой главе мы рассмотрим вспомогательные, но не менее важные процессы: управление доступом пользователей к базе данных и предотвращение потерь данных в случае сбоев. Мы расскажем, как выполнять операции администрирования с помощью специальных SQL-команд, утилит командной строки, а также с помощью графической утилиты MySQL Administrator.

В первую очередь речь пойдет о разграничении доступа пользователей MySQL. Контроль действий пользователей включает два этапа:

• когда пользователь пытается подключиться к серверу баз данных, программа MySQL проверяет, разрешено ли ему подключение, то есть проверяет его учетную запись;  

• когда пользователь пытается выполнить какую-либо операцию, программа MySQL проверяет, имеет ли пользователь привилегию, разрешающую эту операцию.

Следующий раздел посвящается операциям с учетными записями пользователей MySQL. Систему привилегий доступа мы рассмотрим в разделе 5.2 «Система привилегий доступа».

5.1. Учетные записи пользователей

 Сделать закладку на этом месте книги

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

Общие сведения об учетных записях

Под учетной записью пользователя MySQL подразумевается строка в таблице user (Пользователь) системной базы данных mysql. Первичным ключом в этой таблице служат столбцы Host и User. Таким образом, в MySQL идентификация пользователя основана не только на имени пользователя, но и на комбинации имени пользователя и хоста, с которого подключается пользователь. Это означает, что вы не просто можете ограничить круг хостов, с которых разрешено подключаться данному пользователю; вы можете, например, создать разные  учетные записи (а следовательно, назначить разные привилегии доступа) для пользователя anna, подключающегося с компьютера localhost, и для пользователя anna, подключающегося с компьютера somedomain.com.

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

Столбец Host допускает следующие значения:

• конкретное имя компьютера или IP-адрес;

• маска подсети (например, 192.168.1.0/255.255.255.0);

• маска имени компьютера или маска IP-адреса, которая может содержать подстановочные символы:

% – на месте знака процента может быть любое количество произвольных символов;

_ – на месте знака подчеркивания может быть ровно один произвольный символ.


...

Примечание

Если маска начинается с цифры или точки, то она рассматривается как маска IP-адреса. Поэтому значение «122.somedomain.com» не соответствует маске «122.%».

 

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

\'<Значение столбца User>\'[@\'<Значение столбца Host>\']  

Например, \'anna\'@\'localhost\'. Если значение столбца Host не указано, подразумевается маска %, так что идентификаторы \'anna\' и \'anna\'@ % эквивалентны.

При подключении пользователя к серверу MySQL происходит идентификация пользователя – поиск соответствующей ему учетной записи. Поиск начинается с тех строк таблицы user, в которых значение столбца Host не содержит подстановочных символов. Поэтому, например, если в таблице зарегистрированы две учетные записи с идентификаторами, соответственно, \'anna\'@ % и \'anna\'@\'localhost\', то при подключении пользователя с именем anna с локального компьютера будет выбрана вторая из них.

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


...

Примечание

Имена пользователей и пароли чувствительны к регистру символов, а имена хостов – не чувствительны.

 

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

Регистрация пользователя

Чтобы создать учетную запись пользователя, выполните команду

CREATE USER <Идентификатор пользователя>  [IDENTIFIED BY [PASSWORD] \'<Пароль>\'];  

Обязательным параметром этой команды является идентификатор нового пользователя. Если не задан параметр IDENTIFIED BY, то будет использоваться пустой пароль. Параметр PASSWORD необходимо указать в том случае, если вы вводите не реальный, а зашифрованный пароль (что позволяет избежать передачи незашифрованного пароля при отправке на сервер команды CREATE USER). Получить зашифрованное значение из реального пароля вы можете с помощью функции

PASSWORD(\'<Реальный пароль>\')  

Например, команда

CREATE USER \'anna\' IDENTIFIED BY \'annapassword\  

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

CREATE USER \'anna\'@\'localhost\' IDENTIFIED BY PASSWORD  \'*3C7F72EAE78BC95AAFBFD21F8741C24A0056C04B\  

создает учетную запись для пользователя anna, подключающегося с локального компьютера, и устанавливает в качестве пароля значение annalocpassword (поскольку функция PASSWORD(\'annalocpassword\') возвращает значение *3C7F72EAE78BC95AAFBFD21F8741C24A0056C04B).

Сразу после выполнения команды CREATE USER новый пользователь может подключаться к серверу MySQL.

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

Установка пароля

Для установки пароля предназначена команда

SET PASSWORD [FOR <Идентификатор пользователя>]  = PASSWORD(\'<Пароль>\');  

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

SET PASSWORD FOR \'anna\'@\'%\' =  PASSWORD(\'newannapassword\');  

и

SET PASSWORD FOR \'anna\'@\'%\' =  \'*006B99DE1BDA1BE6E1FFF714E764A8FAB0E614DF\  



UPDATE mysql.user SET Password=PASSWORD(\'<Новый пароль root>\') WHERE  

User=\'root\  

FLUSH PRIVILEGES;  


...

Внимание!

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

 

Для сохранения init-файла нажмите комбинацию клавиш Ctrl+S. В стандартном окне Windows Сохранить как выберите папку, в которую нужно поместить файл (например, C:\). Введите имя файла (например, mysql.init) и нажмите кнопку Сохранить.

3. Откройте окно командной строки Windows. Для этого нажмите кнопку Пуск, в меню выберите пункт Выполнить, в появившемся окне Запуск программы в поле Открыть введите команду cmd и нажмите кнопку OK. На экране возникнет окно командной строки, в которой выполните следующую команду (рис. 5.2):

mysqld-nt –defaults-file=<Путь к файлу my.ini>  –init-file=<Путь к init-файлу>  

Например,

mysqld-nt –defaults-file=”C:\Program Files\MySQL\MySQL  Server 5.0\my.ini” –init-file=C:\mysql.init  



4. Остановите сервер MySQL с помощью диспетчера задач, как описано в п. 1, а затем удалите init-файл.

5. Запустите сервер MySQL в обычном режиме. Теперь вы можете использовать новый пароль пользователя root, который был указан в init-файле.

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

Удаление пользователя

Удалить учетную запись вы можете с помощью команды

DROP USER <Идентификатор пользователя>;  

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

Просмотр учетных записей

Для получения информации о зарегистрированных пользователях выполним запрос к таблице user (Пользователь) системной базы данных mysql, например

SELECT * FROM mysql.user;  



Элементы первого уровня в этом списке соответствуют учетным записям вида \'<Имя пользователя>\'@\'%\'. Вложенные элементы соответствуют записям с тем же именем пользователя, но другим хостом. Дважды щелкнув кнопкой мыши на имени пользователя, вы можете открыть или скрыть вложенные элементы.

Например, если для пользователя anna имеются учетные записи с идентификаторами \'anna\'@\'localhost\' и \'anna\'@\'%\', то после щелчка кнопкой мыши на корневом элементе anna вы увидите в правой области окна информацию для учетной записи (см. рис. 5.3), а после щелчка на вложенном элементе localhost – информацию для записи \'anna\'@\'localhost\'. На вкладке User Information (Информация о пользователе) в обоих случаях будут отображены одинаковые сведения, но на остальных вкладках, в частности на вкладке Schema Privileges (Привилегии доступа к базам данных), сведения могут отличаться. Если же для пользователя anna учетная запись \'anna\'@\'%\' не существует, то после щелчка на корневом элементе anna вкладки в правой области станут неактивными.

Помимо просмотра информации о пользователях и хостах, с которых пользователям разрешено подключаться, вы можете выполнить в MySQL Administrator следующие операции:

• Создание нового пользователя.

В правой области главного окна нажмите кнопку Add new user (Добавить нового пользователя). На вкладке User Information (Информация о пользователе) введите имя и пароль нового пользователя. Нажмите кнопку Apply Changes (Сохранить изменения).

Для нового пользователя автоматически создается элемент первого уровня, то есть учетная запись вида \'<Имя пользователя>\'@\'%\'. В дальнейшем вы можете добавить для пользователя другие учетные записи, а эту удалить.

• Добавление новой учетной записи для пользователя.

В области User Accounts (Учетные записи) щелкните правой кнопкой мыши на имени пользователя и выберите в контекстном меню пункт Add host from which the user can connect (Добавить хост, с которого будет разрешено подключаться пользователю). В окне Add Host (Добавление хоста) введите нужное значение (о том, как задать хост или маску хоста для учетной записи, вы узнали из подраздела «Общие сведения об учетных записях»). Нажмите сначала кнопку OK, а затем в главном окне MySQL Administrator кнопку Apply Changes (Сохранить изменения).

• Удаление учетной записи для пользователя.


...

Внимание!

Если для пользователя создана единственная учетная запись, то ее удаление приведет к удалению пользователя.

 

В области User Accounts (Учетные записи) щелкните правой кнопкой мыши на элементе, который соответствует удаляемой учетной записи, и выберите в контекстном меню пункт Remove host from which the user can connect (Удалить хост, с которого разрешено подключаться пользователю). В правой области главного окна нажмите кнопку Apply Changes (Сохранить изменения).

• Установка пароля пользователя.

В области User Accounts (Учетные записи) щелкните на имени пользователя. В правой области окна на вкладке User Information (Информация о пользователе) введите новый пароль в поля Password (Пароль) и Confirm Password (Подтверждение пароля). Нажмите кнопку Apply Changes (Сохранить изменения). Новый пароль будет установлен для всех учетных записей с данным именем пользователя.

• Удаление пользователя.

В области User Accounts (Учетные записи) щелкните правой кнопкой мыши на имени пользователя и выберите в контекстном меню пункт Delete user (Удалить пользователя). На экране возникнет диалоговая панель, в которой нужно подтвердить удаление, нажав кнопку Yes (Да).

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

5.2. Система привилегий доступа

 Сделать закладку на этом месте книги

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

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

Общие сведения о системе привилегий доступа

Создание привилегии доступа в MySQL подразумевает определение следующих параметров:

• идентификатор учетной записи пользователя, которому предоставляется привилегия;

• тип привилегии, то есть тип операций, которые будут разрешены пользователю;

• область действия привилегии.

В MySQL используются следующие основные типы привилегий:

• ALL [PRIVILEGES] – предоставляет все привилегии, кроме GRANT OPTION, для указанной области действия;

• ALTER – разрешает выполнение команд ALTER DATABASE и ALTER TABLE;

• CREATE – разрешает выполнение команд CREATE DATABASE и CREATE TABLE;

• CREATE USER – разрешает выполнение команд CREATE USER, DROP USER, RENAME USER;

• DELETE – разрешает выполнение команды DELETE;

• DROP – разрешает выполнение команд DROP DATABASE и DROP TABLE;

• FILE – разрешает чтение и создание файлов на сервере с помощью команд SELECT… INTO OUTFILEи LOAD DATA INFILE;

• INDEX – разрешает выполнение команд CREATE INDEX и DROP INDEX;

• INSERT – разрешает выполнение команды INSERT;

• SELECT – разрешает выполнение команды SELECT;

• LOCK TABLES – разрешает выполнение команды LOCK TABLES при наличии привилегии SELECT для блокируемых таблиц;

• SHOW DATABASES – разрешает отображение всех баз данных при выполнении команды SHOW DATABASES (если эта привилегия отсутствует, то в списке будут отображены только те базы данных, по отношению к которым у пользователя есть какая-либо привилегия);

• RELOAD – разрешает выполнение команды FLUSH;

• SUPER – привилегия администратора сервера; в частности, разрешает выполнение команды SET GLOBAL;

• UPDATE – разрешает выполнение команды UPDATE;

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


...

Примечание

Здесь приведены только те типы привилегий, которые требуются для выполнения операций, описанных в данной книге. Полный список типов привилегий вы можете найти в документации компании-разработчика на веб-странице https://dev.mysql.com/doc/refman/5.0/en/privileges-provided.html.

 

Областью действия привилегии могут быть:

• все базы данных (такие привилегии называются глобальными);

• отдельная база данных;

• таблица;

• столбец таблицы.

Каждый тип привилегии имеет свои допустимые области действия. Так, привилегии FILE, SHOW DATABASES, RELOAD, SUPER и CREATE USER могут быть только глобальными. Привилегия LOCK TABLES может применяться глобально или к отдельным базам данных, но не к отдельным таблицам. К отдельным столбцам таблицы применимы только привилегии SELECT, INSERT и UPDATE.

Чтобы получить разрешение на выполнение операции с каким-либо объектом базы данных, пользователю достаточно иметь привилегию соответствующего типа для какой-либо области действия, содержащей этот объект. Например, пользователь сможет выполнить запрос данных из столбца description (наименование) таблицы Products (Товары) базы данных SalesDept (Отдел продаж), если у него есть хотя бы одна из следующих привилегий:

• глобальная привилегия SELECT;

• привилегия SELECT для базы данных SalesDept;

• привилегия SELECT для таблицы Products;

• привилегия SELECT для столбца description.

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

UPDATE SalesDept.Products SET price=\'548.00\' WHERE id=5;  

доступна пользователю, если у него одновременно есть привилегия SELECT для таблицы Products (или для базы данных SalesDept, или глобальная) и привилегия UPDATE для столбца price (или для таблицы Products, или для базы данных SalesDept, или глобальная).

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

Предоставление привилегий

Для предоставления привилегий пользователям используется команда

GRANT <Тип привилегии>  

[(<Список столбцов>)] ON <Область действия>  

TO <Идентификатор пользователя>  

[WITH GRANT OPTION];  

В качестве области действия вы можете указать одно из следующих значений:

• *.* – привилегия будет действовать глобально;

• <Имя базы данных>.* – привилегия будет действовать для указанной базы данных;

• * – привилегия будет действовать для базы данных, которая в момент выполнения команды GRANT являлась текущей;

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

Рассмотрим несколько примеров.

• GRANT CREATE ON *.* TO \'anna\'@\'localhost\

Команда предоставляет пользователю anna\'@\'localhost привилегию на создание баз данных и таблиц в любой базе данных.

• GRANT DROP ON SalesDept.* TO \'anna\'@\'localhost\

Команда предоставляет пользователю anna\'@\'localhost привилегию на удаление таблиц в базе данных SalesDept (Отдел продаж), а также на удаление самой базы данных  SalesDept.

• GRANT SELECT ON SalesDept.Products TO \'anna\'@\'localhost\ Команда предоставляет пользователю anna\'@\'localhost привилегию на получение данных из таблицы Products (Товары) базы данных SalesDept (Отдел продаж).

• GRANT UPDATE (price) ON SalesDept.Products TO \'anna\'@\'localhost\ Команда предоставляет пользователю anna\'@\'localhost привилегию на изменение данных в столбце price (цена) таблицы Products (Товары).

При назначении привилегий необходимо иметь в виду следующие особенности.

• Если учетная запись с указанным идентификатором не существует, команда GRANT может создать такую запись. Отключить автоматическое создание учетной записи позволяет ключевое слово NO_AUTO_CREATE_USER в значении переменной sql_mode (напомню, что настройку режима взаимодействия с сервером MySQL мы обсуждали в подразделе «Вставка отдельных строк» главы 2).

• Привилегию ALTER рекомендуется предоставлять с осторожностью: путем переименования таблиц и столбцов пользователь может изменить настройки системы привилегий.

• Если при создании привилегии вы указываете параметр WITH GRANT OPTION, то пользователь получает возможность «делиться» не только созданной привилегией, но и другими  своими привилегиями в рамках данной области действия. Например, после выполнения команд

GRANT SELECT ON *.* TO \'marina\  

GRANT INSERT ON SalesDept.* TO \'marina\' WITH GRANT OPTION;  

GRANT DELETE ON SalesDept.Customers TO \'marina\  

пользователь marina может предоставлять другим пользователям следующие привилегии:

– привилегии SELECT, INSERT и GRANT OPTION на уровне базы данных SalesDept (Отдел продаж). Хотя сам пользователь marina имеет глобальную привилегию SELECT, его возможности делегирования привилегий ограничены базой данных SalesDept;

– привилегию DELETE на уровне таблицы Customers (Клиенты) базы данных SalesDept, так как область действия этой привилегии входит в область действия привилегии GRANT OPTION.

• Если вы предоставляете привилегию GRANT OPTION нескольким пользователям, эти пользователи могут «обменяться» привилегиями, то есть объединить свои наборы привилегий.

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


убрать рекламу






после выполнения команды USE <имя базы данных>, то есть после выбора какой-либо базы данных в качестве текущей. Глобальные привилегии начинают применяться при следующем подключении пользователя к серверу MySQL.

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

Отмена привилегий

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

REVOKE <Тип привилегии>  

[(<Список столбцов>)] ON <Область действия>  

FROM <Идентификатор пользователя>;  

Например,:

• REVOKE CREATE ON *.* FROM \'anna\'@\'localhost\

Команда отменяет глобальную привилегию пользователя \'anna\'@\'localhost\', разрешавшую создание баз данных и таблиц.

• REVOKE DROP ON SalesDept.* FROM \'anna\'@\'localhost\ Команда отменяет привилегию пользователя \'anna\'@\'localhost\' на удаление базы данных SalesDept (Отдел продаж) и таблиц в этой базе данных.

• REVOKE SELECT ON SalesDept.Products

FROM \'anna\'@\'localhost\

Команда отменяет привилегию пользователя \'anna\'@\'localhost\' на получение данных из таблицы Products (Товары) базы данных SalesDept.

• REVOKE UPDATE (price) ON SalesDept.Products

FROM \'anna\'@\'localhost\

Команда отменяет привилегию пользователя \'anna\'@\'localhost\' на изменение данных в столбце price (цена) таблицы Products (Товары).

Параметры команды REVOKE имеют тот же смысл, что и параметры команды GRANT. Аналогичны и правила вступления изменений в силу.

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

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

Просмотр привилегий

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

• Глобальные привилегии хранятся в таблице user (пользователь), которая уже знакома нам из предыдущего раздела. Каждому типу привилегии соответствует отдельный столбец, допускающий значения \'Y\' (операция разрешена) и \'N\' (операция не разрешена).

• Привилегии, областью действия которых является отдельная база данных, хранятся в таблице db (база данных). Первичный ключ в этой таблице образуют столбцы Host (хост), Db (база данных) и User (пользователь). Таким образом, каждая строка таблицы определяет привилегии одного пользователя по отношению к одной базе данных. Как и в таблице user, каждой привилегии соответствует отдельный столбец, возможными значениями которого являются \'Y\' и \'N\'.


...

Примечание

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

 

• Привилегии, относящиеся к отдельным таблицам, хранятся в таблице tables_ priv. Первичным ключом в этой таблице служат столбцы Host (Хост), Db (База данных), User (Пользователь) и Table_name (Имя таблицы). Таким образом, каждая строка таблицы tables_priv определяет привилегии доступа конкретного пользователя к конкретной таблице. Типы привилегий, которыми обладает пользователь, перечислены в столбце Table_priv (Привилегии доступа к таблице), имеющем тип данных SET. Кроме того, в таблице tables_priv имеется столбец Column_priv (Привилегии доступа к столбцу) с типом данных SET, значение которого указывает, что у пользователя имеются привилегии доступа к отдельным столбцам таблицы.

• Привилегии для отдельных столбцов хранятся в таблице columns_priv. Первичный ключ этой таблицы состоит из столбцов, идентифицирующих пользователя (Host и User), и столбцов, идентифицирующих столбец (Db, Table_name и Column_name). Типы привилегий, которыми обладает пользователь по отношению к столбцу, перечислены в столбце Column_priv (Привилегии доступа к столбцу) с типом данных SET.

Таблицы user, db, tables_priv и columns_priv вы можете использовать для получения информации о пользователях, обладающих привилегиями доступа к интересующему вас объекту базы данных. Если же требуется, наоборот, узнать, к каким объектам имеет доступ конкретный пользователь, выполните команду

SHOW GRANTS [FOR Идентификатор пользователя>];  















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

5.3. Резервирование базы данных

 Сделать закладку на этом месте книги

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

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

• периодическое полное  резервное копирование базы данных;

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

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

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

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

Двоичные журналы

Файл двоичного журнала накапливает историю изменений в базе данных за некоторый промежуток времени и позволяет в случае необходимости воспроизвести эти изменения.

Чтобы включить ведение двоичных журналов, запустим сервер MySQL с параметром –log-bin. Это можно сделать одним из следующих способов.

• Если вы запускаете сервер вручную из командной строки (об этом шла речь в подразделе «Запуск и остановка сервера MySQL из командной строки» главы 1), укажите параметр –log-bin в команде запуска сервера:

mysqld-nt –log-bin  





В процессе работы сервера в папке data корневой папки MySQL будут создаваться двоичные журналы – файлы с именами вида <Имя xocTa>-bin.xxxxxx, где xxxxxx – порядковый номер журнала. Очередной файл журнала создается в следующих случаях:

• при достижении предельного размера предыдущего файла;

• при запуске (перезапуске) сервера;

• при принудительном «сбросе» журналов.

«Сброс» журналов необходим при выполнении полного резервного копирования, чтобы изменения с момента резервирования отражались в новом файле (старые файлы журналов при этом становятся не нужны). Кроме того, принудительный «сброс» осуществляется перед промежуточным резервным копированием: сервер начнет протоколировать изменения в новом файле, а предыдущие файлы вы скопируете на резервный носитель.

Для «сброса» журналов выполните SQL-команду FLUSH LOGS; либо запустите утилиту mysqladmin с параметром flush-logs, выполнив в окне командной строки Windows команду

mysqladmin -u <Имя пользователя> -p flush-logs  



3. Дважды щелкните на названии задания. В окне настройки задания на вкладке Задание (рис. 5.12) в поле Выполнить введите команду







7. В окне настройки задания нажмите кнопку OK для сохранения задания.

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

Следующий этап промежуточного резервирования – копирование двоичных журналов на резервный носитель информации. Для решения этой задачи существует множество утилит, как платных, так и бесплатных, которые позволяют по расписанию создавать резервные копии файлов на любом носителе – CD, DVD, USB, удаленном FTP-сервере и др.

В частности, для копирования файлов на другой компьютер в локальной сети вы можете воспользоваться утилитой xcopy, входящей в состав Windows. Запуск этой утилиты по расписанию настраивается аналогично «сбросу» журналов. В качестве выполняемой команды введите

xcopy «<Корневая папка MySQL>/data»  «<Папка на резервном носителе>» /c/d/y  


...

Примечание

Параметр /c утилиты xcopy указывает, что возникающие при копировании ошибки следует игнорировать. Параметр /d означает, что файл в результирующей папке будет заменен файлом из исходной папки только в том случае, если исходный файл более новый. Параметр /y позволяет заменять файлы в результирующей папке, не запрашивая дополнительного подтверждения у пользователя.

 

Расписание для запуска утилиты xcopy целесообразно сделать смещенным на несколько минут относительно расписания «сброса» журналов.

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

Полное резервирование

Для полного резервного копирования баз данных предназначена утилита mysqldump. Чтобы запустить эту утилиту, откройте окно командной строки Windows и выполните команду

mysqldump –u <Имя пользователя> -p  

[Опциональные параметры]  

<Копируемые базы данных и таблицы>  

> <Путь и имя результирующего файла>  

После появления приглашения Enter password (Введите пароль) введите пароль пользователя.

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

• Для резервного копирования таблиц с типом InnoDB необходимо указать параметр –single-transaction. В процессе резервного копирования пользователи смогут продолжать работу с данными, в том числе вносить изменения, однако эти изменения будут незаметны для программы mysqldump. Таким образом, вы получите согласованную  копию баз данных, в которой не будет нарушений целостности данных.

• При резервном копировании таблиц с типом MyISAM необходимо запретить пользователям изменение данных во избежание их рассогласованности. Для этого необходимо указать параметр –lock-all-tables или –lock-tables. Параметр –lock-all-tables устанавливает блокировку для всех таблиц всех баз данных в течение всего времени резервного копирования. Параметр –lock-tables блокирует таблицы той базы данных, которая в данный момент копируется. В последнем случае уменьшается время недоступности каждой таблицы для пользователей, однако отсутствует гарантия непротиворечивости данных, находящихся в разных базах.

Параметры –single-transaction, –lock-all-tables и-lock-tables являются взаимоисключающими: в команде резервного копирования вы можете указать только один из них. Кроме того, поскольку наша стратегия резервного копирования использует двоичные журналы, необходимо указать параметр –flush-logs для «сброса» журналов.

Копируемые объекты вы можете задать одним из следующих способов:

• –all-databases

Необходимо копирование всех баз данных с сервера MySQL (кроме виртуальной базы данных INFORMATION_SCHEMA).

• –databases <Имя базы данных 1> <Имя базы данных 2>… Необходимо скопировать перечисленные базы данных.

• <Имя базы данных> <Имя таблицы 1> <Имя таблицы 2>… Необходимо скопировать перечисленные таблицы указанной базы данных.

Например, команда

mysqldump –u root –p –single-transaction –flush-logs  –databases SalesDept FinanceDept > “C:\data\full_backup.sql”  

выполняет резервное копирование баз данных SalesDept (Отдел продаж) и FinanceDept (Финансовый отдел) в файл full_backup.sql, находящийся в папке C: \data, а команда

mysqldump –u root –p –lock-tables –flush-logs  mysql user db tables_priv columns_priv > «C:\data\users.sql»  

выполняет резервное копирование таблиц user, db, tables_priv и columns_priv системной базы данных mysql в файл users.sql, находящийся в папке C: \data. Таблицы в базе данных mysql имеют тип MyISAM, поэтому при резервировании мы указали параметр –lock-tables.


...

Примечание

Открыв созданный файл с помощью программы Блокнот, вы увидите, что данные в нем представлены в виде SQL-команд CREATE DATABASE, CREATE TABLE и INSERT.

 

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

mysqldump –u <Имя пользователя> -p<Пароль пользователя> [Опциональные параметры]  

<Копируемые базы данных и таблицы>  

> <Путь и имя результирующего файла>  

О том, как создать подобное задание, говорилось в подразделе «Двоичные журналы». Обратите внимание, что в команде mysqldump пароль пользователя должен следовать сразу после ключа -p без пробела.  Учитывая риск разглашения пароля, рекомендуется выполнять резервное копирование не от имени пользователя root, а от имени специально зарегистрированного пользователя. Этот пользователь должен обладать следующими привилегиями:

• глобальной привилегией RELOAD;

• привилегией SELECT для всех копируемых объектов;

• в случае резервирования с параметром –lock-all-tables или –lock-tables – дополнительно привилегией LOCK_TABLES для всех баз данных, участвующих в копировании.

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

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

Восстановление данных

Согласно нашей стратегии резервного копирования в случае сбоя восстановление утраченных данных проводится в два этапа:

• вначале нужно восстановить базу данных из резервной копии;

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

Перед началом восстановления данных необходимо запустить сервер MySQL. Если при сбое были повреждены таблицы, управляющие доступом пользователей, при запуске сервера необходимо указать параметр –skip-grant-tables.

Чтобы восстановить базу данных из файла, содержащего полную резервную копию, откроем окно командной строки Windows и выполним команду

mysql –u root –p [<Имя базы данных>] < <Путь и имя файла>  

После появления приглашения Enter password (Введите пароль) введем пароль пользователя root.


...

Внимание!

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

 

Имя базы данных необходимо указывать в том случае, если файл содержит копии отдельных таблиц. Эта база данных должна уже существовать на сервере в момент восстановления данных. Если же база данных отсутствует, ее необходимо предварительно создать с помощью SQL-команды CREATE DATABASE (об этой команде вы узнали в разделе «Создание базы данных» главы 2).

Например, если резервная копия была создана с помощью команды

mysqldump –u root –p –single-transaction –flush-logs  –databases SalesDept FinanceDept > «C:\data\full_backup.sql»  

то восстановить базы данных SalesDept (Отдел продаж) и FinanceDept (Финансовый отдел) можно с помощью команды

mysql –u root –p < «C:\data\full_backup.sql»  

Если резервная копия была создана с помощью команды

mysqldump –u root –p –lock-tables –flush-logs  mysql user db tables_priv columns_priv > «C:\data\users.sql»  

то при восстановлении необходимо указать имя базы данных, в которую будут помещены воссозданные таблицы user, db, tables_priv и columns_priv:

mysql –u root –p mysql < «C:\data\users.sql»  


...

Совет

Поскольку файл с резервной копией содержит данные в виде SQL-команд, вы можете восстанавливать с его помощью отдельные таблицы по своему выбору, просто копируя SQL-команды CREATE TABLE и INSERT в какое-либо клиентское приложение и отправляя их на сервер.

 

Следующий шаг – восстановление изменений из двоичных журналов, которое выполняется с помощью команды

mysqlbinlog <Список журналов> | mysql –u root -p  

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

mysqlbinlog “C:\data\eugene_pc-bin.000117”  

“C:\data\eugene_pc-bin.000118”  

“C:\data\eugene_pc-bin.000119” | mysql –u root -p  

После появления приглашения Enter password (Введите пароль) введите пароль пользователя. Итак, теперь вы знаете, как организовать резервное копирование базы данных и как в случае потери данных восстановить их из резервных копий и двоичных журналов. Далее вы узнаете об устранении другого возможного последствия сбоев – повреждения таблиц.

5.4. Профилактическая проверка и восстановление таблиц

 Сделать закладку на этом месте книги

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

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

Для проверки таблиц выполните команду

CHECK TABLE <Список таблиц>;  

Команда CHECK TABLE отображает результат проверки таблиц. Например, чтобы получить информацию о состоянии таблиц db и user системной базы данных mysql, выполните команду

CHECK TABLE mysql.db, mysql.user;  



REPAIR TABLE <Имя таблицы>;  

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

REPAIR TABLE <Имя таблицы> EXTENDED;  

Если вновь не получилось исправить повреждения, выполните команду

REPAIR TABLE <Имя таблицы> USE_FRM;  











Нажмите кнопку Repair Tables. В окне отобразится результат восстановления таблиц (аналогично рис. 5.18). Итак, вы научились проверять и в случае повреждений восстанавливать таблицы с типом MyISAM. Рассмотрим теперь последнюю в этой главе тему – получение информации о событиях, происходящих на сервере MySQL, с помощью различных видов журналов.

5.5. Просмотр журналов работы

 Сделать закладку на этом месте книги

Журналы работы сервера MySQL по умолчанию находятся в папке data корневой папки MySQL. Здесь вы можете найти следующие виды журналов.

• Журнал ошибок.

Файл с именем <Имя хоста>.err. Содержит сведения об ошибках в работе сервера, а также о запусках и остановках сервера. Просмотреть файл вы можете с помощью любого текстового редактора, например Блокнот или WordPad.

• Двоичные журналы.

Файлы с именем <Имя хоста>-bin.xxxxxx, где xxxxxx – порядковый номер журнала. Содержат историю изменений данных в базе. Создаются в случае, если сервер запущен с параметром – log-bin (более подробно об этом рассказывалось в подразделе «Двоичные журналы»).

Для просмотра двоичных журналов откройте окно командной строки Windows и выполните команду

mysqlbinlog <Список журналов>  

или

mysqlbinlog <Список журналов> > <Имя файла>  



Вверху вкладки вы увидите полосу прокрутки, которая показывает, какой фрагмент журнала вы сейчас просматриваете. В поле Page Content (Содержимое страницы) в правой части вкладки отображаются собственно строки данного фрагмента журнала, а в поле Events of page (События на странице) представлен список событий, облегчающий навигацию по журналу. Итак, вы теперь знаете, как найти интересующую вас информацию в журналах работы сервера MySQL. Подведем краткие итоги этой главы.

5.6. Резюме

 Сделать закладку на этом месте книги

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

В последней главе этой книги вы найдете несколько советов по повышению производительности базы данных.

Глава 6 Оптимизация

 Сделать закладку на этом месте книги

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

6.1. Оптимизация структуры данных

 Сделать закладку на этом месте книги

Если «узким местом» вашей базы данных является одна или несколько таблиц, попробуем скорректировать структуру этих таблиц:

• выбрать наиболее подходящий тип таблицы;

• минимизировать объем данных в таблице;

• пересмотреть набор индексов в таблице;

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

Как было сказано в предыдущих главах, каждый тип таблиц имеет свои преимущества и недостатки. Если требуется обеспечить высокую производительность операций чтения данных (например, таблица будет использоваться главным образом для анализа содержащихся в ней данных или для генерации динамических веб-страниц), предпочтительным типом такой таблицы является MyISAM. Если же данные в таблице будут редактироваться множеством пользователей (это часто происходит в корпоративных базах данных), желательно присвоить таблице тип InnoDB. В разделе 6.4 «Проблемы, связанные с блокировками» мы рассмотрим особенности блокировки для каждого типа таблицы.

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

• Хранение мультимедийных данных (изображений, аудио– и видеозаписей) не в базе данных, а в файловой системе.

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

• Подбор типов столбцов с наименьшим размером.

Например, если значения в целочисленном столбце не могут превышать 10 000, целесообразно объявить его как SMALLINT, а не INT или MEDIUMINT. Определить диапазон возможных значений столбца вы можете с помощью запроса

SELECT <Список столбцов> FROM <Имя таблицы>  PROCEDURE ANALYSE();  

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

• Указание свойства NOT NULL для всех столбцов, для которых это возможно.

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

Исключением из правила минимизации объема данных является использование статического формата таблиц. Другими словами, если в таблице с типом MyISAM отсутствуют символьные столбцы, допускающие значения переменной длины (такие как VARCHAR, TEXT, BLOB и т. п.), то такая таблица по умолчанию сохраняется в статическом формате; если же в таблице есть столбцы с переменной длиной значений, то по умолчанию применяется динамический формат. Как правило, динамические таблицы занимают значительно меньше места, чем статические, однако статические таблицы работают намного быстрее.


...

Примечание

Вы также можете явно указать формат таблицы MyISAM с помощью опционального параметра ROW_FORMAT. Описание этого параметра приведено в конце данного раздела.

 

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


убрать рекламу






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

OPTIMIZE TABLE <Имя таблицы>;  

Следующий этап оптимизации – настройка набора индексов. Индекс для столбца таблицы позволяет многократно ускорить поиск с условием на значение этого столбца, сортировку (ORDER BY) и группировку (GROUP BY) по значениям столбца, вычисление максимального и минимального значения, а также объединение таблиц. Благодаря наличию индекса выполнение всех этих операций не потребует последовательного перебора всех строк таблицы.

Для максимально эффективного использования индексов необходимо учитывать следующие факты.

• Индекс замедляет добавление и обновление строк таблицы. Поэтому рекомендуется создавать только те индексы, которые будут использоваться в часто выполняемых запросах.

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

При создании индекса для группы столбцов важно правильно выбрать последовательность столбцов в индексе, так как в запросах может применяться часть  многостолбцового индекса, состоящая из нескольких начальных  столбцов. Например, если в таблицу Orders (Заказы) добавить индекс

INDEX (date,product_id,customer_id)  

то он ускорит выполнение запросов

SELECT * FROM Orders WHERE date=CURDATE();  

SELECT * FROM Orders  

WHERE date=CURDATE() AND product_id=3;  

но будет бесполезен при выполнении запросов

SELECT * FROM Orders WHERE product_id=3;  

SELECT * FROM Orders  

WHERE product_id=3 AND customer_id=533;  

• Более короткие индексы работают быстрее. Поэтому в качестве первичного ключа таблицы целесообразно использовать целочисленный столбец с наименьшим размером. При создании индекса для символьного столбца полезно ограничить длину индекса, включив в него только начальные подстроки значений (см. пункт «Ключевые столбцы и индексы»); количество индексируемых символов желательно подобрать так, чтобы минимизировать количество строк с одинаковой начальной подстрокой.

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

• AVG_ROW_LENGTH <Размер в байтах>, MAX ROWS <Количество строк>.

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

• DELAY_KEY_WRITE 1.

Задание этого параметра для таблиц MyISAM включает режим отложенной записи на диск буфера индексов. Этот режим позволяет ускорить обновление индексов при добавлении и изменении записей благодаря более редкому обращению к диску.

• PACK_KEYS <0, 1 или DEFAULT>.

Данный параметр для таблиц MyISAM определяет режим сжатия индексов. Значение 1 указывает, что сжатие будет использоваться как для символьных, так и для числовых индексов. Это ускоряет поиск по таблице, но замедляет обновление индексов. Сжатие числовых индексов дает наибольший эффект в случае большого количества повторяющихся чисел. Значение DEFAULT указывает, что уплотняться будут только символьные индексы, а значение 0 полностью отключает сжатие.

• ROW_FORMAT <Формат>

Данный параметр определяет формат таблицы. Таблица с типом InnoDB может иметь формат COMPACT или REDUNDANT. Формат COMPACT используется по умолчанию и является оптимальным. Для таблицы с типом MyISAM вы можете указать значение FIXED (статический формат) или DYNAMIC (динамический формат). Обратите внимание, что статический формат нельзя установить для таблицы, содержащей столбцы с типом TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB и LONGTEXT: если вы укажете для такой таблицы статический формат, он автоматически изменится на динамический.


...

Примечание

Проверить, какие форматы были фактически присвоены таблицам, вы можете с помощью команды SHOW TABLE STATUS; Эта команда выводит информацию обо всех таблицах в текущей базе данных. В столбце Row_format вы увидите текущий формат таблицы.

 

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

6.2. Оптимизация запросов

 Сделать закладку на этом месте книги

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

EXPLAIN <Текст запроса>;  

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

EXPLAIN SELECT name,address,product_id,qty  

FROM Customers, Orders  

WHERE Customers.id=customer_id AND date=\'20007-12-12\  



ANALYZE TABLE <Имя таблицы>;  

2. Повторно выполните команду EXPLAIN. Если и после обновления статистики индекс не начал использоваться, добавьте в текст запроса после имени таблицы параметр FORCE INDEX (<Имя индекса>). Сравните время выполнения запроса с параметром FORCE INDEX и без него и выберите оптимальный вариант.

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

• Исключите получение лишней информации из базы данных. Результат запроса должен содержать только те данные, которые действительно необходимы. Например, если вы отображаете на веб-странице не более 20 товаров, не нужно получать из таблицы Products (Товары) все  данные. Вместо этого используйте запросы вида

SELECT <Список столбцов> FROM <Список таблиц>  

[WHERE <Условие отбора>]  

 

LIMIT <Количество строк> OFFSET <Сдвиг>;  

Так, для получения первой «порции» из 20 товаров выполните запрос

SELECT * FROM Products LIMIT 20 OFFSET 0;  

Следующих 20 товаров —

SELECT * FROM Products LIMIT 20 OFFSET 20;  

Затем

SELECT * FROM Products LIMIT 20 OFFSET 40;  

и т. д.

• Максимально упростите систему привилегий доступа. Чем сложнее система привилегий, тем больше времени занимает проверка прав доступа при выполнении запросов (а также других SQL-команд). Хорошим решением является разграничение доступа на уровне баз данных и отказ от присвоения привилегий доступа к отдельным таблицам и столбцам. В этом случае контроль действий пользователей не требует обращения к таблицам tables_priv и columns_ priv (см. подраздел «Просмотр привилегий»).

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

SELECT BENCHMARK(<Количество повторений>,<Выражение>);  

Функция BENCHMARK() всегда возвращает значение 0, однако в сообщении о результате выполнения команды указывается время ее выполнения, благодаря чему вы можете оценить время вычисления выражения. Например, если ваш запрос включает вычисление синуса для каждой строки таблицы, выполните команду

SELECT BENCHMARK(10000000,SIN(1));  

При использовании процессора с тактовой частотой 1,6 ГГц выполнение этой команды займет приблизительно 1 с. Таким образом, программа MySQL способна производить около 10 млн вычислений синуса в секунду, а значит, функция SIN() не оказывает существенного влияния на скорость запроса. Итак, мы рассмотрели способы оптимизации таблиц и запросов. В следующем разделе вы узнаете о том, как увеличить быстродействие сервера путем настройки системных переменных.

6.3. Параметры работы сервера

 Сделать закладку на этом месте книги

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

Узнать текущие значения серверных переменных вы можете с помощью уже знакомой вам команды

SHOW VARIABLES;  

Для изменения значения переменной можно использовать команду

SET GLOBAL <Имя переменной>=<Значение>;  

однако установленное таким образом значение будет действовать только до момента перезапуска сервера MySQL. Поэтому лучше указать нужные значения переменных непосредственно при запуске сервера MySQL. • Если вы запускаете сервер вручную из командной строки (об этом говорилось в подразделе «Запуск и остановка сервера MySQL из командной строки» главы 1), укажите в команде запуска сервера параметр – <Имя переменной> = <Значение>, например

mysqld-nt –table-cache=256  

• Если сервер MySQL был сконфигурирован как сервис Windows и запускается или автоматически, или с помощью панели управления, или с помощью MySQL Administrator (см. подразделы «Запуск и остановка сервера MySQL с помощью MySQL Administrators «Запуск и остановка сервера MySQL с панели управления» главы 1), откройте конфигурационный файл my.ini, находящийся в папке, где установлена программа MySQL, и добавьте параметр <Имя переменной> = <Значение> в раздел [mysqld] (см. рис. 5.9). Сохраните файл my.ini. Новые значения переменных вступят в действие после перезапуска сервера.


...

Примечание

В корневой папке MySQL вы найдете примеры конфигурационных файлов с различными вариантами настроек системных переменных: my-small.ini, my-medium.ini, my-large.ini, my-huge-ini и my-innodb-heavy-4G.ini.

 

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

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

Таблица 6.2.

Параметры работы сервера







6.4. Проблемы, связанные с блокировками

 Сделать закладку на этом месте книги

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

В главах 1 и 2 было отмечено, что в таблицах с типом InnoDB блокировка выполняется на уровне отдельных строк. Для таблиц MyISAM построчная блокировка не поддерживается, и при необходимости таблица блокируется целиком. Преимуществом построчной блокировки является возможность параллельного редактирования данных множеством пользователей. Однако табличная блокировка выполняется быстрее и требует меньшего количества оперативной памяти. Табличные блокировки оказываются предпочтительными в следующих случаях:

• таблица используется главным образом для чтения данных;

• основными операциями в таблице являются запросы и добавление строк, а изменение и удаление данных происходит редко; в этом случае можно выполнять чтение и запись параллельно (об этом будет подробно рассказано ниже);

• в таблице часто выполняются запросы, требующие просмотра всей таблицы (при этом построчные блокировки будут неэффективны).

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

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

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

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

LOCK TABLES <Основная таблица> WRITE,  

<Вспомогательная таблица> WRITE;  

INSERT INTO <Основная таблица>  

(SELECT * FROM <Вспомогательная таблица>);  

DELETE FROM <Вспомогательная таблица>);  

UNLOCK TABLES;  

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

• Другое решение состоит в присвоении значения 2 системной переменной concurrent_insert. Такая настройка позволяет выполнять запросы и добавление строк одновременно: если таблица используется для чтения, новые строки записываются в конец таблицы. При этом пустые блоки, образующиеся при удалении строк, не заполняются новыми строками, так что таблицу полезно периодически дефрагментировать с помощью команды OPTIMIZE TABLE, о которой говорилось в разделе 6.1 «Оптимизация структуры данных».

• Уменьшите значение переменной max_write_lock_count, чтобы разрешить чередование блокировок записи и чтения. Данная переменная определяет количество блокировок записи, после применения которых допускается выполнение блокировок чтения, несмотря на наличие ожидающих своей очереди блокировок записи (значение по умолчанию – 102 4).

• Снизьте приоритет всех  операций записи, установив значение ON переменной low-priority-updates. При таком значении к таблице в первую очередь будут применяться блокировки чтения, и только в их отсутствие – блокировки записи.

• Снизьте приоритет отдельных операций записи, включив в SQL-команду параметр LOW_PRIORITY. Например, выполнение команды

UPDATE LOW_PRIORITY Customers  SET phone=\'444-25-27\' WHERE id=536;  

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

• Вставку строк можно выполнять в отложенном режиме, задав в команде INSERT и REPLACE параметр DELAYED. При этом клиентское приложение сразу же получает сообщение о результате выполнения операции, однако добавляемая строка записывается не непосредственно в таблицу, а в очередь отложенных добавлений (общую для всех клиентских приложений). Как только таблица освобождается от предыдущей блокировки, в нее единой группой вносятся строки, накопленные в очереди. Если очередь слишком велика, то операция вставки строк в таблицу периодически прерывается для выполнения ожидающих своей очереди запросов. Таким образом, отложенный режим добавления строк замедляет выполнение запросов в меньшей степени, чем обычный режим.

• Если необходимо сочетать массовое удаление строк и выполнение запросов, рекомендуется удалять строки поэтапно, используя параметр LIMIT команды DELETE (см. раздел 2.6 «Изменение данных»).

• Повысим приоритет отдельных запросов, включив в текст запроса параметр HIGH_PRIORITY.

Например, запрос

SELECT HIGH_PRIORITY * FROM Customers WHERE rating>1000;  

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

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

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

6.5. Резюме

 Сделать закладку на этом месте книги

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


убрать рекламу












На главную » Гольцман Виктор » MySQL 5.0. Библиотека программиста.

Close