Секция FROM, логическое связывание таблиц
Перечень таблиц, из которых производится выборка данных, указывается
в секции FROM. Выборка возможна как из одной таблицы, так и из нескольких логически взаимосвязанных. Логическая взаимосвязь осуществляется с помощью подсекции JOIN. На каждую логическую связь пишется отдельная подсекция. Внутри подсекции указывается условие связи двух таблиц (обычно по условию равенства первичных и вторичных ключей). Примеры для модели данных Сотрудники-Отделы-Города:
Employees | ||||
TabNum | Name | Position | DeptNum | Salary |
Иванов | Начальник | |||
Петров | Инж. | |||
Сидоров | Менеджер |
Departments | ||
DeptNum | City | Name |
Производственный отдел | ||
Отдел продаж |
Cities | |
City | Name |
Минск | |
Москва |
SELECTEmployees.TabNum, Employees.Name,Departments.Name
FROMEmployees
JOINDepartmentsONEmployees.DeptNum =
Departments.DeptNum
Результат запроса будет выглядеть следующим образом:
Иванов | Производственный отдел | |
Петров | Производственный отдел | |
Сидоров | Отдел продаж |
SELECTEmployees.TabNum, Employees.Name, Departments.Name, Cities.Name
FROMEmployees
JOINDepartmentsONEmployees.DeptNum = Departments.DeptNum
JOINCitiesONDepartments.City = Cities.City
Результат запроса будет выглядеть следующим образом:
Иванов | Производственный отдел | Минск | |
Петров | Производственный отдел | Минск | |
Сидоров | Отдел продаж | Москва |
Пример связывания таблиц по нескольким полям:
SELECTTable1.Field1, Table2.Field2
FROM Table1
JOINTable2
ONTable2.ID1 =Table1.ID1
ANDTable2.ID2 =Table1.ID2
AND ….
Существует несколько типов связывания:
Тип | Результат |
JOIN | Внутреннее соединение. В результирующем наборе присутствуют только записи, значения связанных полей в которых совпадают |
LEFT JOIN | Левое внешнее соединение. В результирующем наборе присутствуют все записи из Table1 и соответствующие им записи из Table2. Если соответствия нет, поля из Table2 будут пустыми |
RIGHT JOIN | Правое внешнее соединение. В результирующем наборе присутствуют все записи из Table2 и соответствующие им записи из Table1. Если соответствия нет, поля из Table1 будут пустыми |
FULL JOIN | Полное внешнее соединение. Комбинация двух предыдущих. В результирующем наборе присутствуют все записи из Table1 и соответствующие им записи из Table2. Если соответствия нет – поля из Table2 будут пустыми. Записи из Table2, которым не нашлось пары в Table1, тоже будут присутствовать в результирующем наборе. В этом случае поля из Table1 будут пустыми. |
CROSS JOIN | Cartesian product. Результирующий набор содержит все варианты комбинации строк из Table1 и Table2. Условие соединения при этом не указывается. |
Проиллюстрируем каждый тип примерами. Модель данных:
Table1 | Table2 | |||
Key1 | Field1 | Key2 | Field2 | |
A | AAA | |||
В | BBB | |||
C | CCC | |||
DDD |
SELECT Table1.Field1, Table2.Field2
FROM Table1
JOIN Table2 ON Table1.Key1 = Table2.Key2
Результат:
A | AAA |
B | BBB |
B | CCC |
SELECT Table1.Field1, Table2.Field2
FROM Table1
LEFT JOIN Table2 ON Table1.Key1 = Table2.Key2
Результат:
A | AAA |
B | BBB |
B | CCC |
C |
SELECT Table1.Field1, Table2.Field2
FROM Table1
RIGHT JOIN Table2 ON Table1.Key1 = Table2.Key2
Результат:
A | AAA |
B | BBB |
B | CCC |
DDD |
SELECT Table1.Field1, Table2.Field2
FROM Table1
FULL JOIN Table2 ON Table1.Key1 = Table2.Key2
Результат:
A | AAA |
B | BBB |
B | CCC |
DDD | |
C |
SELECT Table1.Field1, Table2.Field2
FROM Table1
CROSS JOIN Table2
Результат:
A | AAA |
A | BBB |
A | CCC |
A | DDD |
B | AAA |
B | BBB |
B | CCC |
B | DDD |
C | AAA |
C | BBB |
C | CCC |
C | DDD |
Секция WHERE
Для фильтрации результатов выполнения запроса можно использовать условия выборки в секции WHERE. В общем виде синтаксис WHERE выглядит следующим образом:
WHERE[NOT] <условие1>[AND |OR<условие2>]
Условие представляет собой конструкцию вида:
<столбец таблицы, константа или выражение>
<оператор сравнения> <столбец таблицы, константа или выражение>
или
IS [NOT] NULL
или
[NOT] LIKE <шаблон>
или
[NOT] IN (<список значений>)
или
[NOT] BETWEEN <нижняя граница> AND <верхняя граница>
Операторы сравнения:
< | Меньше |
<= | Меньше либо равно |
<> | Не равно |
> | Больше |
>= | Больше либо равно |
= | Равно |
Примеры запросов с операторами сравнения:
SELECT * FROM Table WHERE Field > 100
SELECT * FROM Table WHERE Field1 <= (Field2 + 25)
Выражение IS [NOT] NULL проверяет данные на [не]пустые значения:
SELECT * FROM Table WHERE Field IS NOT NULL
SELECT * FROM Table WHERE Field IS NULL
Необходимо отметить, что язык SQL, в отличие от языков программирования, имеет встроенные средства поддержки факта отсутствия каких-либо данных. Осуществляется это с помощью NULL-концепции. NULL не является каким-то фиксированным значением, хранящимся в поле записи вместо реальных данных. Значение NULL не имеет определенного типа. NULL – это индикатор, говорящий пользователю (и SQL) о том, что данные в поле записи отсутствуют. Поэтому его нельзя использовать в операциях сравнения. Для проверки факта наличия-отсутствия данных в SQL введены специальные выражения.
Выражение [NOT] LIKE используется при проверке текстовых данных на [не]соответствие заданному шаблону. Символ ‘%’ (процент) в шаблоне заменяет собой любую последовательность символов, а символ ‘_’ (подчеркивание) – один любой символ.
SELECT * FROM Employees WHERE Name LIKE ‘Иван%’
Попадающие под заданное условие фамилии: Иванов
SELECT * FROM Employees WHERE Name LIKE ‘__д%’
Попадающие под заданное условие фамилии: Сидоров
Выражение [NOT] IN проверяет значения на [не]вхождение в определенный список:
SELECT * FROM Employees WHERE Position IN (‘Начальник’, ‘Менеджер’)
Выражение [NOT] BETWEEN проверяет значения на [не]попадание в некоторый диапазон:
SELECT * FROM Employees WHERE Salary BETWEEN 200 AND 500
Этот запрос вернет список работников, зарплата которых больше либо равна 200 у.е. и меньше либо равна 500 у.е.
Несколько условий поиска могут комбинироваться посредством логических операторов AND, OR или NOT:
SELECT *
FROM Employees
WHERE Position IN (‘Начальник’, ‘Менеджер’)
AND Salary BETWEEN 200 AND 500
SELECT *
FROM Employees
WHERE (Position = ‘Начальник’ OR Position =
‘Менеджер’)
AND Salary BETWEEN 200 AND 500
SELECT *
FROM Employees
WHERE NOT (Position = ‘Начальник’ OR Position =
‘Менеджер’)
Секция ORDER BY
Необязательная секция ORDER BY в команде SELECT предназначена для сортировки строк результирующего набора данных. Формат этой секции в общем виде выглядит так:
ORDER BY Field1 [ASC | DESC] [, Field2 [ASC | DESC] ] [, …]
Ключевое слово ASC предписывает производить сортировку по возрастанию, а DESC – по убыванию. Если ASC и DESC отсутствуют, по умолчанию подразумевается ASC. Например, выберем записи о начальниках и отсортируем результат
в порядке убывания размера зарплат:
SELECT *
FROM Employees
WHERE Position = ‘Начальник’
ORDER BY Salary DESC
Следующий запрос отсортирует сотрудников по отделам (в порядке возрастания номера отдела) и по размеру зарплат внутри каждого отдела (в порядке убывания зарплаты):
SELECT *
FROM Employees
ORDER BY DeptNum ASC, Salary DESC
Ключевое слово ASC можно опустить, ибо оно действует по умолчанию:
SELECT *
FROM Employees
ORDER BY DeptNum, Salary DESC
Групповые функции
Если нас не интересуют строки таблицы как таковые, а интересуют некоторые итоги, мы можем использовать в процессе выборки колонок таблиц групповые функции. Основные групповые функции представлены ниже:
Функция | Описание |
SUM(Field) | Вычисляет сумму по указанной колонке |
MIN(Field) | Вычисляет минимальное значение по указанной колонке |
MAX(Field) | Вычисляет максимальное значение по указанной колонке |
AVG(Field) | Вычисляет среднее значение по указанной колонке |
COUNT(*) | Вычисляет количество строк в результирующей выборке |
COUNT(Field) | Вычисляет количество не пустых значений в колонке |
Например, чтобы узнать максимальную зарплату, получаемую сотрудниками в организации, можно выполнить запрос вида:
SELECT MAX(SALARY)
FROM Employees
Общее количество записей в таблице вернет запрос вида:
SELECT COUNT(*)
FROM Employees
Секция GROUP BY
По умолчанию группой, на которой вычисляется групповая функция, является вся результирующая выборка. Если мы нуждаемся в вычислении промежуточных итогов, мы можем разбить итоговую выборку на подгруппы с помощью необязательной секции GROUP BY:
GROUP BY Field1 [, Field2] [, …]
Например, подсчитаем максимальную зарплату по отделам организации:
SELECT DeptNum, MAX(SALARY)
FROM Employees
GROUP BY DeptNum
В этом случае функция MAX будет считаться отдельно для всех записей с одинаковым значением поля DeptNum.
Секция HAVING
На промежуточные итоги может быть наложен дополнительный фильтр посредством секции HAVING. В нижеприведенном примере в результат попадут только отделы, максимальная зарплата в которых превышает 1000 у.е.:
SELECT DeptNum, MAX(SALARY)
FROM Employees
GROUP BY DeptNum
HAVING MAX(SALARY) > 1000
Важно понимать, что секции HAVING и WHERE взаимно дополняют друг друга. Сначала с помощью ограничений WHERE формируется итоговая выборка, затем выполняется разбивка на группы по значениям полей, заданных в GROUP BY. Далее по каждой группе вычисляется групповая функция и в заключение накладывается условие HAVING.
Изменение данных
Под изменением данных понимаются следующие операции:
- вставка новых строк в таблицу;
- изменение существующих строк;
- удаление существующих строк.
Команда INSERT
Добавление новых записей в таблицу осуществляется посредством команды INSERT. Она имеет следующий синтаксис:
INSERT INTO <имя таблицы> [(<список имен колонок>)]
VALUES(<список констант>)
Например, для внесения сведений о новом работнике необходимо выполнить следующую команду:
INSERT INTO Employees(TabNum, Name, Position, DeptNum,
Salary)
VALUES(45, ‘Сергеев’, ‘Старший менеджер’, 15, 850)
После выполнения команды таблица Employees будет выглядеть следующим образом:
Employees | ||||
TabNum | Name | Position | DeptNum | Salary |
Иванов | Начальник | |||
Петров | Инженер | |||
Сидоров | Менеджер | |||
Сергеев | Старший менеджер |
Если какая-либо колонка в списке будет опущена при вставке, в соответствующее поле записи автоматически будет занесено пустое значение (NULL):
INSERT INTO Employees(TabNum, Name, DeptNum, Salary)
VALUES(45, ‘Сергеев’, 15, 850)
После выполнения команды таблица Employees будет выглядеть следующим образом:
Employees | ||||
TabNum | Name | Position | DeptNum | Salary |
Иванов | Начальник | |||
Петров | Инженер | |||
Сидоров | Менеджер | |||
Сергеев |
Количество констант в секции VALUES всегда должно соответствовать количеству колонок. Список колонок в команде INSERT может быть опущен целиком. В этом случае список констант в секции VALUES должен точно соответствовать описанию колонок таблицы в словаре данных СУБД, иначе команда будет отвергнута ядром БД. Пример правильной команды:
INSERT INTO Employees VALUES(45, ‘Сергеев’,
‘Старший менеджер’, 15, 850)
Команда вида:
INSERT INTO Employees VALUES(45, ‘Сергеев’, 15, 850)
завершится ошибкой, так как количество констант не соответствует реальному количеству колонок в таблице.
В колонку можно в явном виде внести пустое значение посредством ключевого слова NULL. Последний запрос можно переписать следующим образом:
INSERT INTO Employees VALUES(45, ‘Сергеев’, NULL, 15, 850)
В этом случае команда вставки отработает корректно, и в поле Position будет внесено пустое значение. Очевидно, что к аналогичному результату приведет
и команда:
INSERT INTO Employees(TabNum, Name, Position, DeptNum,
Salary)
VALUES(45, ‘Сергеев’, NULL, 15, 850)
Кроме простого добавления новых записей, команда INSERT позволяет осуществлять пакетную перекачку данных из таблицы в таблицу. Синтаксис подобной команды следующий:
INSERT INTO <имя таблицы> [(<список имен колонок>)]
<команда SELECT>
Например:
INSERT INTO Table1(Field1, Field2)
SELECT Field3, (Field4 + 5) FROM Table2
Команда DELETE
Чтобы удалить ненужные записи из таблицы, следует использовать команду DELETE:
DELETE FROM <имя таблицы> [WHERE <условия поиска>]
Если опустить секцию условий поиска WHERE, из таблицы будут удалены все записи. Иначе – только записи, удовлетворяющие критериям поиска. Форматы секций WHERE команд SELECT и DELETE аналогичны.
Примеры команды DELETE:
DELETE FROM Employees
DELETE FROM Employees WHERE TabNum = 45
Команда UPDATE
Изменить ранее внесенные командой INSERT данные можно с помощью команды UPDATE:
UPDATE < имя таблицы>
SET <имя колонки> = <новое значение> , <имя колонки> =
<новое значение>, …
WHERE <условия поиска>]
Как и в случае команды DELETE, при отсутствии секции WHERE обновлены будут все строки таблицы. Иначе – только подходящие под заданные условия. Примеры:
UPDATE Employees SET Salary = Salary + 100
UPDATE Employees
SET Position = ‘Старший менеджер’, Salary = 1000
WHERE TabNum = 45 AND Position IS NULL