Вы находитесь на странице: 1из 77

1

https://metanit.com/sql/mysql/

Руководство по MySQL
Последнее обновление: 26.05.2018

1. Глава 1. Введение в MySQL


1. Что такое MySQL. Установка сервера
2. Консольный клиент MySQL Command Line Client
3. Графический клиент MySQL Workbench
2. Глава 2. Определение структуры данных
1. Создание и удаление базы данных
2. Создание и удаление таблиц
3. Типы данных MySQL
4. Атрибуты столбцов и таблиц
5. Внешние ключи FOREIGN KEY
6. Изменение таблиц и столбцов
3. Глава 3. Основные операции с данными
1. Добавление данных. Команда INSERT
2. Выборка данных. Команда SELECT
3. Фильтрация данных. Оператор WHERE
4. Обновление данных. Команда UPDATE
5. Удаление данных. Команда DELETE
4. Глава 4. Запросы
1. Выборка уникальных значений. Оператор DISTINCT
2. Операторы фильтрации
3. Сортировка. ORDER BY
4. Получение диапазона строк. Оператор LIMIT
5. Агрегатные функции
6. Группировка
7. Подзапросы
8. Подзапросы в основных командах SQL
9. Оператор EXISTS
5. Глава 5. Соединение таблиц
1. Неявное соединение таблиц
2. Inner Join
3. Outer Join
4. UNION
6. Глава 6. Встроенные функции
1. Функции для работы со строками
2. Функции для работы с числами
3. Функции для работы с датами и временем
4. Функции CASE, IF, IFNULL, COALESCE

Глава 1. Введение в MySQL 1.1


Что такое MySQL. Установка сервера
Последнее обновление: 04.05.2018
2
MySQL представляет систему управления реляционными базами данных (СУБД). На
сегодняшний день это одна из самых популярных систем управления базами данных.

Изначальным разработчиком данной СУБД была шведская компания MySQL AB. В 1995
году она выпустила первый релиз MySQL. В 2008 году компания MySQL AB была куплена
компанией Sun Microsystems, а в 2010 году уже компания Oracle поглотила Sun и тем самым
приобрела права на торговую марку MySQL. Поэтому MySQL на сегодняшней день
развивается под эгидой Oracle.

Текущей актуальной версией СУДБ является версия 8.0, которая вышла в январе 2018 года.

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


в том числе наиболее популярные версии Linux, Windows, MacOS.

Официальный сайт проекта: https://www.mysql.com/.

Установка MySQL

Для установки MySQL загрузим дистрибутив по адресу


http://dev.mysql.com/downloads/mysql/ и выберем нужную версию.

После выбора версии нажмем на кнопку "Go to Download Page", и нас перенаправит на
страницу загрузки дистрибутива. Здесь можно выбрать либо онлайн-загрузчик, либо полный
пакет инсталлятора. Можно выбрать любой:
3
После загрузки запустим инсталлятор. Вначале нам отобразится окно с лицензионным
соглашением, которое нужно принять:

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


Выберем тип Full и нажмем на кнопку Next:
Далее на следующем этапе может отобразиться следующее окно, если какие-то
дополнительные компоненты отсутствуют в системе:

В данном случае программа установки показывает, что у меня не установлен Python 2.7.
Поскольку эти компоненты не важны, нажимаем Next.
5

Затем на этапе установки инсталлятор отобразит весь список устанавливаемых компонентов.


У меня он выглядит так:
Чтобы выполнить установку всех компонентов, нажмем кнопку Execute. После того, как все
компоненты будут установлены, нажмем кнопку Next.

Далее надо будет указать тип сервера. Выберем настройку по умолчанию Standalone MySQL
Server / Classic MySQL Replication
6
Далее будет предложено установить ряд конфигурационных настроек сервера MySQL.
Оставим настройки соединения и порта по умолчанию:

На следующем шаге будет предложено установить метод аутентификации. Оставим


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

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


сервер будет запускаться в качестве службы Windows при запуске операционной
системы:
8
Следующее окно позволяет настроить дополнительные плагины и расширения. Начиная с
версии 5.7 в MySQL доступен X Protocol, который представляет новый способ
взаимодействия с хранилищем данных. Эту опцию необязательно отмечать. В данном случае
я ее отмечу:

И на следующем экране необходимо применить все ранее установленные конфигурационные


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

НазадСодержаниеВперед

1.2 Консольный клиент MySQL Command Line


Client Последнее обновление: 04.05.2018
При установке сервера MySQL также устанавливается консольный клиент для работы с
базами данных. Например, в Windows в меню Пуск можно найти программу MySQL 8.0
Command Line Client. Это и есть собственно консольный клиент:

Причем клиент устанавливается сразу в двух вариантах - с поддержкой Unicode и без.

Запустим MySQL 8.0 Command Line Client - Unicode. Вначале нам отобразится предложение
ввести пароль:

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

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

Теперь создадим базу данных с помощью следующей команды языка

SQL: create database test;

Для создания базы данных применяется команда create database, после которой указывается
название БД. То есть в данном случае база данных будет называться "test".

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


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

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


create table users (id integer auto_increment primary key, name varchar(30), age
integer);

Данная команда создает таблицу users, в которой будет три столбца - id, name и age. id будет
хранить уникальный числовой идентификатор пользователя и будет автоматически
генерироваться базой данных, name будет хранить имя пользователя, а age - его возраст.
11
После этого мы можем добавлять и получать данные из выше созданной таблицы. Вначале
добавим в таблицу одну строку с помощью следующей команды:

insert into users (name, age) values ('Tom', 34);

И в конце получим добавленные данные:


select * from users;

Таким образом в общих чертах мы можем работать с консольным клиентом MySQL


Command Line Client.

НазадСодержаниеВперед

1.3 Графический клиент MySQL Workbench


Последнее обновление: 04.05.2018

Для упрощения работы с сервером MySQL в базовый комплект установки входит такой
инструмент как MySQL Workbench. Он представляет графический клиент для работы с
сервером, через который мы в удобном виде можем создавать, удалять, изменять базы
данных и управлять ими. Так, на Windows после установки в меню Пуск мы можем найти
значок программы и запустить ее:
12

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

Здесь надо ввести пароль, который был установлен для пользователя root при установке
MySQL.

После успешного логина нам откроется содержимое сервера:


13
В частности, в левой части в окне SCHEMAS можно увидеть доступные базы данных.
Теперь посмотрим, как мы можем выполнять в этой программе запросы к БД. Вначале
создадим саму БД. Для этого нажмем над списком баз данных на значок "SQL" с
плюсом:

После этого в центральной части программы откроется окно для ввода скрипта SQL. Введем
в него следующую команду:

1CREATE DATABASE usersdb;

Данная команда создает базу данных usersdb.


14

Для выполнения скрипта в панели инструментов нажмем на значок молнии:

После этого внизу программы в поле вывода в случае удачного выполнения мы увидим
зеленый маркер и отчет о выполнении.

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

1
USE usersdb;
2
CREATE TABLE users (
3
id INTEGER AUTO_INCREMENT PRIMARY KEY, 4
firstname VARCHAR(30),
5
age INTEGER
6
);
7
INSERT INTO users (firstname, age) VALUES ('Tom',34);

Все команды отделяются друг от друга точкой с запятой. Первая команда - USE
устанавливает в качестве используемой базу данных usersdb, которая была создана выше.
Вторая команда - CREATE TABLE создает в БД таблицу users, в которой будет три столбца: id,
firstname и age. Третья команда - INSERT INTO добавляет в таблицу users одну строку. Для
выполнения этих команд также нажмем на значок молнии.
15

И в конце получим все данные из таблицы users с помощью следующих команд:


1
USE usersdb;
2
SELECT * FROM users;
Таким

образом, мы можем осуществлять запросы к БД в прогамме MySQL Workbench CE.


НазадСодержаниеВперед

Глава2. Определение структуры


данных 2.1 Создание и удаление базы данных
Последнее обновление: 04.05.2018

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


16

Для создания базы данных используется команда CREATE DATABASE. Она имеет
следующий синтаксис:

1CREATE DATABASE [IF NOT EXISTS] имя_базы_даных;

В конце команды указывается имя базы данных.

Первая форма CREATE DATABASE имя_базы_даных пытается создать базу данных, но если
такая база данных уже существует, то операция возвратит ошибку.

Вторая форма CREATE DATABASE IF NOT EXISTS имя_базы_даных пытается создать базу
данных, если на сервере отсутствует БД с таким именем.

Например, в MySQL Workbench CE (или в MySQL Command Line Client) выполним


следующую команду:

1CREATE DATABASE productsdb;

Она создаст на сервере бд productsdb.


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

1USE productsdb;

Удаление базы данных

Для удаления базы данных применяется команда DROP DATABASE, которая имеет
следующий синтаксис:

1DROP DATABASE [IF EXISTS] имя_базы_даных;

Первая форма DROP DATABASE имя_базы_даных пытается удалить базу данных, но если такая
база данных отсутствует на сервере, то операция возвратит ошибку.
17

Вторая форма DROP DATABASE IF EXISTS имя_базы_даных пытается удалить базу данных,
если на сервере имеется БД с таким именем.

Например, удалим выше созданную базу данных productsdb:

1DROP DATABASE productsdb;

НазадСодержаниеВперед

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


Последнее обновление: 04.05.2018

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

Для создания таблиц используется команда CREATE TABLE. Эта команды применяет ряд
операторов, которые определяют столбцы таблицы и их атрибуты. Общий формальный
синтаксис команды CREATE TABLE:
CREATE TABLE название_таблицы
(название_столбца1 тип_данных атрибуты_столбца1,
название_столбца2 тип_данных атрибуты_столбца2,
................................................
название_столбцаN тип_данных атрибуты_столбцаN,
атрибуты_уровня_таблицы
)

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

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

скрипт: CREATE DATABASE productsdb;

USE productsdb;

CREATE TABLE Customers


(
Id INT,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20)
);

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

Далее собственно идет создание таблицы, которая называется Customers. Она определяет
четыре столбца: Id, Age, FirstName, LastName. Первые два столбца представляют
идентификатор клиента и его возраст и имеют тип INT, то есть будут хранить числовые
значения. Следующие столбцы представляют имя и фамилию клиента и имеют тип
VARCHAR(20), то есть представляют строку длиной не более 20 символов. В данном случае
18

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

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

Переименование таблиц

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


использовать команду RENAME TABLE, которая имеет следующий синтаксис:

RENAME TABLE старое_название TO новое_название;

Например, переименуем таблицу Customers в Clients:


RENAME TABLE Customers TO Clients;

Полное удаление данных

Для полного удаления данных, очистки таблицы применяется команда TRUNCATE TABLE.
Например, очистим таблицу Clients:

TRUNCATE TABLE Clients;

Удаление таблиц

Для удаления таблицы из БД применяется команда DROP TABLE, после которой


указывается название удаляемой таблицы. Например, удалим таблицу Clients:
DROP TABLE Clients;

НазадСодержаниеВперед

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


Последнее обновление: 25.05.2018

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

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

Символьные типы

• CHAR: представляет стоку фиксированной длины.

Длина хранимой строки указывается в скобках, например, CHAR(10) - строка из десяти


символов. И если в таблицу в данный столбец сохраняется строка из 6 символов (то
есть меньше установленной длины в 10 символов), то строка дополняется 4
пробелами и в итоге все равно будет занимать 10 символов

• VARCHAR: представляет стоку переменной длины.

Длина хранимой строки также указывается в скобках, например, VARCHAR(10). Однако


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

Начиная с MySQL 5.6 типы CHAR и VARCHAR по умолчанию используют кодировку UTF
8, которая позволяет использовать до 3 байт для хранения символа в зависимости от языка
( для многих европейских языков по 1 байту на символ, для ряда восточно-европейских и
ближневосточных - 2 байта, а для китайского, японского, корейского - по 3 байта на символ).

Ряд дополнительных типов данных представляют текст неопределенной длины:

• TINYTEXT: представляет текст длиной до 255 байт.


• TEXT: представляет текст длиной до 65 КБ.
• MEDIUMTEXT: представляет текст длиной до 16 МБ
• LARGETEXT: представляет текст длиной до 4 ГБ
Числовые типы

• TINYINT: представляет целые числа от -127 до 128, занимает 1 байт • BOOL: фактически
не представляет отдельный тип, а является лишь псевдонимом для типа TINYINT(1) и
может хранить два значения 0 и 1. Однако данный тип может также в качестве значения
принимать встроенные константы TRUE (представляет число 1) и FALSE (предоставляет
число 0).

Также имеет псевдоним BOOLEAN.

• TINYINT UNSIGNED: представляет целые числа от 0 до 255, занимает 1 байт •


SMALLINT: представляет целые числа от -32768 до 32767, занимает 2 байтa •
SMALLINT UNSIGNED: представляет целые числа от 0 до 65535, занимает 2 байтa •
MEDIUMINT: представляет целые числа от -8388608 до 8388607, занимает 3 байта •
MEDIUMINT UNSIGNED: представляет целые числа от 0 до 16777215, занимает 3
байта
• INT: представляет целые числа от -2147483648 до 2147483647, занимает 4 байта • INT
UNSIGNED: представляет целые числа от 0 до 4294967295, занимает 4 байта • BIGINT:
представляет целые числа от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807,
занимает 8 байт
• BIGINT UNSIGNED: представляет целые числа от 0 до 18 446 744 073 709 551 615,
занимает 8 байт
• DECIMAL: хранит числа с фиксированной точностью. Данный тип может принимать
два параметра precision и scale: DECIMAL(precision, scale).

Параметр precision представляет максимальное количество цифр, которые может


хранить число. Это значение должно находиться в диапазоне от 1 до 65.
20

Параметр scale представляет максимальное количество цифр, которые может


содержать число после запятой. Это значение должно находиться в диапазоне от 0 до
значения параметра precision. По умолчанию оно равно 0.

Например, в определении следующего столбца:

1salary DECIMAL(5,2)

Число 5 - precision, а число 2 - scale, поэтому данный столбец может хранить


значения из диапазона от -999.99 до 999.99.

Размер данных в байтах для DECIMAL зависит от хранимого значения.

Данный тип также имеет псевдонимы NUMERIC, DEC, FIXED.

• FLOAT: хранит дробные числа с плавающей точкой одинарной точности от -3.4028 *


1038 до 3.4028 * 1038, занимает 4 байта

Может принимать форму FLOAT(M,D), где M - общее количество цифр, а D - количество


цифр после запятой

• DOUBLE: хранит дробные числа с плавающей точкой двойной точности от -1.7976 *


10308 до 1.7976 * 10308, занимает 8 байт. Также может принимать форму DOUBLE(M,D),
где M - общее количество цифр, а D - количество цифр после запятой.

Данный тип также имеет псевдонимы REAL и DOUBLE PRECISION, которые можно
использовать вместо DOUBLE.

Типы для работы с датой и временем

• DATE: хранит даты с 1 января 1000 года до 31 декабря 9999 года (c "1000-01-01" до
"9999-12-31"). По умолчанию для хранения используется формат yyyy-mm-dd.
Занимает 3 байта.
• TIME: хранит время от -838:59:59 до 838:59:59. По умолчанию для хранения времени
применяется формат "hh:mm:ss". Занимает 3 байта.
• DATETIME: объединяет время и дату, диапазон дат и времени - с 1 января 1000 года
по 31 декабря 9999 года (с "1000-01-01 00:00:00" до "9999-12-31 23:59:59"). Для
хранения по умолчанию используется формат "yyyy-mm-dd hh:mm:ss". Занимает 8
байт
• TIMESTAMP: также хранит дату и время, но в другом диапазоне: от "1970-01-01
00:00:01" UTC до "2038-01-19 03:14:07" UTC. Занимает 4 байта
• YEAR: хранит год в виде 4 цифр. Диапазон доступных значений от 1901 до 2155.
Занимает 1 байт.

Тип Date может принимать даты в различных форматах, однако непосредственно для
хранения в самой бд даты приводятся к формату "yyyy-mm-dd". Некоторые из принимаемых
форматов:

• yyyy-mm-dd - 2018-05-25
• yyyy-m-dd - 2018-5-25
• yy-m-dd - 18-05-25
21

В таком формате двузначные числа от 00 до 69 воспринимаются как даты в диапазоне


2000-2069. А числа от 70 до 99 как диапазон чисел 1970 - 1999.

• yyyymmdd - 20180525
• yyyy.mm.dd - 2018.05.25

Для времени тип Time использует 24-часовой формат. Он может принимать время в
различных форматах:

• hh:mi - 3:21 (хранимое значение 03:21:00)


• hh:mi:ss - 19:21:34
• hhmiss - 192134

Примеры значений для типов DATETIME и TIMESTAMP:

• 2018-05-25 19:21:34
• 2018-05-25 (хранимое значение 2018-05-25 00:00:00)

Составные типы

• ENUM: хранит одно значение из списка допустимых значений. Занимает 1-2 байта •
SET: может хранить несколько значений (до 64 значений) из некоторого списка
допустимых значений. Занимает 1-8 байт.

Бинарные типы

• TINYBLOB: хранит бинарные данные в виде строки длиной до 255 байт. •


BLOB: хранит бинарные данные в виде строки длиной до 65 КБ.
• MEDIUMBLOB: хранит бинарные данные в виде строки длиной до 16 МБ •
LARGEBLOB: хранит бинарные данные в виде строки длиной до 4 ГБ
НазадСодержаниеВперед

2.4 Атрибуты столбцов и таблиц


Последнее обновление: 11.05.2018

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


мы можем использовать.

PRIMARY KEY

Атрибут PRIMARY KEY задает первичный ключ таблицы.


USE productsdb;

CREATE TABLE Customers


(
Id INT PRIMARY KEY,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20)
);
22

Первичный ключ уникально идентифицирует строку в таблице. В качестве первичного


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

Установка первичного ключа на уровне таблицы:


USE productsdb;
CREATE TABLE Customers
(
Id INT,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20),
PRIMARY KEY(Id)
);

Первичный ключ может быть составным. Такой ключ использовать сразу несколько
столбцов, чтобы уникально идентифицировать строку в таблице. Например:
CREATE TABLE OrderLines
(
OrderId INT,
ProductId INT,
Quantity INT,
Price MONEY,
PRIMARY KEY(OrderId, ProductId)
)

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

AUTO_INCREMENT

Атрибут AUTO_INCREMENT позволяет указать, что значение столбца будет автоматически


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

CREATE TABLE Customers


(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20)
);

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

UNIQUE

Атрибут UNIQUE указывает, что столбец может хранить только уникальные значения.
CREATE TABLE Customers
(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20),
Phone VARCHAR(13) UNIQUE
);
23

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

Также мы можем определить этот атрибут на уровне таблицы:


CREATE TABLE Customers
(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20),
LastName VARCHAR(20),
Email VARCHAR(30),
Phone VARCHAR(20),
UNIQUE(Email, Phone)
);

NULL и NOT NULL

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

CREATE TABLE Customers


(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Email VARCHAR(30) NULL,
Phone VARCHAR(20) NULL
);

В данном случае столбец Age по умолчанию будет иметь атрибут NULL.

DEFAULT

Атрибут DEFAULT определяет значение по умолчанию для столбца. Если при добавлении
данных для столбца не будет предусмотрено значение, то для него будет использоваться
значение по умолчанию.
CREATE TABLE Customers
(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT DEFAULT 18,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Email VARCHAR(30) NOT NULL UNIQUE,
Phone VARCHAR(20) NOT NULL UNIQUE
);

Здесь столбец Age в качестве значения по умолчанию имеет число

18. CHECK

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

соответствовать столбец или несколько столбцов. Например, возраст клиентов не может


быть меньше 0 или больше 100:

CREATE TABLE Customers


(
Id INT AUTO_INCREMENT,
Age INT DEFAULT 18 CHECK(Age >0 AND Age < 100),
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Email VARCHAR(30) CHECK(Email !=''),
Phone VARCHAR(20) CHECK(Phone !='')
);

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

Для соединения условий используется ключевое слово AND. Условия можно задать в виде
операций сравнения больше (>), меньше (<), не равно (!=).

Также CHECK можно использовать на уровне таблицы:


CREATE TABLE Customers
(
Id INT AUTO_INCREMENT,
Age INT DEFAULT 18,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Email VARCHAR(30),
Phone VARCHAR(20),
CHECK((Age >0 AND Age<100) AND (Email !='') AND (Phone !='')) );

Оператор CONSTRAINT. Установка имени ограничений

С помощью ключевого слова CONSTRAINT можно задать имя для ограничений. Они
указываются после ключевого слова CONSTRAINT перед атрибутами на уровне таблицы:
CREATE TABLE Customers
(
Id INT AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Email VARCHAR(30),
Phone VARCHAR(20) NOT NULL,
CONSTRAINT customers_pk PRIMARY KEY(Id),
CONSTRAINT customer_phone_uq UNIQUE(Phone),
CONSTRAINT customer_age_chk CHECK(Age >0 AND Age<100)
);

В данном случае ограничение для PRIMARY KEY называется customers_pk, для UNIQUE -
customer_phone_uq, а для CHECK - customer_age_chk. Смысл установки имен ограничений
заключается в том, что впоследствии через эти имена мы сможем управлять ограничениями -
удалять или изменять их.

Установить имя можно для ограничений PRIMARY KEY, CHECK, UNIQUE, а также
FOREIGN KEY, который рассматривается далее.

НазадСодержаниеВперед

2.5 Внешние ключи FOREIGN KEY


25

Последнее обновление: 11.05.2018

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


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

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

[CONSTRAINT] REFERENCES главная_таблица (столбец_главной_таблицы)


[ON DELETE действие]
[ON UPDATE действие]

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

Общий синтаксис установки внешнего ключа на уровне таблицы:


[CONSTRAINT имя_ограничения]
FOREIGN KEY (стобец1, столбец2, ... столбецN)
REFERENCES главная_таблица (столбец_главной_таблицы1, столбец_главной_таблицы2, ...
столбец_главной_таблицыN)
[ON DELETE действие]
[ON UPDATE действие]

Например, определим две таблицы и свяжем их посредством внешнего ключа:


CREATE TABLE Customers
(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Phone VARCHAR(20) NOT NULL UNIQUE
);

CREATE TABLE Orders


(
Id INT PRIMARY KEY AUTO_INCREMENT,
CustomerId INT REFERENCES Customers (Id),
CreatedAt Date
);

В данном случае определены таблицы Customers и Orders. Customers является главной и


представляет клиента. Orders является зависимой и представляет заказ, сделанный клиентом.
Таблица Orders через столбец CustomerId связана с таблицей Customers и ее столбцом Id. То
есть столбец CustomerId является внешним ключом, который указывает на столбец Id из
таблицы Customers.

Мы также могли бы определить внешний ключ на уровне таблицы:


CREATE TABLE Orders
(
Id INT PRIMARY KEY AUTO_INCREMENT,
CustomerId INT,
CreatedAt Date,
FOREIGN KEY (CustomerId) REFERENCES Customers (Id)
26

);

С помощью оператора CONSTRAINT можно задать имя для ограничения внешнего ключа:
CREATE TABLE Orders
(
Id INT PRIMARY KEY AUTO_INCREMENT,
CustomerId INT,
CreatedAt Date,
CONSTRAINT orders_custonmers_fk
FOREIGN KEY (CustomerId) REFERENCES Customers (Id)
);

ON DELETE и ON UPDATE

С помощью выражений ON DELETE и ON UPDATE можно установить действия, которые


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

• CASCADE: автоматически удаляет или изменяет строки из зависимой таблицы при


удалении или изменении связанных строк в главной таблице.
• SET NULL: при удалении или обновлении связанной строки из главной таблицы
устанавливает для столбца внешнего ключа значение NULL. (В этом случае столбец
внешнего ключа должен поддерживать установку NULL)
• RESTRICT: отклоняет удаление или изменение строк в главной таблице при наличии
связанных строк в зависимой таблице.
• NO ACTION: то же самое, что и RESTRICT.
• SET DEFAULT: при удалении связанной строки из главной таблицы устанавливает для
столбца внешнего ключа значение по умолчанию, которое задается с помощью
атрибуты DEFAULT. Несмотря на то, что данная опция в принципе доступна, однако
движок InnoDB не поддерживает данное выражение.

Каскадное удаление

Каскадное удаление позволяет при удалении строки из главной таблицы автоматически


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

CREATE TABLE Orders


(
Id INT PRIMARY KEY AUTO_INCREMENT,
CustomerId INT,
CreatedAt Date,
FOREIGN KEY (CustomerId) REFERENCES Customers (Id) ON DELETE CASCADE );

Подобным образом работает и выражение ON UPDATE CASCADE. При изменении значения


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

Установка NULL

При установке для внешнего ключа опции SET NULL необходимо, чтобы столбец внешнего
ключа допускал значение NULL:

CREATE TABLE Orders


(
27

Id INT PRIMARY KEY AUTO_INCREMENT,


CustomerId INT,
CreatedAt Date,
FOREIGN KEY (CustomerId) REFERENCES Customers (Id) ON DELETE SET NULL );

НазадСодержаниеВперед

2.6 Изменение таблиц и столбцов


Последнее обновление: 11.05.2018

Если таблица уже была ранее создана, и ее необходимо изменить, то для этого применяется
команда ALTER TABLE. Ее сокращенный формальный синтаксис:

ALTER TABLE название_таблицы


{ ADD название_столбца тип_данных_столбца [атрибуты_столбца] |
DROP COLUMN название_столбца |
MODIFY COLUMN название_столбца тип_данных_столбца [атрибуты_столбца] |
ALTER COLUMN название_столбца SET DEFAULT значение_по_умолчанию | ADD
[CONSTRAINT] определение_ограничения |
DROP [CONSTRAINT] имя_ограничения}

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

Добавление нового столбца

Добавим в таблицу Customers новый столбец Address:


ALTER TABLE Customers
ADD Address VARCHAR(50) NULL;

В данном случае столбец Address имеет тип VARCHAR и для него определен атрибут NULL.

Удаление столбца

Удалим столбец Address из таблицы Customers:


ALTER TABLE Customers
DROP COLUMN Address;

Изменение значения по умолчанию

Установим в таблице Customers для столбца Age значение по умолчанию 22:


ALTER TABLE Customers
ALTER COLUMN Age SET DEFAULT 22;
Изменение типа столбца

Изменим в таблице Customers тип данных у столбца FirstName на CHAR(100) и установим для
него атрибут NULL:

ALTER TABLE Customers


MODIFY COLUMN FirstName CHAR(100) NULL;
28

Добавление и удаление внешнего ключа

Пусть изначально в базе данных будут добавлены две таблицы, никак не связанные:
CREATE TABLE Customers
(
Id INT PRIMARY KEY AUTO_INCREMENT,
Age INT,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL
);
CREATE TABLE Orders
(
Id INT PRIMARY KEY AUTO_INCREMENT,
CustomerId INT,
CreatedAt Date
);

Добавим ограничение внешнего ключа к столбцу CustomerId таблицы Orders:


ALTER TABLE Orders
ADD FOREIGN KEY(CustomerId) REFERENCES Customers(Id);

При добавлении ограничений мы можем указать для них имя, используя оператор
CONSTRAINT, после которого указывается имя ограничения:
ALTER TABLE Orders
ADD CONSTRAINT orders_customers_fk
FOREIGN KEY(CustomerId) REFERENCES Customers(Id);

В данном случае ограничение внешнего ключа называется orders_customers_fk. Затем по


этому имени мы можем удалить ограничение:
ALTER TABLE Orders
DROP FOREIGN KEY orders_customers_fk;

Добавление и удаление первичного ключа

Добавим в таблицу Products первичный ключ:


CREATE TABLE Products
(
Id INT,
Model VARCHAR(20)
);

ALTER TABLE Products


ADD PRIMARY KEY (Id);

Теперь удалим первичный ключ:


ALTER TABLE Products
DROP PRIMARY KEY;

НазадСодержаниеВперед
Глава 3. Основные операции с
данными 3.1 Добавление данных. Команда
INSERT
29

Последнее обновление: 11.05.2018

Для добавления данных в БД в MySQL используется команда INSERT, которая имеет


следующий формальный синтаксис:

INSERT [INTO] имя_таблицы [(список_столбцов)] VALUES (значение1, значение2, ...


значениеN)

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

Например, пусть в базе данных productsdb есть следующая таблица Products:


CREATE DATABASE productsdb;
USE productsdb;
CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);

Добавим в эту таблицу одну строку с помощью следующего кода:


INSERT Products(ProductName, Manufacturer, ProductCount, Price)
VALUES ('iPhone X', 'Apple', 5, 76000);

В данном случае значения будут передаваться столбцам по позиции. То есть столбцу


ProductName передается строка "iPhone X", столбцу Manufacturer - строка "Apple" и так
далее.

Важно, чтобы между значениями и типами данных столбцов было соответствие. Так, столбец
ProductName представляет тип varchar, то есть строку. Соответственно этому столбцу мы
можем передать строковое значение в одинарных кавычках. А столбец ProductCount
представляет тип int, то есть целое число, поэтому данному столбцу нужно передать целые
числа, но никак не строки.

После удачного выполнения в MySQL Workbench в поле вывода должны появиться зеленый
маркер и сообщение "1 row(s) affected":
30

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

Также мы можем опускать при добавлении такие столбцы, которые поддерживают значение
NULL или для которых указано значение по умолчанию, то есть для них определены
атрибуты NULL или DEFAULT. Так, в таблице Products столбец ProductCount имеет значение по
умолчанию - число 0. Поэтому мы можем при добавлении опустить этот столбец, и ему
будет передаваться число 0:
INSERT Products(ProductName, Manufacturer, Price)
VALUES ('Galaxy S9', 'Samsung', 63000);

С помощью ключевых слов DEFAULT и NULL можно указать, что в качестве значения будет
использовать значение по умолчанию или NULL соответственно:
INSERT Products(ProductName, Manufacturer, Price, ProductCount)
VALUES ('Nokia 9', 'HDM Global', 41000, DEFAULT);

или
INSERT Products(ProductName, Manufacturer, Price, ProductCount)
VALUES ('Nokia 9', 'HDM Global', 41000, NULL);

Множественное добавление

Также мы можем добавить сразу несколько строк:


INSERT Products(ProductName, Manufacturer, Price, ProductCount)
VALUES
('iPhone 8', 'Apple', 51000, 3),
('P20 Lite', 'Huawei', 34000, 4),
('Galaxy S8', 'Samsung', 46000, 2);

В данном случае в таблицу будут добавлены три строки.

НазадСодержаниеВперед

3.2 Выборка данных. Команда SELECT


Последнее обновление: 11.05.2018

Для выборки данных из БД в MySQL применяется команда SELECT. В упрощенном виде она
имеет следующий синтаксис:
SELECT список_столбцов FROM имя_таблицы

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

CREATE TABLE Products


(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL
31

);

INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price)


VALUES
('iPhone X', 'Apple', 3, 76000),
('iPhone 8', 'Apple', 2, 51000),
('Galaxy S9', 'Samsung', 2, 56000),
('Galaxy S8', 'Samsung', 1, 41000),
('P20 Pro', 'Huawei', 5, 36000);

Получим все объекты из этой таблицы:


SELECT * FROM Products;

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

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

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


спецификации этих столбцов перечисляются через запятую после SELECT:

SELECT ProductName, Price FROM Products;


32

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

SELECT ProductName, Price * ProductCount


FROM Products;

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

С помощью оператора AS можно изменить название выходного столбца или определить его
псевдоним:

SELECT ProductName AS Title, Price * ProductCount AS TotalSum


FROM Products;

Здесь для первого столбца определяется псевдоним Title, хотя в реальности он будет
представлять столбец ProductName. Второй столбец TotalSum хранит произведение столбцов
ProductCount и Price.

НазадСодержаниеВперед
3.3 Фильтрация данных. Оператор WHERE
Последнее обновление: 11.05.2018

Зачастую необходимо извлекать не все данные из БД, а только те, которые соответствуют
определенному условию. Для фильтрации данных в команде SELECT применяется оператор
WHERE, после которого указывается условие:

WHERE условие

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


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

• =: сравнение на равенство
• !=: сравнение на равенство
• <>: сравнение на неравенство
• <: меньше чем
• >: больше чем
• <=: меньше чем или равно
• >=: больше чем или равно
33

К примеру, выберем всех товары, производителем которых является компания Samsung:


SELECT * FROM Products
WHERE Manufacturer = 'Samsung';

Стоит отметить, что для MySQL не важен регистр символов, и, к примеру, строка "Samsung"
будет эквивалентна строке "SAMSUNG" или "sumSunG".

Другой пример - найдем все товары, количество которых меньше 3:


SELECT * FROM Products
WHERE ProductCount < 3;

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


Например, найдем все товары, у которых совокупная стоимость больше 100 000:
SELECT * FROM Products
WHERE Price * ProductCount > 100000;

Логические операторы

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


использовать следующие логические операторы:

• AND: операция логического И. Она объединяет два выражения:


выражение1 AND выражение2

Только если оба этих выражения одновременно истинны, то и общее условие


оператора AND также будет истинно. То есть если и первое условие истинно, и
второе.
34

• OR: операция логического ИЛИ. Она также объединяет два выражения:


выражение1 OR выражение2

Если хотя бы одно из этих выражений истинно, то общее условие оператора OR также
будет истинно. То есть если или первое условие истинно, или второе.

• NOT:операция логического отрицания. Если выражение в этой операции ложно, то


общее условие истинно.

NOT выражение

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


больше 50000:

SELECT * FROM Products


WHERE Manufacturer = 'Samsung' AND Price > 50000

Теперь изменим оператор на OR. То есть выберем все товары, у которых либо производитель
Samsung, либо цена больше 50000:

SELECT * FROM Products


WHERE Manufacturer = 'Samsung' OR Price > 50000

Применение оператора NOT - выберем все товары, у которых производитель не Samsung:


SELECT * FROM Products
WHERE NOT Manufacturer = 'Samsung';
35
Приоритет операций

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


Однако следует учитывать, что самой приоритетной операцией, которая выполняется в
первую очередь, является NOT, менее приоритетная - AND и операция с наименьшим
приоритетом - OR. Например:
SELECT * FROM Products
WHERE Manufacturer ='Samsung' OR NOT Price > 30000 AND ProductCount > 2;

В данном случае сначала вычисляется выражение NOT Price > 30000, то есть цена должна
быть меньше или равна 30000.

Затем вычисляется выражение NOT Price > 30000 AND ProductCount > 2, то есть цена
должна быть меньше или равна 30000 и одновременно количество товаров должно быть
больше 2.

В конце вычисляется оператор OR - либо цена должна быть меньше или равна 30000 и
одновременно количество товаров должно быть больше 2, либо производителем должен
быть Samsung.

С помощью скобок можно переопределить приоритет операций:


SELECT * FROM Products
WHERE Manufacturer ='Samsung' OR NOT (Price > 30000 AND ProductCount > 2);

В данном случае находим товары, у которых либо производитель Samsung, либо


одновременно цена товара меньше или равна 30000 и количество товаров меньше
3.
36
НазадСодержаниеВперед
3.4 Обновление данных. Команда UPDATE
Последнее обновление: 11.05.2018

Команда UPDATE применяется для обновления уже имеющихся строк. Она имеет
следующий формальный синтаксис:
UPDATE имя_таблицы
SET столбец1 = значение1, столбец2 = значение2, ... столбецN = значениеN
[WHERE условие_обновления]

Например, увеличим у всех товаров цену на 3000:


UPDATE Products
SET Price = Price + 3000;

Однако при выполнении данного запроса в MySQL Workbench мы можем столкнуться с


ошибкой:

Ошибка говорит о том, что мы находимся в безопасном режиме. И чтобы его отключить, в
MySQL Workbench надо перейти в меню Edit -> Preferences и в открывшемся окне перейти к
пункту SQL Editor:
37
В открывшейся вкладке в самом низу надо снять флажок с поля "Safe Updates (reject
UPDATEs and DELETEs with no restrictions)" и затем сохранить изменения, нажав на кнопку
OK. После этого надо переподключиться к серверу.

Используем выражение WHERE и изменим название производителя с "Samsung" на


"Samsung Inc.":

UPDATE Products
SET Manufacturer = 'Samsung Inc.'
WHERE Manufacturer = 'Samsung';

Также можно обновлять сразу несколько столбцов:


UPDATE Products
SET Manufacturer = 'Samsung',
ProductCount = ProductCount + 3
WHERE Manufacturer = 'Samsung Inc.';

При обновлении вместо конкретных значений и выражений мы можем использовать


ключевые слова DEFAULT и NULL для установки соответственно значения по умолчанию
или NULL:
UPDATE Products
SET ProductCount= DEFAULT
WHERE Manufacturer = 'Huawei';

НазадСодержаниеВперед

3.5 Удаление данных. Команда DELETE


38

Последнее обновление: 11.05.2018


Команда DELETE удаляет данные из БД. Она имеет следующий формальный синтаксис:
DELETE FROM имя_таблицы
[WHERE условие_удаления]

Например, удалим строки, у которых производитель - Huawei:


DELETE FROM Products
WHERE Manufacturer='Huawei';

Или удалим все товары, производителем которых является Apple и которые имеют цену
меньше 60000:
DELETE FROM Products
WHERE Manufacturer='Apple' AND Price < 60000;

Если необходимо вовсе удалить все строки вне зависимости от условия, то условие можно не
указывать:
DELETE FROM Products;

НазадСодержаниеВперед

Глава 4. Запросы
4.1 Выборка уникальных значений. Оператор
DISTINCT Последнее обновление: 16.05.2018
С помощью оператора DISTINCT можно выбрать уникальные данные по определенным
столбцам.

К примеру, разные товары могут иметь одних и тех же производителей, и, допустим, у нас
следующая таблица товаров:
USE productsdb;

DROP TABLE IF EXISTS Products;


39

CREATE TABLE Products


(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);
INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price)
VALUES
('iPhone X', 'Apple', 3, 71000),
('iPhone 8', 'Apple', 3, 56000),
('Galaxy S9', 'Samsung', 6, 56000),
('Galaxy S8', 'Samsung', 2, 46000),
('Honor 10', 'Huawei', 3, 26000);

Выберем всех производителей:


SELECT Manufacturer FROM Products;

Однако при таком запросе производители повторяются. Теперь применим оператор


DISTINCT для выборки уникальных значений:
SELECT DISTINCT Manufacturer FROM Products;

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

столбцам: SELECT DISTINCT Manufacturer, ProductCount FROM Products;

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


строк только для двух строк эти столбцы имеют повторяющиеся значения. Поэтому в
выборке будет 4 строки:
40
НазадСодержаниеВперед
4.2 Операторы фильтрации
Последнее обновление: 16.05.2018

Оператор IN

Оператор IN определяет набор значений, которые должны иметь

столбцы: WHERE выражение [NOT] IN (выражение)

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

Например, выберем товары, у которых производитель либо Samsung, либо Xiaomi, либо
Huawei:
SELECT * FROM Products
WHERE Manufacturer IN ('Samsung', 'HTC', 'Huawei');

Оператор NOT, наоборот, позволяет выбрать все строки, столбцы которых не имеют
определенных значений:
SELECT * FROM Products
WHERE Manufacturer NOT IN ('Samsung', 'HTC', 'Huawei');
41
Оператор BETWEEN
Оператор BETWEEN определяет диапазон значений с помощью начального и конечного
значения, которому должно соответствовать выражение:

WHERE выражение [NOT] BETWEEN начальное_значение AND конечное_значение

Например, получим все товары, у которых цена от 20 000 до 50 000 (начальное и конечное
значения также включаются в диапазон):
SELECT * FROM Products
WHERE Price BETWEEN 20000 AND 50000;

Если надо, наоборот, выбрать те строки, которые не попадают в данный диапазон, то


добавляется оператор NOT:
SELECT * FROM Products
WHERE Price NOT BETWEEN 20000 AND 50000;

Также можно использовать более сложные выражения. Например, получим товары по


совокупной стоимости (цена * количество):

SELECT * FROM Products


WHERE Price * ProductCount BETWEEN 90000 AND 150000;

Операторы LIKE и REGEXP

Оператор LIKE принимает шаблон строки, которому должно соответствовать

выражение. WHERE выражение [NOT] LIKE шаблон_строки

Для определения шаблона могут применяться ряд специальных символов подстановки:


42

• %:соответствует любой подстроке, которая может иметь любое количество символов,


при этом подстрока может и не содержать ни одного символа

Например, выражение WHERE ProductName LIKE 'Galaxy%' соответствует таким


значениям как "Galaxy Ace 2" или "Galaxy S7"

• _: соответствует любому одиночному символу

Например, выражение WHERE ProductName LIKE 'Galaxy S_' соответствует таким


значениям как "Galaxy S7" или "Galaxy S8".

Применим оператор LIKE:


SELECT * FROM Products
WHERE ProductName LIKE 'iPhone%';

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


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

WHERE выражение [NOT] REGEXP регулярное выражение

Регулярное выражение может принимать следующие специальные символы:

• ^: указывает на начало строки


• $: указывает на конец строки
• .: соответствует любому одиночному символу
• [символы]: соответствует любому одиночному символу из скобок
• [начальный_символ-конечный_символ]: соответствует любому одиночному символу
из диапазона символов
• |: отделяет два шаблона строки, и значение должно соответствовать одну из этих
шаблонов

Примеры REGEXP:

• WHERE ProductName REGEXP 'Phone': строка должна содержать "Phone", например,


iPhone X, Nokia Phone N, iPhone
• WHERE ProductName REGEXP '^Phone': строка должна начинаться с "Phone",
например, Phone 34, PhoneX
• WHERE ProductName REGEXP 'Phone$': строка должна заканчиваться на "Phone",
например, iPhone, Nokia Phone
• WHERE ProductName REGEXP 'iPhone [78]';: строка должна содержать либо iPhone 7,
либо iPhone 8
43

• WHERE ProductName REGEXP 'iPhone [6-8]';: строка должна содержать либо iPhone 6,
либо iPhone 7, либо iPhone 8

Например, найдем товары, названия которых содержат либо "Phone", либо "Galaxy":
SELECT * FROM Products
WHERE ProductName REGEXP 'Phone|Galaxy';

IS NULL

Оператор IS NULL позволяет выбрать все строки, столбцы которых имеют значение NULL:
SELECT * FROM Products
WHERE ProductCount IS NULL;

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

SELECT * FROM Products


WHERE ProductCount IS NOT NULL;

НазадСодержаниеВперед

4.3 Сортировка. ORDER BY


Последнее обновление: 16.05.2018

Оператор ORDER BY сортируют значения по одному или нескольких столбцам. Например,


упорядочим выборку из таблицы Products по столбцу Price:

SELECT * FROM Products


ORDER BY Price;
44

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


определяется с помощью оператора AS:
SELECT ProductName, ProductCount * Price AS TotalSum
FROM Products
ORDER BY TotalSum;

В качестве критерия сортировки также можно использовать сложно выражение на основе


столбцов:

SELECT ProductName, Price, ProductCount


FROM Products
ORDER BY ProductCount * Price;

Сортировка по убыванию

По умолчанию данные сортируются по возрастанию, однако с помощью оператора DESC


можно задать сортировку по убыванию.

SELECT ProductName, ProductCount


FROM Products
ORDER BY ProductCount DESC;
45

По умолчанию вместо DESC используется оператор ASC, который сортирует по


возрастанию:
SELECT ProductName, ProductCount
FROM Products
ORDER BY ProductCount ASC;

Сотировка по нескольким столбцам

При сортировке сразу по нескольким столбцам все эти столбцы указываются через запятую
после оператора ORDER BY:

SELECT ProductName, Price, Manufacturer


FROM Products
ORDER BY Manufacturer, ProductName;

Здесь строки сначала сортируются по столбцу Manufacturer по возрастанию. Затем если есть
две строки, в которых столбец Manufacturer имеет одинаковое значение, то они сортируются
по столбцу ProductName также по возрастанию. Но опять же с помощью ASC и DESC можно
отдельно для разных столбцов определить сортировку по возрастанию и убыванию:
SELECT ProductName, Price, Manufacturer
FROM Products
ORDER BY Manufacturer ASC, ProductName DESC;

НазадСодержаниеВперед
46

4.4 Получение диапазона строк. Оператор


LIMIT Последнее обновление: 16.05.2018
Оператор LIMIT позволяет извлечь определенное количество строк и имеет следующий
синтаксис:
LIMIT [offset,] rowcount

Если оператору LIMIT передается один параметр, то он указывает на количество


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

Например, выберем первые три строки:


SELECT * FROM Products
LIMIT 3;
Теперь используем второй параметр и укажем смещение, с которой должна происходить
выборка:

SELECT * FROM Products


LIMIT 2, 3;

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

Как правило, оператор LIMIT используетс вместе с оператором ORBER BY:


47

SELECT * FROM Products


ORDER BY ProductName
LIMIT 2, 3;

НазадСодержаниеВперед

4.5 Агрегатные функции


Последнее обновление: 21.05.2018

Агрегатные функции вычисляют некоторые скалярные значения в наборе строк. В MySQL


есть следующие агрегатные функции:

• AVG: вычисляет среднее значение


• SUM: вычисляет сумму значений
• MIN: вычисляет наименьшее значение
• MAX: вычисляет наибольшее значение
• COUNT: вычисляет количество строк в запросе

Все агрегатные функции принимают в качестве параметра выражение, которое представляет


критерий для определения значений. Зачастую, в качестве выражения выступает название
столбца, над значениями которого надо проводить вычисления.
Выражения в функциях AVG и SUM должно представлять числовое значение (например,
столбец, который хранит числовые значения). Выражение в функциях MIN, MAX и COUNT
может представлять числовое или строковое значение или дату.

Все агрегатные функции за исключением COUNT(*) игнорируют значения

NULL. Avg

Функция Avg возвращает среднее значение на диапазоне значений столбца

таблицы. Например, пусть есть следующая таблица товаров Products:

CREATE TABLE Products


(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);

INSERT INTO Products(ProductName, Manufacturer, ProductCount, Price)


VALUES
('iPhone X', 'Apple', 3, 76000),
('iPhone 8', 'Apple', 2, 51000),
('iPhone 7', 'Apple', 5, 32000),
('Galaxy S9', 'Samsung', 2, 56000),
('Galaxy S8', 'Samsung', 1, 46000),
('Honor 10', 'Huawei', 5, 28000),
('Nokia 8', 'HMD Global', 6, 38000)

Найдем среднюю цену товаров из базы данных:


SELECT AVG(Price) AS Average_Price FROM Products
48

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

На этапе выборки можно применять фильтрацию. Например, найдем среднюю цену для
товаров определенного производителя:
SELECT AVG(Price) FROM Products
WHERE Manufacturer='Apple'

Также можно находить среднее значение для более сложных выражений. Например, найдем
среднюю сумму всех товаров, учитывая их количество:
SELECT AVG(Price * ProductCount) FROM Products

Count
Функция Count вычисляет количество строк в выборке. Есть две формы этой функции.
Первая форма COUNT(*) подсчитывает число строк в выборке:

SELECT COUNT(*) FROM Products

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

SELECT COUNT(Manufacturer) FROM Products

Min и Max

Функции Min и Max вычисляют минимальное и максимальное значение по столбцу


соответственно. Например, найдем минимальную цену среди товаров:
SELECT MIN(Price), MAX(Price) FROM Products
49

Данные функции также игнорируют значения NULL и не учитывают их при подсчете.

Sum

Функция Sum вычисляет сумму значений столбца. Например, подсчитаем общее количество
товаров:
SELECT SUM(ProductCount) FROM Products

Также вместо имени столбца может передаваться вычисляемое выражение. Например,


найдем общую стоимость всех имеющихся товаров:

SELECT SUM(ProductCount * Price) FROM Products

All и Distinct

По умолчанию все вышеперечисленных пять функций учитывают все строки выборки для
вычисления результата. Но выборка может содержать повторяющие значения. Если
необходимо выполнить вычисления только над уникальными значениями, исключив из
набора значений повторяющиеся данные, то для этого применяется оператор DISTINCT.
SELECT COUNT(DISTINCT Manufacturer) FROM Products
По умолчанию вместо DISTINCT применяется оператор ALL, который выбирает все строки:
SELECT COUNT(ALL Manufacturer) FROM Products

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

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

Комбинирование функций

Объединим применение нескольких функций:


SELECT COUNT(*) AS ProdCount,
SUM(ProductCount) AS TotalCount,
MIN(Price) AS MinPrice,
MAX(Price) AS MaxPrice,
AVG(Price) AS AvgPrice
FROM Products

НазадСодержаниеВперед
50

4.6 Группировка
Последнее обновление: 21.05.2018

Операторы GROUP BY и HAVING позволяют сгруппировать данные. Они употребляются в


рамках команды SELECT:
SELECT столбцы
FROM таблица
[WHERE условие_фильтрации_строк]
[GROUP BY столбцы_для_группировки]
[HAVING условие_фильтрации_групп]
[ORDER BY столбцы_для_сортировки]

GROUP BY

Оператор GROUP BY определяет, как строки будут группироваться.

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


SELECT Manufacturer, COUNT(*) AS ModelsCount
FROM Products
GROUP BY Manufacturer

Первый столбец в выражении SELECT - Manufacturer представляет название группы, а


второй столбец - ModelsCount представляет результат функции Count, которая вычисляет
количество строк в группе.
И если в выражении SELECT производится выборка по одному или нескольким столбцам и
также используются агрегатные функции, то необходимо использовать выражение GROUP
BY. Так, следующий пример работать не будет, так как он не содержит выражение
группировки:

SELECT Manufacturer, COUNT(*) AS ModelsCount


FROM Products

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


группировку по количеству товаров:
SELECT Manufacturer, ProductCount, COUNT(*) AS ModelsCount
FROM Products
GROUP BY Manufacturer, ProductCount
51

Следует учитывать, что выражение GROUP BY должно идти после выражения WHERE, но до
выражения ORDER BY:

SELECT Manufacturer, COUNT(*) AS ModelsCount


FROM Products
WHERE Price > 30000
GROUP BY Manufacturer
ORDER BY ModelsCount DESC

Фильтрация групп. HAVING

Оператор HAVING позволяет выполнить фильтрацию групп, то есть определяет, какие


группы будут включены в выходной результат.

Использование HAVING во многом аналогично применению WHERE. Только есть WHERE


применяется для фильтрации строк, то HAVING - для фильтрации групп.
Например, найдем все группы товаров по производителям, для которых определено более 1
модели:

SELECT Manufacturer, COUNT(*) AS ModelsCount


FROM Products
GROUP BY Manufacturer
HAVING COUNT(*) > 1

В одной команде также можно сочетать выражения WHERE и HAVING:


SELECT Manufacturer, COUNT(*) AS ModelsCount

52

FROM Products
WHERE Price * ProductCount > 80000
GROUP BY Manufacturer
HAVING COUNT(*) > 1;

То есть в данном случае сначала фильтруются строки: выбираются те товары, общая


стоимость которых больше 80000. Затем выбранные товары группируются по
производителям. И далее фильтруются сами группы - выбираются те группы, которые
содержат больше 1 модели.

Если при этом необходимо провести сортировку, то выражение ORDER BY идет после
выражения HAVING:

SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units


FROM Products
WHERE Price * ProductCount > 80000
GROUP BY Manufacturer
HAVING SUM(ProductCount) > 2
ORDER BY Units DESC;

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


каждого производителя (Models) и общее количество всех товаров по всем этим моделям
(Units). В конце группы сортируются по количеству товаров по убыванию.
НазадСодержаниеВперед
4.7 Подзапросы
Последнее обновление: 22.05.2018

Подзапросы представляют выражения SELECT, которые встроены в другие запросы SQL.


Рассмотрим простейший пример применения подзапросов.

Например, создадим таблицы для товаров и заказов:


CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);
53

CREATE TABLE Orders


(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL REFERENCES Products(Id) ON DELETE CASCADE,
ProductCount INT DEFAULT 1,
CreatedAt DATE NOT NULL,
Price DECIMAL NOT NULL
);

Таблица Orders содержит данные о купленным товарам из таблицы

Products. Добавим в таблицы некоторые данные:

INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price)


VALUES ('iPhone X', 'Apple', 2, 76000),
('iPhone 8', 'Apple', 2, 51000),
('iPhone 7', 'Apple', 5, 42000),
('Galaxy S9', 'Samsung', 2, 56000),
('Galaxy S8', 'Samsung', 1, 46000),
('Honor 10', 'Huawei', 2, 26000),
('Nokia 8', 'HMD Global', 6, 38000);

INSERT INTO Orders (ProductId, CreatedAt, ProductCount, Price)


VALUES
(
(SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
'2018-05-21',
2,
(SELECT Price FROM Products WHERE ProductName='Galaxy S8') ),
(
(SELECT Id FROM Products WHERE ProductName='iPhone X'),
'2018-05-23',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone X') ),
(
(SELECT Id FROM Products WHERE ProductName='iPhone 8'),
'2018-05-21',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone 8') );

При добавлении данных в таблицу Orders как раз используются подзапросы. Например,
первый заказ был сделан на товар Galaxy S8. Соответственно в таблицу Orders нам надо
сохранить информацию о заказе, где поле ProductId указывает на Id товара Galaxy S8, поле
Price - на его цену. Но на момент написания запроса нам может быть неизвестен ни Id
покупателя, ни Id товара, ни цена товара. В этом случае можно выполнить подзапрос в
виде
(SELECT Price FROM Products WHERE ProductName='iPhone 8')

Подзапрос выполняет команду SELECT и заключается в скобки. В данном же случае при


добавлении одного товара выполняется два подзапроса. Каждый подзапрос возвращает
одного скалярное значение, например, числовой идентификатор.

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


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

SELECT * FROM Products


WHERE Price = (SELECT MIN(Price) FROM Products);

Или найдем товары, цена которых выше средней:


54

SELECT * FROM Products


WHERE Price > (SELECT AVG(Price) FROM Products);

Коррелирующие и некоррелирующие подзапросы

Подзапросы бывают коррелирующими и некоррелирующими. В примерах выше команды


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

Но также можно использовать и коррелирующие подзапросы (correlated subquery),


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

Например, выберем все заказы из таблицы Orders, добавив к ним информацию о товаре:
SELECT CreatedAt, Price,
(SELECT ProductName FROM Products
WHERE Products.Id = Orders.ProductId) AS Product
FROM Orders;

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

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


выполняется основной запрос. Например, выберем из таблицы Products те товары, стоимость
которых выше средней цены товаров для данного производителя:
SELECT ProductName,
55

Manufacturer,
Price,
(SELECT AVG(Price) FROM Products AS SubProds
WHERE SubProds.Manufacturer=Prods.Manufacturer) AS AvgPrice
FROM Products AS Prods
WHERE Price >
(SELECT AVG(Price) FROM Products AS SubProds
WHERE SubProds.Manufacturer=Prods.Manufacturer);

Здесь определено два коррелирующих подзапроса. Первый подзапрос определяет


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

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


таблицы Products. И также он будет выполняться для каждой строки.

Чтобы избежать двойственности при фильтрации в подзапросе при сравнении


производителей (SubProds.Manufacturer=Prods.Manufacturer) для внешней выборки
установлен псевдоним Prods, а для выборки из подзапросов определен псевдоним SubProds.

Следует учитывать, что коррелирующие подзапросы выполняются для каждой отдельной


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

НазадСодержаниеВперед

4.7 Подзапросы в основных командах SQL


Последнее обновление: 22.05.2018

Подзапросы в SELECT

В выражении SELECT мы можем вводить подзапросы четырьмя способами:

1. В условии в выражении WHERE


2. В условии в выражении HAVING
3. В качестве таблицы для выборки в выражении FROM
4. В качестве спецификации столбца в выражении SELECT
56

Рассмотрим некоторые из этих случаев. Например, получим все товары, у которых цена
выше средней:

SELECT * FROM Products


WHERE Price > (SELECT AVG(Price) FROM Products)

Чтобы получить нужные товары, нам вначале надо выполнить подзапрос на получение
средней цены товара: SELECT AVG(Price) FROM Products.

Оператор IN

Нередко подзапросы применяются вместе с оператором IN, который выбирает из набора


значений. И подзапрос как раз может предоставить требуемый набор значений. Например,
выберем все товары из таблицы Products, на которые есть заказы в таблице Orders:
SELECT * FROM Products
WHERE Id IN (SELECT ProductId FROM Orders)

То есть подзапрос в данном случае выбирает все идентификаторы товаров из Orders, затем
по этим идентификаторам извлекаютя товары из Products.

Добавив оператор NOT, мы можем выбрать те товары, на которые нет заказов в таблице
Orders:

SELECT * FROM Products


WHERE Id NOT IN (SELECT ProductId FROM Orders)

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

Получение набора значений

При использовании в операторах сравнения подзапросы должны возвращать одно скалярное


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

SELECT * FROM Products


WHERE Price < ALL(SELECT Price FROM Products WHERE Manufacturer='Apple')

Если бы мы в данном случае опустили бы ключевое слово ALL, то мы бы столкнулись с


ошибкой.

Допустим, если данный подзапрос возвращает значения vаl1, val2 и val3, то условие
фильтрации фактически было бы аналогично объединению этих значений через оператор
AND:
WHERE Price < val1 AND Price < val2 AND Price < val3

В тоже время подобный запрос гораздо проще переписать другим образом:


SELECT * FROM Products
WHERE Price < (SELECT MIN(Price) FROM Products WHERE Manufacturer='Apple')
57

Как работает оператор ALL:

• x > ALL (1, 2) эквивалентно x > 2


• x < ALL (1, 2) эквивалентно x < 1
•x = ALL (1, 2) эквивалентно (x = 1) AND (x = 2)
•x <> ALL (1, 2) эквивалентно x NOT IN (1, 2)

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

SELECT * FROM Products


WHERE Price < ANY(SELECT Price FROM Products WHERE Manufacturer='Apple')

И также стоит отметить, что данный запрос можно сделать проще, переписав следующим
образом:
SELECT * FROM Products
WHERE Price < (SELECT MAX(Price) FROM Products WHERE Manufacturer='Apple')

Как работает оператор ANY (а также SOME):

• x > ANY (1, 2) эквивалентно x > 1


• x < ANY (1, 2) эквивалентно x < 2
•x = ANY (1, 2) эквивалентно x NOT (1, 2)
•x <> ANY (1, 2) эквивалентно (x <> 1) OR (x <> 2)

Подзапрос как спецификация столбца

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


все заказы и добавим к ним информацию о названии товара:

SELECT *,
(SELECT ProductName FROM Products WHERE Id=Orders.ProductId) AS Product
FROM Orders
Подзапросы в команде INSERT
В команде INSERT подзапросы могут применяться для определения значения, которое
вставляется в один из столбцов:

INSERT INTO Orders (ProductId, CreatedAt, ProductCount, Price)


VALUES
58

(
(SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
'2018-05-23',
2,
(SELECT Price FROM Products WHERE ProductName='Galaxy S8')
)

Подзапросы в команде UPDATE

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

1. В качестве устанавливаемого значения после оператора SET


2. Как часть условия в выражении WHERE

Так, увеличим в таблице Orders количество купленных товаров компании Apple на 2:


UPDATE Orders
SET ProductCount = ProductCount + 2
WHERE ProductId IN (SELECT Id FROM Products WHERE Manufacturer='Apple');

Или установим для заказа цену товара, полученную в результате подзапроса:

UPDATE Orders
SET Price = (SELECT Price FROM Products WHERE Id=Orders.ProductId) + 3000
WHERE Id=1;

Подзапросы в команде DELETE

В команде DELETE подзапросы также применяются как часть условия. Так, удалим все
заказы на Galaxy S8:
DELETE FROM Orders
WHERE ProductId=(SELECT Id FROM Products WHERE ProductName='Galaxy S8');

НазадСодержаниеВперед

4.9 Оператор EXISTS


Последнее обновление: 22.05.2018

Оператор EXISTS проверяет, возвращает ли подзапрос какое-либо значение. Как правило,


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

Применение оператора имеет следующий формальный синтаксис:


WHERE [NOT] EXISTS (подзапрос)

Например, найдем все товары из таблицы Products, на которые есть заказы в таблице Orders:
SELECT * FROM Products
WHERE EXISTS
(SELECT * FROM Orders WHERE Orders.ProductId = Products.Id)
59

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


условию, то можно использовать операторы NOT EXISTS. Например, найдем все товары из
таблицы Products, на которые не было заказов в таблице Orders:
SELECT * FROM Products
WHERE NOT EXISTS (SELECT * FROM Orders WHERE Products.Id = Orders.ProductId)

Стоит отметить, что для получения подобного результата можно было бы использовать и
опеатор IN:

SELECT *
FROM Products
WHERE Id NOT IN (SELECT ProductId FROM Orders)

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


более оптимально и эффективно, чем использование оператора IN.

НазадСодержаниеВперед

Глава 5. Соединение таблиц


5.1 Неявное соединение таблиц
Последнее обновление: 22.05.2018

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


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

Допустим, у нас есть следующие таблицы, которые связаны между собой связями:
CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);
CREATE TABLE Customers
(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL
60

);
CREATE TABLE Orders
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL REFERENCES Products(Id) ON DELETE CASCADE,
CustomerId INT NOT NULL REFERENCES Customers(Id) ON DELETE CASCADE,
CreatedAt DATE NOT NULL,
ProductCount INT DEFAULT 1,
Price DECIMAL NOT NULL
);

Здесь таблицы Products и Customers связаны с таблицей Orders связью один ко многим.
Таблица Orders в виде внешних ключей ProductId и CustomerId содержит ссылки на столбцы
Id из соответственно таблиц Products и Customers. Также она хранит количество купленного
товара (ProductCount) и и по какой цене он был куплен (Price). И кроме того, таблицы также
хранит в виде столбца CreatedAt дату покупки.

Пусть эти таблицы будут содержать следующие данные:


INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price)
VALUES ('iPhone X', 'Apple', 2, 76000),
('iPhone 8', 'Apple', 2, 51000),
('iPhone 7', 'Apple', 5, 42000),
('Galaxy S9', 'Samsung', 2, 56000),
('Galaxy S8', 'Samsung', 1, 46000),
('Honor 10', 'Huawei', 2, 26000),
('Nokia 8', 'HMD Global', 6, 38000);

INSERT INTO Customers(FirstName) VALUES ('Tom'), ('Bob'),('Sam');

INSERT INTO Orders (ProductId, CustomerId, CreatedAt, ProductCount, Price)


VALUES
(
(SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
(SELECT Id FROM Customers WHERE FirstName='Tom'),
'2018-05-21',
2,
(SELECT Price FROM Products WHERE ProductName='Galaxy S8') ),
(
(SELECT Id FROM Products WHERE ProductName='iPhone X'),
(SELECT Id FROM Customers WHERE FirstName='Tom'),
'2018-05-23',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone X') ),
(
(SELECT Id FROM Products WHERE ProductName='iPhone X'),
(SELECT Id FROM Customers WHERE FirstName='Bob'),
'2018-05-21',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone X') );

Теперь соединим две таблицы Orders и Customers:


SELECT * FROM Orders, Customers;

При такой выборке каждая строка из таблицы Orders будет соединяться с каждой строкой из
таблицы Customers. То есть, получится перекрестное соединение. Например, в Orders три
строки, а в Customers то же три строки, значит мы получим 3 * 3 = 9 строк:
61

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

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


при условии, что поле CustomerId из Orders соответствует полю Id из Customers:
SELECT * FROM Orders, Customers
WHERE Orders.CustomerId = Customers.Id;

Теперь объединим данные по трем таблицам Orders, Customers и Proucts. То есть получим
все заказы и добавим информацию по клиенту и связанному товару:

SELECT Customers.FirstName, Products.ProductName, Orders.CreatedAt


FROM Orders, Customers, Products
WHERE Orders.CustomerId = Customers.Id AND Orders.ProductId=Products.Id;

Так как здесь нужно соединить три таблицы, то применяются как минимум два
условия. Ключевой таблицей остается Orders, из которой извлекаются все заказы, а
затем к ней подсоединяется данные по клиенту по условию Orders.CustomerId =
Customers.Id и данные по товару по условию Orders.ProductId=Products.Id
62
В данном случае названия таблиц сильно увеличивают код, но мы его можем сократить за
счет использования псевдонимов таблиц:

SELECT C.FirstName, P.ProductName, O.CreatedAt


FROM Orders AS O, Customers AS C, Products AS P
WHERE O.CustomerId = C.Id AND O.ProductId=P.Id;

Если необходимо при использовании псевдонима выбрать все столбцы из определенной


таблицы, то можно использовать звездочку:
SELECT C.FirstName, P.ProductName, O.*
FROM Orders AS O, Customers AS C, Products AS P
WHERE O.CustomerId = C.Id AND O.ProductId=P.Id;

НазадСодержаниеВперед

5.2 Inner Join


Последнее обновление: 22.05.2018

В прошлой теме было рассмотрено неявное соединение таблиц с помощью простой выборки
путем сведения данных. Но, как правило, более распространенный подход соединения
данных из разных таблиц представляет применение оператора JOIN. Общий формальный
синтаксис применения оператора INNER JOIN:

SELECT столбцы
FROM таблица1
[INNER] JOIN таблица2
ON условие1
[[INNER] JOIN таблица3
ON условие2]

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

Возьмем таблицы с данными из прошлой темы:


CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
63

ProductCount INT DEFAULT 0,


Price DECIMAL NOT NULL
);
CREATE TABLE Customers
(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL
);
CREATE TABLE Orders
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL REFERENCES Products(Id) ON DELETE CASCADE,
CustomerId INT NOT NULL REFERENCES Customers(Id) ON DELETE CASCADE,
CreatedAt DATE NOT NULL,
ProductCount INT DEFAULT 1,
Price DECIMAL NOT NULL
);

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


SELECT Orders.CreatedAt, Orders.ProductCount, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId;

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


столбцов для выборки указывается их полное имя вместе с именем таблицы, например,
"Orders.ProductCount".

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


SELECT O.CreatedAt, O.ProductCount, P.ProductName
FROM Orders AS O
JOIN Products AS P
ON P.Id = O.ProductId;

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

SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName


FROM Orders
JOIN Products ON Products.Id = Orders.ProductId
JOIN Customers ON Customers.Id=Orders.CustomerId;
64

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


или ее сортировки:

SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName


FROM Orders
JOIN Products ON Products.Id = Orders.ProductId
JOIN Customers ON Customers.Id=Orders.CustomerId
WHERE Products.Price > 45000
ORDER BY Customers.FirstName;

Условия после ключевого слова ON могут быть более сложными по составу:


SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId AND
Products.Manufacturer='Apple'
JOIN Customers ON Customers.Id=Orders.CustomerId
ORDER BY Customers.FirstName;

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

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

НазадСодержаниеВперед

5.3 Outer Join


Последнее обновление: 22.05.2018

В предыдущей теме рассматривля Inner Join или внутреннее соединение таблиц. Но также в
MySQL мы можем использовать и так называемое внешнее соединение или Outer Join. В
отличие от Inner Join внешнее соединение возвращает все строки одной или двух таблиц,
которые участвуют в соединении.

Outer Join имеет следующий формальный синтаксис:


SELECT столбцы
FROM таблица1
{LEFT|RIGHT} [OUTER] JOIN таблица2 ON условие1
[{LEFT|RIGHT} [OUTER] JOIN таблица3 ON условие2]...
65

Перед оператором JOIN указывается одно из ключевых слов LEFT или RIGHT, которые
определяют тип соединения:

• LEFT:
выборка будет содержать все строки из первой или левой таблицы •
RIGHT: выборка будет содержать все строки из второй или правой таблицы

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

Например, соединим таблицы Orders и Customers:


SELECT FirstName, CreatedAt, ProductCount, Price, ProductId
FROM Orders LEFT JOIN Customers
ON Orders.CustomerId = Customers.Id

Таблица Orders является первой или левой таблицей, а таблица Customers - правой таблицей.
Поэтому, так как здесь используется выборка по левой таблице, то вначале будут выбираться
все строки из Orders, а затем к ним по условию Orders.CustomerId = Customers.Id будут
добавляться связанные строки из Customers.

По вышеприведенному результату может показаться, что левостороннее соединение


аналогично INNER Join, но это не так. Inner Join объединяет строки из двух таблиц при
соответствии условию. Если одна из таблиц содержит строки, которые не соответствуют
этому условию, то данные строки не включаются в выходную выборку. Left Join выбирает
все строки первой таблицы и затем присоединяет к ним строки правой таблицы. К примеру,
возьмем таблицу Customers и добавим к покупателям информацию об их заказах:
#INNER JOIN
SELECT FirstName, CreatedAt, ProductCount, Price
FROM Customers JOIN Orders
ON Orders.CustomerId = Customers.Id;

#LEFT JOIN
SELECT FirstName, CreatedAt, ProductCount, Price
FROM Customers LEFT JOIN Orders
ON Orders.CustomerId = Customers.Id;
66

В случае с LEFT JOIN MySQL выбирает сначала всех покупателей из таблицы Customers,
затем сопоставляет их с заказами из таблицы Orders через условие Orders.CustomerId =
Customers.Id. Однако не у всех покупателей есть заказы. В этом случае покупателю для
соответствующих столбцов устанавливаются значения NULL.
Изменим в примере выше тип соединения для OUTER JOIN с левостороннего на
правостороннее:

SELECT FirstName, CreatedAt, ProductCount, Price


FROM Customers RIGHT JOIN Orders
ON Orders.CustomerId = Customers.Id;

Теперь будут выбираться все строки из Orders (из правой таблицы), а к ним уже будет
присоединяться связанные по условию строки из таблицы Customers:

Используем левостороннее соединение для добавления к заказам информации о


пользователях и товарах:
SELECT Customers.FirstName, Orders.CreatedAt,
67

Products.ProductName, Products.Manufacturer
FROM Orders
LEFT JOIN Customers ON Orders.CustomerId = Customers.Id
LEFT JOIN Products ON Orders.ProductId = Products.Id;

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


Например, выберем все заказы с информацией о клиентах и товарах по тем товарам, у
которых цена меньше 45000, и отсортируем по дате заказа:
SELECT Customers.FirstName, Orders.CreatedAt,
Products.ProductName, Products.Manufacturer
FROM Orders
LEFT JOIN Customers ON Orders.CustomerId = Customers.Id
LEFT JOIN Products ON Orders.ProductId = Products.Id
WHERE Products.Price > 45000
ORDER BY Orders.CreatedAt;

Или выберем всех пользователей из Customers, у которых нет заказов в таблице Orders:
SELECT FirstName FROM Customers
LEFT JOIN Orders ON Customers.Id = Orders.CustomerId
WHERE Orders.CustomerId IS NULL;

Также можно комбинировать Inner Join и Outer Join:


SELECT Customers.FirstName, Orders.CreatedAt,
Products.ProductName, Products.Manufacturer
FROM Orders
JOIN Products ON Orders.ProductId = Products.Id AND Products.Price > 45000
LEFT JOIN Customers ON Orders.CustomerId = Customers.Id
ORDER BY Orders.CreatedAt;

Вначале по условию к таблице Orders через Inner Join присоединяется связанная информация
из Products, затем через Outer Join добавляется информация из таблицы Customers.

НазадСодержаниеВперед

5.4 UNION
Последнее обновление: 22.05.2018

Оператор UNION позволяет объединить две однотипных выборки. Эти выборки могут быть
из разных таблиц или из одной и той же таблицы. Формальный синтаксис объединения:
68

SELECT_выражение1
UNION [ALL] SELECT_выражение2
[UNION [ALL] SELECT_выражениеN]

Например, пусть в базе данных будут две отдельные таблицы для клиентов банка (таблица
Customers) и для сотрудников банка (таблица Employees):

CREATE TABLE Customers


(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
AccountSum DECIMAL
);
CREATE TABLE Employees
(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL
);

INSERT INTO Customers(FirstName, LastName, AccountSum)


VALUES
('Tom', 'Smith', 2000),
('Sam', 'Brown', 3000),
('Mark', 'Adams', 2500),
('Paul', 'Ins', 4200),
('John', 'Smith', 2800),
('Tim', 'Cook', 2800);

INSERT INTO Employees(FirstName, LastName)


VALUES
('Homer', 'Simpson'),
('Tom', 'Smith'),
('Mark', 'Adams'),
('Nick', 'Svensson');

Здесь мы можем заметить, что обе таблицы, несмотря на наличие различных данных, могут
характеризоваться двумя общими атрибутами - именем (FirstName) и фамилией (LastName).
Выберем сразу всех клиентов банка и его сотрудников из обеих таблиц:
SELECT FirstName, LastName
FROM Customers
UNION SELECT FirstName, LastName FROM Employees;

Здесь из первой таблицы выбираются два значения - имя и фамилия клиента. Из второй
таблицы Employees также выбираются два значения - имя и фамилия сотрудников. То есть
при объединении количество выбираемых столбцов и их тип совпадают для обеих
выборок.
69

При этом названия столбцов объединенной выборки будут совпадать с названия столбцов
первой выборки. И если мы захотим при этом еще произвести сортировку, то в выражениях
ORDER BY необходимо ориентироваться именно на названия столбцов первой выборки:
SELECT FirstName AS FName, LastName
FROM Customers
UNION SELECT FirstName, LastName
FROM Employees
ORDER BY FName DESC;

В данном случае каждая выборка имеет по столбцу FName из первой выборки. Тем не менее
при сортировке будет учитываться и значение столбца FirstName из второй выборки:

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

SELECT FirstName, LastName, AccountSum


FROM Customers
UNION SELECT FirstName, LastName
FROM Employees;

Если оба объединяемых набора содержат в строках идентичные значения, то при


объединении повторяющиеся строки удаляются. Например, в случае с таблицами Customers
и Employees сотрудники банка могут быть одновременно его клиентами и содержаться в
70

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

SELECT FirstName, LastName


FROM Customers
UNION ALL SELECT FirstName, LastName
FROM Employees
ORDER BY FirstName;

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


суммы на счете клиента нам надо начислять ему определенные проценты:

SELECT FirstName, LastName, AccountSum + AccountSum * 0.1 AS TotalSum


FROM Customers WHERE AccountSum < 3000
UNION SELECT FirstName, LastName, AccountSum + AccountSum * 0.3 AS TotalSum
FROM Customers WHERE AccountSum >= 3000;

В данном случае если сумма меньше 3000, то начисляются проценты в размере 10% от
суммы на счете. Если на счете больше 3000, то проценты увеличиваются до 30%.
71

НазадСодержаниеВперед

Глава 6. Встроенные функции


6.1 Функции для работы со строками
Последнее обновление: 26.05.2018

Для работы со строка в MySQL определен ряд встроенных функций:

• CONCAT: объединяет строки. В качестве параметра принимает от 2-х и более строк,


которые надо соединить:
SELECT CONCAT('Tom', ' ', 'Smith') -- Tom Smith

При этом в функцию можно передавать не только непосредственно строки, но и


числа, даты - они будут преобразовываться в строки и также объединяться.

• CONCAT_WS: также объединяет строки, но в качестве первого параметра принимает


разделитель, который будет соединять строки:

SELECT CONCAT_WS(' ', 'Tom', 'Smith', 'Age:', 34) -- Tom Smith Age: 34

• LENGTH:возвращает количество символов в строке. В качестве параметра в


функцию передается строка, для которой надо найти длину:
SELECT LENGTH('Tom Smith') -- 9

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


строку:

SELECT LTRIM(' Apple')

• RTRIM: удаляет конечные пробелы из строки. В качестве параметра принимает


строку:

SELECT RTRIM(' Apple ')

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


принимает строку:
SELECT TRIM(' Tom Smith ')

С помощью дополнительного оператора можно задать где именно удалить пробелы:


BOTH (в начале и в конце), TRAILING (только в конце), LEADING (только в начале):

SELECT TRIM(BOTH FROM ' Tom Smith ')

• LOCATE(find, search [, start]): возвращает позицию первого вхождения подстроки find в


строку search. Дополнительный параметр start позволяет установить позицию в
строке search, с которой начинается поиск подстроки find. Если подстрока search не
найдена, то возвращается 0:
• SELECT LOCATE('om', 'Tom Smith'); -- 2
• SELECT LOCATE('m', 'Tom Smith'); -- 3
• SELECT LOCATE('m', 'Tom Smith', 4); -- 6
• SELECT LOCATE('mig', 'Tom Smith'); -- 0
72

• LEFT:вырезает с начала строки определенное количество символов. Первый


параметр функции - строка, а второй - количество символов, которые надо вырезать
сначала строки:

SELECT LEFT('Apple', 3) -- App

• RIGHT:вырезает с конца строки определенное количество символов. Первый


параметр функции - строка, а второй - количество символов, которые надо вырезать
сначала строки:
SELECT RIGHT('Apple', 3) -- ple

• SUBSTRING(str, start [, length]): вырезает из строки str подстроку, начиная с позиции


start. Третий необязательный параметр передает количество вырезаемых символов: •
SELECT SUBSTRING('Galaxy S8 Plus', 8), -- S8 Plus • (SELECT SUBSTRING('Galaxy S8
Plus', 8, 2) ); -- S8
• SUBSTRING_INDEX(str, delimiter, count): вырезает из строки str подстроку. Параметр
delimiter определяет разделитель внутри строки. А параметр count определяет, до какого
вхождения разделителя надо вырезать подстроку. Если count положительный, то
подстрока вырезается с начала, если count отрицательный, то с конца строки str:
• SELECT SUBSTRING_INDEX('Galaxy S8 Plus', ' ', 1), -- Galaxy
• (SELECT SUBSTRING_INDEX('Galaxy S8 Plus', ' ', 2) ), -- Galaxy S8
• (SELECT SUBSTRING_INDEX('Galaxy S8 Plus', ' ', -2) ); -- S8 Plus
• REPLACE(search, find, replace): заменяет в строке find подстроку search на
подстроку
replace. Первый параметр функции - строка, второй - подстрока, которую надо
заменить, а третий - подстрока, на которую надо заменить:
SELECT REPLACE('Galaxy S8 Plus', 'S8 Plus', 'Note 8') -- Galaxy Note 8

• INSERT(str,start, length, insert): вставляет в строку str, заменяя length символов с


позиции start подстрокой insert. Первый параметр функции - строка, второй - позиция,
с которой надо заменить, третий - сколько символов с позиции start надо заменить
вставляемой подстрокой, четвертый параметр - вставляемая подстрока:

SELECT INSERT('Galaxy S9', 8, 3, 'Note 9'); -- Galaxy Note 9 •

REVERSE: переворачивает строку наоборот:

SELECT REVERSE('123456789') -- 987654321

• LOWER: переводит строку в нижний регистр:


SELECT LOWER('Apple') -- apple
• UPPER: переводит строку в верхний регистр
SELECT UPPER('Apple') -- APPLE

• SPACE:возвращает строку, которая содержит определенное количество пробелов •


REPEATE(str, count): возвращает строку, которая содержит определенное количество
повторов подстроки str. Количество повторов задается через параметр count.

SELECT REPEAT('ab', 5); -- ababababab


73

• LPAD(str,length, pad): добавляет слева от строки str некоторое количество символов,


которые определены в параметре pad. Количество добавляемых символов
вычисляется по формуле length - LENGTH(str). Если параметр length меньше длины
строки str, то эта строка усекается до length символов.
SELECT LPAD('Tom Smith', 13, '*'); -- ****Tom Smith

• RPAD(str,length, pad): добавляет справа от строки str некоторое количество символов,


которые определены в параметре pad. Количество добавляемых символов
вычисляется по формуле length - LENGTH(str). Если параметр length меньше длины
строки str, то эта строка усекается до length символов.
SELECT RPAD('Tom Smith', 13, '*'); -- Tom Smith****

Например, возьмем таблицу:


CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);

И при извлечении данных применим строковые функции:


SELECT UPPER(LEFT(Manufacturer,2)) AS Abbreviation,
CONCAT(ProductName, ' - ', Manufacturer) AS FullProdName
FROM Products
ORDER BY Abbreviation

НазадСодержаниеВперед
6.2 Функции для работы с числами
Последнее обновление: 26.05.2018

Для работы с числовыми данными MySQL предоставляет ряд функций:


74

• ROUND: округляет число. В качестве первого параметра передается число. Второй


параметр указывает на длину. Если длина представляет положительное число, то оно
указывает, до какой цифры после запятой идет округление. Если длина представляет
отрицательное число, то оно указывает, до какой цифры с конца числа до запятой
идет округление
• SELECT ROUND(1342.345, 2), -- 1342.35
• (SELECT ROUND(1342.345, -2)); -- 1300;
• TRUNCATE: оставляет в дробной части определенное количество символов •
SELECT TRUNCATE(1342.345, 2); -- 1342.34
• ABS: возвращает абсолютное значение числа.

SELECT ABS(-123) -- 123

• CEILING:возвращает наименьшее целое число, которое больше или равно текущему


значению.
• SELECT CEILING(-123.45), -- -123
• (SELECT CEILING(123.45)); -- 124
• FLOOR: возвращает наибольшее целое число, которое меньше или равно текущему
значению.
• SELECT FLOOR(-123.45), -- -124
• (SELECT FLOOR(123.45)); -- 123
• POWER: возводит число в определенную степень.
• SELECT POWER(5, 2), -- 25
• (SELECT POWER(5, 3)); -- 125
• SQRT: получает квадратный корень числа.
SELECT SQRT(225); -- 15

• SIGN:возвращает -1, если число меньше 0, и возвращает 1, если число больше 0. Если
число равно 0, то возвращает 0.
• SELECT SIGN(-5), -- -1
• (SELECT SIGN(7)); -- 1
• RAND: генерирует случайное число с плавающей точкой в диапазоне от 0 до 1. •
SELECT RAND(); -- 0.707365088352935
• SELECT RAND(); -- 0.173808327956812

Например, возьмем таблицу:


CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);

Округлим произведение цены товара на количество этого товара:


SELECT ProductName, ROUND(Price * ProductCount, 2)
FROM Products;

НазадСодержаниеВперед

6.3 Функции для работы с датами и


временем Последнее обновление: 26.05.2018
75

MySQL имеет ряд встроенных функций для работы с датами и

временем. Получение даты и времени

• Функции NOW(), SYSDATE(), CURRENT_TIMESTAMP() возвращают текущую


локальную дату и время на основе системных часов в виде объекта datetime. Все три
функции возвращают одинаковый результат
• SELECT NOW(); -- 2018-05-25 21:34:55 • SELECT SYSDATE(); -- 2018-05-
25 21:34:55 • SELECT CURRENT_TIMESTAMP(); -- 2018-05-25 21:32:55
• Функции CURDATE и CURRENT_DATE возвращают текущую локальную дату в
виде объекта date:
• SELECT CURRENT_DATE(); -- 2018-05-25
• SELECT CURDATE(); -- 2018-05-25
• Функции CURTIME и CURRENT_TIME возвращают текущее время в виде объекта
time:
• SELECT CURRENT_TIME(); -- 20:47:45
• SELECT CURTIME(); -- 20:47:45
• UTC_DATE возвращает текущую локальную дату относительно GMT
SELECT UTC_DATE(); -- 2018-05-25

• UTC_TIME возвращает текущее локальное время относительно GMT


SELECT UTC_TIME(); -- 17:47:45
Парсинг даты и времени

• DAYOFMONTH(date) возвращает день месяца в виде числового значения •


DAYOFWEEK(date) возвращает день недели в виде числового значения •
DAYOFYEAR(date) возвращает номер дня в году
• MONTH(date) возвращает месяц даты
• YEAR(date) возвращает год из даты
• QUARTER(date) возвращает номер квартала года
• WEEK(date [, first]) возвращает номер недели года. Необязательный параметр позволяет
задать стартовый день недели. Если этот параметр равен 1, то первым днем считается
понедельник, иначе воскресенье
• LAST_DAY(date) возвращает последний день месяца в виде даты
• DAYNAME(date) возвращает название дня недели
• MONTHNAME(date) возвращает название текущего месяца
• HOUR(time) возвращает час времени
• MINUTE(time) возвращает минуту времени
• SECOND(time) возвращает секунду времени

Примеры функций:

Функция Результат
DAYOFMONTH('2018-05-25') 25
DAYOFWEEK('2018-05-25') 6
DAYOFYEAR('2018-05-25') 145
MONTH('2018-05-25') 5
YEAR('2018-05-25') 2018
QUARTER('2018-05-25') 2
WEEK('2018-05-25', 1) 21
LAST_DAY('2018-05-25') 2018-05-31
76

DAYNAME('2018-05-25') Friday
MONTHNAME('2018-05-25') May
HOUR('21:25:54') 21
MINUTE('21:25:54') 25
SECOND('21:25:54') 54
Функция EXTRACT

Функция EXTRACT извлекает из даты и времени какой-то определенный компонент. Ее


формальный синтаксис:

EXTRACT(unit FROM datetime)

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

• SECOND (секунды)
• MINUTE (минуты)
• HOUR (час)
• DAY (день)
• MONTH (месяц)
• YEAR (год)
• MINUTE_SECOND (минуты и секунды)
• HOUR_MINUTE (часы и минуты)
• DAY_HOUR (день и часы)
• YEAR_MONTH (год и месяц)
• HOUR_SECOND (часы, минуты и секунды)
• DAY_MINUTE (день, часы и минуты)
• DAY_SECOND (день, часы, минуты и секунды)

Примеры вызова функции:

Вызов Результат EXTRACT( SECOND FROM '2018-05-25 21:25:54') 54


EXTRACT( MINUTE FROM '2018-05-25 21:25:54') 25
EXTRACT( HOUR FROM '2018-05-25 21:25:54') 21
EXTRACT( DAY FROM '2018-05-25 21:25:54') 25
EXTRACT( MONTH FROM '2018-05-25 21:25:54') 5
EXTRACT( YEAR FROM '2018-05-25 21:25:54') 2018
EXTRACT( MINUTE_SECOND FROM '2018-05-25 21:25:54') 2554
EXTRACT( DAY_HOUR FROM '2018-05-25 21:25:54') 2521
EXTRACT( YEAR_MONTH FROM '2018-05-25 21:25:54') 201805
EXTRACT( HOUR_SECOND FROM '2018-05-25 21:25:54') 212554
EXTRACT( DAY_MINUTE FROM '2018-05-25 21:25:54') 252125
EXTRACT( DAY_SECOND FROM '2018-05-25 21:25:54') 25212554
Функции для манипуляции с датами

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

• DATE_ADD(date,INTERVAL expression unit) возвращает объект DATE или


DATETIME, который является результатом сложения даты date с определенным
77
временным интервалом. Интервал задается с помощью выражения INTERVAL
expression unit, где INTERVAL предоставляет ключевое слово, expression -
количество добавляемых к дате единиц, а unit - тип единиц (часы, дни и т.д.)
Параметр unit может иметь те же значения, что и в функции EXTRACT, то есть
DAY, HOUR и т.д.
• DATE_SUB(date, INTERVAL expression unit) возвращает объект DATE или
DATETIME, который является результатом вычитания из даты date определенного
временного интервала
• DATEDIFF(date1, date2) возвращает разницу в днях между датами date1 и date2 •
TO_DAYS(date) возвращает количество дней с 0-го года
• TIME_TO_SEC(time) возвращает количество секунд, прошедших с момента полуночи

Примеры применения:

Вызов Результат
DATE_ADD('2018-05-25', INTERVAL 1 DAY) 2018-05-26
DATE_ADD('2018-05-25', INTERVAL 3 MONTH) 2018-08-25
DATE_ADD('2018-05-25 21:31:27', INTERVAL 4 HOUR) 2018-05-26 01:31:27
DATE_SUB('2018-05-25', INTERVAL 4 DAY) 2018-05-21
DATEDIFF('2018-05-25', '2018-05-27') -2
DATEDIFF('2018-05-25', '2018-05-21') 4
DATEDIFF('2018-05-25', '2018-03-21') 65
TO_DAYS('2018-05-25') 737204
TIME_TO_SEC('10:00') 36000
Форматирование дат и времени

• DATE_FORMAT(date, format) возвращает объект DATE или DATETIME,


отформатированный с помощью шаблона format
• TIME_FORMAT(date, format) возвращает объект TIME или DATETIME,
отформатированный с помощью шаблона format

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

• %m: месяц в числовом формате 01..12


• %с: месяц в числовом формате 1..12
• %M: название месяца (January...December)
• %b: аббревиатура месяца (Jan...Dec)
• %d: день месяца в числовом формате 00..31
• %e: день месяца в числовом формате 0..31
• %D: номер дня месяца с суффиксом (1st, 2nd, 3rd...)
• %y: год в виде двух чисел
• %Y: год в виде четырех чисел
• %W: название дня недели (Sunday...Saturday)
• %a: аббревиатура дня недели (Sun...Sat)
• %H: час в формате 00..23
• %k: час в формате 0..23
• %h: час в формате 01..12
• %l: час в формате 1..12
• %i: минуты в формате 00..59
• %r: время в 12-ти часовом формате (hh:mm:ss AM или PM)
• %T: время в 24-ти часовом формате (hh:mm:ss)
78
• %S: секунды в формате 00..59
• %p: AM или PM

Примеры применения:

Вызов Результат
DATE_FORMAT('2018-05-25', '%d/%m/%y') 25/05/18
DATE_FORMAT('2018-05-25 21:25:54', '%d %M %Y') 25 May 2018
DATE_FORMAT('2018-05-25 21:25:54', '%r') 09:25:54 PM
TIME_FORMAT('2018-05-25 21:25:54', '%H:%i:%S') 21:25:24
TIME_FORMAT('21:25:54', '%k:%i') 21:25

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

SELECT * FROM Orders


WHERE DATEDIFF(CURDATE(), CreatedAt) = 5;

НазадСодержаниеВперед

6.4 Функции CASE, IF, IFNULL,


COALESCE Последнее обновление: 26.05.2018
CASE

Функция CASE проверяет истинность набора условий и в зависимости от результата


проверки может возвращать тот или иной результат. Эта функция принимает следующую
форму:

CASE
WHEN условие_1 THEN результат_1
WHEN условие_2 THEN результат_2
.................................
WHEN условие_N THEN условие_N
[ELSE альтернативный_результат]
END

Возьмем для примера следующую таблицу Products:


CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
79

Manufacturer VARCHAR(20) NOT NULL,


ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);

Выполним запрос к этой таблице и используем функцию CASE:


SELECT ProductName, ProductCount,
CASE
WHEN ProductCount = 1
THEN 'Товар заканчивается'
WHEN ProductCount = 2
THEN 'Мало товара'
WHEN ProductCount = 3
THEN 'Есть в наличии'
ELSE 'Много товара'
END AS Category
FROM Products;

Функция IF

Функция IF в зависимости от результата условного выражения возвращает одно из двух


значений. Общая форма функции выглядит следующим образом:

IF(условие, значение_1, значение_2)

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


значение, иначе возвращается второе значение. Например:

SELECT ProductName, Manufacturer,


IF(ProductCount > 3, 'Много товара', 'Мало товара')
FROM Products;
80
IFNULL
Функция IFNULL проверяет значение некоторого выражения. Если оно равно NULL, то
функция возвращает значение, которое передается в качестве второго параметра:

IFNULL(выражение, значение)

Например, возьмем следующую таблицу


CREATE TABLE Clients
(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
Phone VARCHAR(20) NULL,
Email VARCHAR(20) NULL
);

INSERT INTO Clients (FirstName, LastName, Phone, Email)


VALUES ('Tom', 'Smith', '+36436734', NULL),
('Bob', 'Simpson', NULL, NULL);

И применим при получении данных функцию IFNULL:


SELECT FirstName, LastName,
IFNULL(Phone, 'не определено') AS Phone,
IFNULL(Email, 'неизвестно') AS Email
FROM Clients;

Вам также может понравиться