Перейти к основному содержимому

Справочник по SQL


Назначение

Базис: Операторы — оператор, операнд и приоритет в коде; полезно перед условиями в запросах и логикой селекторов.

Синтаксис, операторы, команды клиента и ограничения SQL. Учебный курс: раздел. Пошаговые примеры на схеме магазина — SQL — реальные кейсы.


Краткое пояснение

Полный список команд. Для старта с нуля удобнее компактные таблицы в учебных главах — порядок выполнения SELECT, конструкции чтения, агрегаты, типы JOIN, DDL/DML/TCL.


Полное API SQL (алфавитный указатель)

Ниже — расширенный список SQL-команд, операторов и функций с кратким смыслом. Это быстрый справочник, который удобно читать по ключевому слову.

A

  • AND — логическое И.
  • AS — псевдоним столбца/таблицы.
  • AVG — среднее арифметическое.
  • ABS — модуль числа.
  • ALTER TABLE — изменение структуры таблицы.
  • ADD COLUMN — добавление столбца.

B

  • BETWEEN — выбор значений из диапазона.

C

  • COUNT — подсчёт записей.
  • CASE — условный выбор значения.
  • COALESCE — первое не-NULL значение.
  • CEILING — округление вверх.
  • CONCAT — склейка строк.
  • CONCAT_WS — склейка строк с разделителем.
  • CHAR_LENGTH — длина строки в символах.
  • CURRENT_DATE — текущая дата.
  • CURRENT_TIME — текущее время.
  • CURDATE — дата сейчас (MySQL).
  • CURTIME — время сейчас (MySQL).
  • CURRENT_TIMESTAMP — текущий timestamp.
  • CROSS JOIN — декартово произведение.
  • CREATE DATABASE — создание БД.
  • CREATE TABLE — создание таблицы.
  • CREATE INDEX — создание индекса.
  • COMMIT — фиксация изменений транзакции.

D

  • DELETE — удаление записей.
  • DISTINCT — уникальные значения.
  • DAY — день из даты.
  • DAYOFMONTH — день месяца.
  • DATE — дата из datetime/timestamp.
  • DAYOFWEEK — день недели (номер).
  • DAYNAME — день недели (название).
  • DAYOFYEAR — номер дня в году.
  • DATE_FORMAT — форматирование даты.
  • DATE_ADD — сложение даты и интервала.
  • DATE_SUB — вычитание интервала из даты.
  • DATEDIFF — разница дат в днях.
  • DROP DATABASE — удаление БД.
  • DROP TABLE — удаление таблицы.
  • DROP COLUMN — удаление столбца.
  • DROP INDEX — удаление индекса.
  • DESCRIBE — структура таблицы.

E

  • EXISTS — проверка наличия строк в подзапросе.
  • ELT — строка по номеру из списка аргументов.
  • EXTRACT — извлечение части даты/времени.
  • EXPLAIN — план выполнения запроса.

F

  • FLOOR — округление вниз.
  • FIELD — номер значения в списке.
  • FIND_IN_SET — поиск в строковом списке.
  • FROM_DAYS — преобразование дней в дату.
  • FOREIGN KEY — внешний ключ.

G

  • GREATEST — максимум из значений.
  • GROUP_CONCAT — объединение значений группы в строку.
  • GROUP BY — группировка.

H

  • HOUR — часы из даты/времени.
  • HAVING — фильтрация после группировки.

I

  • INSERT — вставка записей.
  • IN — принадлежность набору.
  • IS NOT NULL — значение не равно NULL.
  • IS NULL — значение равно NULL.
  • IFNULL — подмена NULL.
  • INSERT SELECT — вставка результата SELECT.
  • INSERT IGNORE — вставка без конфликта (MySQL).
  • INSTR — позиция подстроки.
  • INTERVAL — интервал дат/времени.
  • INNER JOIN — внутренний JOIN.

J

  • JOIN — соединение таблиц.

L

  • LIMIT — ограничение выборки.
  • LIKE — поиск по шаблону.
  • LEAST — минимум из значений.
  • LOCATE — поиск позиции подстроки.
  • LEFT — N символов слева.
  • LPAD — дополнение строки слева.
  • LOWER — нижний регистр.
  • LCASE — синоним LOWER.
  • LTRIM — обрезание пробелов слева.
  • LENGTH — длина строки.
  • LEFT JOIN — левый JOIN.

M

  • MIN — минимальное значение.
  • MAX — максимальное значение.
  • MOD — остаток от деления.
  • MID — подстрока (синоним SUBSTRING в MySQL).
  • MONTH — месяц из даты.
  • MINUTE — минуты из даты/времени.
  • MONTHNAME — название месяца.
  • MODIFY COLUMN — изменение столбца.

N

  • NOT — отрицание.
  • NULLIF — возвращает NULL при совпадении значений.
  • NOW — текущие дата и время.

O

  • OR — логическое ИЛИ.
  • ORDER BY — сортировка.
  • OFFSET — смещение строк.
  • ON DUPLICATE KEY UPDATE — upsert по ключу (MySQL).
  • ON — условие соединения таблиц.

P

  • POW — степень числа.
  • POSITION — поиск подстроки.
  • PERIOD_ADD — добавление месяцев.
  • PERIOD_DIFF — разница месяцев.
  • PRIMARY KEY — первичный ключ.

R

  • REPLACE INTO — замена/вставка записи (MySQL).
  • ROUND — округление числа.
  • RAND — случайное число.
  • REPLACE — замена подстроки.
  • RIGHT — N символов справа.
  • RPAD — дополнение строки справа.
  • REVERSE — разворот строки.
  • REPEAT — повтор строки.
  • RTRIM — обрезание пробелов справа.
  • REGEXP — фильтрация по regex.
  • RIGHT JOIN — правый JOIN.
  • RENAME TABLE — переименование таблицы.
  • ROLLBACK — откат транзакции.

S

  • SELECT — получение записей.
  • SUM — сумма.
  • SIGN — знак числа.
  • SQRT — квадратный корень.
  • SUBSTRING — взятие подстроки.
  • SUBSTRING_INDEX — часть строки по разделителю.
  • SPACE — строка из пробелов.
  • SECOND — секунды из времени.
  • SEC_TO_TIME — секунды в TIME.
  • STR_TO_DATE — строка в дату.
  • SELECT INTO — копирование результата выборки в таблицу/переменную (по диалекту).
  • START TRANSACTION — начало транзакции.
  • SAVEPOINT — промежуточная точка отката.
  • SELECT ... FOR UPDATE — блокировка строк на обновление.
  • SHOW TABLES — список таблиц.
  • SHOW COLUMNS — столбцы таблицы.
  • SHOW INDEX — индексы таблицы.
  • SHOW CREATE TABLE — SQL создания таблицы.

T

  • TRUNCATE — усечение числа.
  • TRIM — обрезание пробелов/символов.
  • TIME_FORMAT — форматирование времени.
  • TO_DAYS — дата в дни.
  • TIME_TO_SEC — время в секунды.
  • TIMESTAMPDIFF — разница дат/времени по единице измерения.
  • TRUNCATE TABLE — очистка таблицы.

U

  • UPDATE — редактирование записей.
  • UPPER — верхний регистр.
  • UCASE — синоним UPPER.
  • USING — соединение по одноимённым столбцам.
  • UNION — объединение с удалением дублей.
  • UNION ALL — объединение без удаления дублей.
  • USE — выбор базы данных.
  • UNIQUE — ограничение уникальности.

W

  • WHERE — условие фильтрации.
  • WEEKDAY — день недели.
  • WEEK — номер недели в году.

Y

  • YEAR — год из даты.
  • YEARWEEK — год и номер недели.
Важно про диалекты SQL

Часть операторов и функций зависит от диалекта — MySQL, PostgreSQL, SQL Server, Oracle. Используйте этот список как карту по терминам и сверяйте точный синтаксис с документацией вашей СУБД.


Быстрый старт

ЗадачаКоманда
Подключение psqlсм. блок ниже
Список БД\l
Таблицы\dt
Выполнить файлсм. блок ниже
psql -h db-host -U app_user -d app_db
psql -f migrations/001_init.sql

Справочные таблицы

Справочник SQL

Версия: ANSI SQL:2016 (с учётом общепринятых расширений)


1. DDL — Data Definition Language

Операции определения и модификации структуры данных.


CREATE

Создание объектов БД.


Таблица
CREATE TABLE [IF NOT EXISTS] table_name (
column_name data_type [CONSTRAINT constraint_name] [column_constraint],
...,
[table_constraint]
);
  • IF NOT EXISTS — в PostgreSQL/MySQL/SQLite в заголовке CREATE TABLE; в T-SQL — отдельная проверка:
-- PostgreSQL / MySQL / SQLite
CREATE TABLE IF NOT EXISTS employees (...);

-- SQL Server
IF NOT EXISTS (
SELECT 1 FROM sys.tables WHERE name = N'employees' AND schema_id = SCHEMA_ID(N'dbo')
)
CREATE TABLE dbo.employees (...);
  • column_constraint:
    NOT NULL, NULL, UNIQUE, PRIMARY KEY, CHECK (condition), DEFAULT value, REFERENCES ref_table (col) [ON DELETE | UPDATE action]
  • table_constraint:
    PRIMARY KEY (col1, col2), FOREIGN KEY (col) REFERENCES ..., UNIQUE (col), CHECK (condition)

Индекс
CREATE [UNIQUE] INDEX [IF NOT EXISTS] index_name
ON table_name (column_name [ASC | DESC] [, ...])
[INCLUDE (included_column, ...)] -- T-SQL, PostgreSQL 11+
[WHERE condition]; -- filtered index: T-SQL, PostgreSQL (partial index)

Представление
CREATE [OR REPLACE] [TEMP | TEMPORARY] VIEW view_name [(alias_col, ...)] AS
SELECT ...;
-- WITH [LOCAL | CASCADE] CHECK OPTION — в ANSI, поддерживается в PostgreSQL, Oracle

Схема
CREATE SCHEMA [IF NOT EXISTS] schema_name
[AUTHORIZATION user_name];

Домен (PostgreSQL, Firebird)
CREATE DOMAIN domain_name AS base_type
[CONSTRAINT constraint_name] [CHECK (condition)];

Последовательность (serial, identity support)

Код ITЗагрузка примера кода…


Тип данных (PostgreSQL, Oracle)
CREATE TYPE type_name AS (
field_name data_type,
...
);

-- Или ENUM:
CREATE TYPE enum_name AS ENUM ('val1', 'val2', ...);

Триггер (общая форма)
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF} {event [, ...]}
ON table_name
[REFERENCING {OLD [AS] old_alias | NEW [AS] new_alias}]
[FOR EACH {ROW | STATEMENT}]
[WHEN (condition)]
EXECUTE {FUNCTION function_name() | PROCEDURE proc_name()};
-- event: INSERT, UPDATE [OF col], DELETE
-- Поддержка: Oracle (PL/SQL), PostgreSQL (PL/pgSQL), SQL Server (T-SQL, но синтаксис отличается)

ALTER

Изменение объектов.


Таблица
ALTER TABLE table_name
ADD [COLUMN] column_name data_type [column_constraint],
DROP [COLUMN] column_name [CASCADE | RESTRICT],
ALTER [COLUMN] column_name {SET ДАННЫЕ TYPE new_type | SET DEFAULT value | DROP DEFAULT | SET NOT NULL | DROP NOT NULL},
ADD CONSTRAINT constraint_name constraint_definition,
DROP CONSTRAINT constraint_name [CASCADE],
RENAME COLUMN old_name TO new_name, -- PostgreSQL, SQLite
RENAME TO new_table_name; -- PostgreSQL, Oracle
  • В T-SQL:
ALTER TABLE dbo.Orders ALTER COLUMN amount DECIMAL(18,2) NOT NULL;
ALTER TABLE dbo.Orders DROP COLUMN legacy_code;
EXEC sp_rename 'dbo.Orders.old_col', 'new_col', 'COLUMN';

Индекс / представление / последовательность
ALTER INDEX index_name RENAME TO new_name; -- PostgreSQL
ALTER SEQUENCE seq_name [RESTART [WITH value] | ...];
-- Для представлений: обычно DROP + CREATE или CREATE OR REPLACE

DROP

Удаление объектов.

DROP TABLE [IF EXISTS] table_name [CASCADE | RESTRICT];
DROP INDEX [IF EXISTS] index_name;
DROP VIEW [IF EXISTS] view_name [CASCADE];
DROP SCHEMA [IF EXISTS] schema_name [CASCADE | RESTRICT];
DROP SEQUENCE [IF EXISTS] sequence_name [CASCADE];
DROP TYPE [IF EXISTS] type_name [CASCADE];
DROP TRIGGER [IF EXISTS] trigger_name ON table_name;
-- CASCADE: рекурсивно удаляет зависимые объекты (например, FK, views)
-- RESTRICT (по умолчанию в ANSI): запрещает удаление при наличии зависимостей
-- IF EXISTS — поддерживается в PostgreSQL, MySQL, SQLite; в T-SQL — `IF OBJECT_ID('name','U') IS NOT NULL DROP TABLE ...`

TRUNCATE

Быстрая очистка таблицы (не DML!).

TRUNCATE TABLE table_name
[RESTART IDENTITY] -- сброс сиквенсов, связанных с IDENTITY/serial (PostgreSQL, T-SQL)
[IDENTITY RESTART] -- T-SQL синоним
[CONTINUE IDENTITY] -- T-SQL: не сбрасывать
[CASCADE]; -- рекурсивно для дочерних таблиц (PostgreSQL)
-- Не вызывает триггеры DELETE (в большинстве СУБД)
-- Не может быть отменён отдельно в рамках транзакции в некоторых СУБД без explicit BEGIN

RENAME (не ANSI, но широко используется)
-- PostgreSQL, SQLite
ALTER TABLE old_name RENAME TO new_name;
ALTER TABLE table_name RENAME COLUMN old_col TO new_col;

-- Oracle
RENAME old_name TO new_name;

-- MySQL
RENAME TABLE old_name TO new_name;
ALTER TABLE table_name RENAME COLUMN old_col TO new_col; -- ≥8.0.3

2. DML — Data Manipulation Language

Работа с данными.


INSERT

Код ITЗагрузка примера кода…


3. DCL — Data Control Language

Управление доступом и привилегиями.


GRANT

Код ITЗагрузка примера кода…


REVOKE
REVOKE [GRANT OPTION FOR] privilege [, ...] ON object_type object_name
FROM {user | role} [, ...]
[CASCADE | RESTRICT];

-- CASCADE: отзывает привилегию и у тех, кому она была передана этим пользователем (если WITH GRANT OPTION был использован)
-- RESTRICT (по умолчанию): запрещает отозвать, если привилегия была передана дальше
-- Отзыв всех:
REVOKE ALL PRIVILEGES ON TABLE employees FROM analyst;

CREATE ROLE / DROP ROLE (не ANSI, но стандарт де-факто)
CREATE ROLE role_name [WITH option [, ...]];
-- PostgreSQL: LOGIN, SUPERUSER, CREATEDB, CREATEROLE, INHERIT, REPLICATION, CONNECTION LIMIT n, PASSWORD 'pwd', VALID UNTIL 'timestamp'
-- SQL Server: CREATE LOGIN, CREATE USER, ALTER ROLE role_name ADD MEMBER user

DROP ROLE [IF EXISTS] role_name;

⚠️ В T-SQL управление доступом разделено (сервер → БД → роль):

CREATE LOGIN app_login WITH PASSWORD = '...';
CREATE USER app_user FOR LOGIN app_login;
ALTER ROLE db_datareader ADD MEMBER app_user;
-- DENY имеет приоритет над GRANT

4. TCL — Transaction Control Language

Управление транзакциями.


BEGIN / START TRANSACTION
-- ANSI:
START TRANSACTION [ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}]
[READ {ONLY | WRITE}];

-- PostgreSQL, MySQL:
BEGIN [WORK | TRANSACTION];
-- Необязательно — в большинстве СУБД DML-команды неявно запускают транзакцию, если autocommit = OFF.

-- T-SQL:
BEGIN TRANSACTION [transaction_name];
-- Можно вкладывать (savepoints под капотом), но commit/rollback действуют на весь блок, если не указано savepoint.

COMMIT
COMMIT [WORK | TRANSACTION]; -- ANSI
-- T-SQL: COMMIT [TRANSACTION [name]]
-- PostgreSQL: COMMIT AND CHAIN — продолжает новую транзакцию

ROLLBACK
ROLLBACK [WORK | TRANSACTION]; -- откат всей транзакции
ROLLBACK [WORK | TRANSACTION] TO [SAVEPOINT] savepoint_name;

SAVEPOINT
SAVEPOINT savepoint_name;
-- В T-SQL: SAVE TRANSACTION savepoint_name
-- Откат к точке:
ROLLBACK TO savepoint_name; -- ANSI, PostgreSQL
ROLLBACK TRANSACTION savepoint_name; -- T-SQL

-- Удаление точки (необязательно, удаляются при COMMIT/ROLLBACK):
RELEASE SAVEPOINT savepoint_name; -- PostgreSQL
-- В T-SQL точка остаётся до конца транзакции.

Уровни изоляции (стандартные и поведение)
УровеньDirty ReadNon-Repeatable ReadPhantom ReadСериализуемость
READ UNCOMMITTEDдададанет
READ COMMITTEDнетдаданет
REPEATABLE READнетнетзависит¹нет
SERIALIZABLEнетнетнетда

¹ — в PostgreSQL REPEATABLE READ предотвращает phantom reads за счёт snapshot isolation; в SQL Server — нет (требуется SERIALIZABLE).


5. DQL — Data Query Language

Извлечение данных. Основной оператор — SELECT.


Обобщённый синтаксис (логический порядок обработки)

Код ITЗагрузка примера кода…

🔹 Физический порядок выполнения:
FROMJOINWHEREGROUP BYHAVINGSELECTDISTINCTWINDOWORDER BYLIMIT/FETCH.


FROM и JOIN
Типы JOIN (ANSI)
ТипСинтаксисПримечание
Внутреннее соединениеINNER JOIN или JOINТолько совпадающие строки
Левое внешнееLEFT [OUTER] JOINВсе строки из левой таблицы
Правое внешнееRIGHT [OUTER] JOINВсе строки из правой таблицы
Полное внешнееFULL [OUTER] JOINВсе строки из обеих таблиц
Перекрёстное (декартово)CROSS JOINБез условия — полное произведение
Самосоединениеtable t1 JOIN table t2 ON ...Та же таблица, разные алиасы

Расширения
  • LATERAL (PostgreSQL, Oracle 12c+, SQL Server APPLY):
SELECT *
FROM employees e
LEFT JOIN LATERAL (
SELECT * FROM salaries s
WHERE s.emp_id = e.id
ORDER BY s.effective_date DESC
LIMIT 1
) AS latest_sal ON true;
  • T-SQL OUTER APPLY / CROSS APPLY — аналог LATERAL:
SELECT *
FROM employees e
OUTER APPLY (
SELECT TOP 1 * FROM salaries s
WHERE s.emp_id = e.id
ORDER BY s.effective_date DESC
) AS latest_sal;

WHERE

Фильтрация строк до группировки.
Поддерживает:

  • Сравнения (=, <>, <, >, <=, >=, !=)
  • Логические (AND, OR, NOT)
  • BETWEEN a AND b — включительно
  • IN (val1, val2, ...) / NOT IN (...)
  • LIKE 'pattern' / ILIKE (PostgreSQL, case-insensitive)
    % — любое кол-во символов, _ — ровно один
  • SIMILAR TO (PostgreSQL, SQL:2008) — регулярные выражения (ограниченные)
  • ~, ~*, !~, !~* (PostgreSQL — полноценные regex)
  • IS [NOT] NULL
  • EXISTS (subquery)
  • ANY / SOME / ALL с подзапросами:
    value > ALL (SELECT ...) — строго больше любого

GROUP BY

Группировка строк. Требует агрегации для всех неключевых колонок в SELECT.


Агрегатные функции (стандартные)
ФункцияОписание
COUNT(*)число строк (включая NULL)
COUNT(col)число ненулевых значений в col
SUM(col), AVG(col)сумма, среднее (только числовые)
MIN(col), MAX(col)мин/макс (работает с датами, строками)
ARRAY_AGG(col)PostgreSQL: массив значений
STRING_AGG(col, delimiter)PostgreSQL/SQL Server: строка через разделитель
GROUP_CONCAT(col SEPARATOR delim)MySQL — аналог
BOOL_AND(col), BOOL_OR(col)PostgreSQL: логические агрегаты
JSON_AGG(col)PostgreSQL/MySQL 5.7+: JSON-массив
JSON_OBJECT_AGG(k, v)PostgreSQL/MySQL: JSON-объект

GROUPING SETS, ROLLUP, CUBE (ANSI, PostgreSQL, SQL Server, Oracle)
-- GROUPING SETS: явное перечисление групп
SELECT dept, region, SUM(sales)
FROM t
GROUP BY GROUPING SETS ( (dept, region), (dept), (region), () );

-- ROLLUP: иерархическая агрегация (сверху вниз)
GROUP BY ROLLUP (A, B, C)
-- эквивалентно: (A,B,C), (A,B), (A), ()

-- CUBE: все комбинации
GROUP BY CUBE (A, B)
-- эквивалентно: (A,B), (A), (B), ()

GROUPING() — идентификатор уровня агрегации
SELECT
GROUPING(dept) AS g_dept,
dept,
SUM(sales)
FROM t
GROUP BY ROLLUP (dept);
-- g_dept = 1, если dept — NULL из агрегата ("итоговая" строка)

HAVING

Фильтрация после группировки. Допускает агрегаты:

SELECT dept, AVG(salary)
FROM employees
GROUP BY dept
HAVING COUNT(*) > 5 AND AVG(salary) > 70000;

WINDOW и оконные функции
Объявление окна
SELECT
emp_id,
salary,
AVG(salary) OVER w AS dept_avg,
ROW_NUMBER() OVER w AS rn
FROM employees
WINDOW w AS (PARTITION BY dept_id ORDER BY salary DESC);

Стандартные оконные функции
КатегорияФункции
РанжированиеROW_NUMBER(), RANK(), DENSE_RANK(), NTILE(n)
АгрегатныеSUM(), AVG(), MIN(), MAX(), COUNT() — с OVER
СмещенияLAG(col, offset, default), LEAD(col, offset, default), FIRST_VALUE(), LAST_VALUE(), NTH_VALUE(col, n)
СтатистическиеPERCENT_RANK(), CUME_DIST(), PERCENTILE_CONT(frac), PERCENTILE_DISC(frac)

Спецификация окна
OVER (
[PARTITION BY expr, ...]
[ORDER BY expr [ASC | DESC] [NULLS {FIRST | LAST}]]
[frame_clause]
)
-- frame_clause:
-- RANGE | ROWS | GROUPS
-- { UNBOUNDED PRECEDING | CURRENT ROW | offset PRECEDING | offset FOLLOWING }
-- [BETWEEN start AND end]
-- Например:
-- ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
-- RANGE BETWEEN INTERVAL '1' DAY PRECEDING AND CURRENT ROW -- для временных типов

⚠️ RANGE интерпретирует смещение по значению, ROWS — по числу строк.
Пример (все строки за последний час относительно текущей):

ORDER BY ts
RANGE BETWEEN INTERVAL '1 hour' PRECEDING AND CURRENT ROW

SELECT расширения
DISTINCT ON (PostgreSQL)
SELECT DISTINCT ON (dept_id) dept_id, emp_id, hire_date
FROM employees
ORDER BY dept_id, hire_date DESC; -- обязательно ORDER BY по ключу DISTINCT ON
-- Возвращает первую строку в каждой группе dept_id

TOP (T-SQL), LIMIT (ANSI/PostgreSQL/MySQL), FETCH (ANSI)
-- T-SQL:
SELECT TOP 10 * FROM orders ORDER BY total DESC;
SELECT TOP 10 PERCENT * FROM orders ORDER BY total DESC;

-- ANSI / PostgreSQL ≥8.4 / SQL Server ≥2012:
SELECT * FROM orders
ORDER BY total DESC
FETCH FIRST 10 ROWS ONLY;

-- С пропуском:
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

FOR UPDATE, FOR SHARE
-- Блокировка строк для обновления (PostgreSQL, Oracle):
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;

-- T-SQL: использует табличные хинты:
SELECT * FROM accounts WITH (UPDLOCK, ROWLOCK) WHERE id = 1;

-- SKIP LOCKED / NOWAIT (PostgreSQL, MySQL 8+):
SELECT * FROM queue FOR UPDATE SKIP LOCKED; -- пропустить занятые строки
SELECT * FROM queue FOR UPDATE NOWAIT; -- ошибка, если строка занята

-- Пакетный захват в одной транзакции — см. [Блокировки в PostgreSQL](./110.md#skip-locked-paket)

6. Системные / служебные команды (не ANSI, но критичны)

Получение метаданных
# PostgreSQL (psql)
\dt
\d+ orders
-- PostgreSQL
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public';

-- MySQL
SHOW TABLES;
DESCRIBE orders;

-- SQL Server
EXEC sp_help 'dbo.Orders';

-- Oracle
SELECT table_name FROM user_tables;
СУБДКлиент / каталог
PostgreSQL\dt, \d, information_schema, pg_catalog
MySQLSHOW, DESCRIBE, information_schema
SQL Serversp_help, sys.*
Oracleuser_*, all_*, dba_*

Управление сессиями / настройками
-- ANSI: SET [SESSION | LOCAL] parameter = value;
SET TIME ZONE 'UTC';
SET search_path TO myschema, public; -- PostgreSQL
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- T-SQL:
SET NOCOUNT ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;

Условное выполнение (в скриптах)
  • PostgreSQL:
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'logs') THEN
CREATE TABLE logs (...);
END IF;
END $$;
  • T-SQL:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'logs' AND type = 'U')
CREATE TABLE logs (...);

7. CTE — Common Table Expressions

Временные именованные результаты запроса, существующие только в рамках одного SELECT/INSERT/UPDATE/DELETE/MERGE.


Базовый синтаксис
WITH cte_name [(col_alias, ...)] AS (
SELECT ...
)
SELECT ... FROM cte_name;

Особенности
  • Можно объявлять несколько CTE через запятую:
WITH
sales_2024 AS (SELECT * FROM sales WHERE year = 2024),
top_customers AS (SELECT cust_id, SUM(amount) AS total FROM sales_2024 GROUP BY cust_id HAVING SUM(amount) > 10000)
SELECT c.name, tc.total
FROM customers c
JOIN top_customers tc ON c.id = tc.cust_id;
  • CTE могут ссылаться друг на друга только вперёд (последовательно).
  • В PostgreSQL 12+ после AS можно указать подсказку планировщику
    • MATERIALIZED — выполнить CTE один раз и сохранить результат
    • NOT MATERIALIZED — предпочесть встраивание CTE в основной запрос
    • Подробный разбор с примерами — CTE и материализация в PostgreSQL
WITH cte AS MATERIALIZED (SELECT ...) ...
WITH cte AS NOT MATERIALIZED (SELECT ...) ...

Рекурсивные CTE (WITH RECURSIVE)

Код ITЗагрузка примера кода…

  • Обязательно UNION ALL (в ANSI; UNION не разрешён в рекурсивной части).
  • В PostgreSQL/SQL Server — лимиты на сессию перед тяжёлым рекурсивным запросом:
-- PostgreSQL
SET work_mem = '256MB';
SET statement_timeout = '30s';

-- T-SQL
OPTION (MAXRECURSION 100);
  • Для предотвращения зацикливания:
    • PostgreSQL ≥14: SEARCH BREADTH FIRST BY id SET ordercol, CYCLE id SET is_cycle TO 'Y' DEFAULT 'N' USING pathcol
    • Oracle: CONNECT BY NOCYCLE
    • T-SQL: OPTION (MAXRECURSION n) (макс. 32767)

8. Подзапросы

Типы
ТипОписаниеПример
СкалярныйВозвращает одно значение (одна строка, один столбец)SELECT name, (SELECT AVG(salary) FROM employees) AS dept_avg FROM employees
КоррелированныйСсылается на внешний запросSELECT name FROM employees e WHERE salary > (SELECT AVG(salary) FROM employees WHERE dept_id = e.dept_id)
Табличный (в FROM)Возвращает таблицуSELECT * FROM (SELECT dept_id, AVG(salary) AS avg_sal FROM employees GROUP BY dept_id) AS dept_stats
Существование (EXISTS)Проверяет наличие строкSELECT name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id)

Оптимизация
  • EXISTS предпочтительнее IN при работе с NULLIN NULL "отравляет" результат: value NOT IN (a, NULL)UNKNOWN).
  • NOT EXISTS надёжнее NOT IN.
  • Подзапросы в SELECT (скалярные) могут вызывать N+1 — лучше заменять JOIN или оконными функциями.

9. Множественные операции

Объединение результатов нескольких SELECT с одинаковой структурой.

ОператорANSIPostgreSQLSQL ServerMySQLЗамечание
Объединение без дубликатовUNIONСортирует для удаления дублей
Объединение с дубликатамиUNION ALLБыстрее, не сортирует
ПересечениеINTERSECT≤8.0.31: нетУдаляет дубли
Пересечение с дублямиINTERSECT ALL
РазностьEXCEPTMINUS (Oracle)EXCEPTУдаляет дубли
Разность с дублямиEXCEPT ALL

Синтаксис
query1
UNION [ALL]
query2
[UNION [ALL] query3 ...]
[ORDER BY ...] -- только в конце всего выражения
[LIMIT ...];

Важно
  • Порядок столбцов и их типы должны быть совместимы (не обязательно идентичны — INTEGER и BIGINT совместимы).
  • Имена столбцов берутся из первого SELECT.
  • ORDER BY внутри отдельного SELECT недопустим без LIMIT (и то — только в PostgreSQL с OFFSET 0 или LIMIT ALL для эмуляции).

10. Работа с JSON

Стандарт SQL:2016 (JSON_VALUE, JSON_QUERY, JSON_TABLE)

Код ITЗагрузка примера кода…


MySQL
SELECT JSON_EXTRACT(doc, '$.user.name') -- возвращает JSON-значение ("Timur")
SELECT doc->'$.user.name' -- синтаксический сахар
SELECT doc->>'$.user.name' -- как строка: Timur
SELECT JSON_UNQUOTE(JSON_EXTRACT(...)) -- аналог ->>
SELECT * FROM JSON_TABLE(...);

11. Полнотекстовый поиск

PostgreSQL (tsvector, tsquery)

Код ITЗагрузка примера кода…


MySQL (FULLTEXT)
ALTER TABLE articles ADD FULLTEXT(title, content);
SELECT *, MATCH(title, content) AGAINST('SQL база данных' IN NATURAL LANGUAGE MODE) AS score
FROM articles
WHERE MATCH(title, content) AGAINST('SQL база данных');
-- Режимы: NATURAL LANGUAGE, BOOLEAN, WITH QUERY EXPANSION

SQL Server (CONTAINS, FREETEXT)
-- Требует полнотекстового каталога и индекса
SELECT * FROM articles
WHERE CONTAINS((title, content), 'FORMSOF(INFLECTIONAL, "develop") AND "database"');

12. Хранимые модули

CREATE FUNCTION

Код ITЗагрузка примера кода…


Параметры
  • IN (по умолчанию) — входной
  • OUT — выходной (только в процедурах)
  • INOUT — вход/выход
  • VARIADIC (PostgreSQL) — для массивов: VARIADIC arr INT[]

13. Вспомогательные конструкции

CASE
-- Простой CASE (по значению)
CASE col
WHEN 1 THEN 'один'
WHEN 2 THEN 'два'
ELSE 'много'
END

-- Поисковый CASE (по условию)
CASE
WHEN salary < 30000 THEN 'низкий'
WHEN salary BETWEEN 30000 AND 70000 THEN 'средний'
ELSE 'высокий'
END

Функции обработки NULL
ФункцияОписаниеANSIПример
COALESCE(a, b, c)возвращает первый ненулевой аргументCOALESCE(phone, email, 'нет контакта')
NULLIF(a, b)возвращает NULL, если a = b, иначе aNULLIF(value, 0) — избежать деления на 0
ISNULL(a, b)T-SQL: аналог COALESCE, но только 2 аргументаISNULL(name, '—')
NVL(a, b)Oracle: аналог COALESCE (2 аргумента)NVL(salary, 0)

Функции сравнения
ФункцияОписание
GREATEST(a, b, c)максимум из аргументов (PostgreSQL, MySQL, Oracle)
LEAST(a, b, c)минимум
IIF(cond, true_val, false_val)T-SQL: инлайновый CASE

Приведение типов
CAST(expr AS type)
expr::type -- PostgreSQL, Redshift
TRY_CAST(expr AS type) -- T-SQL, возвращает NULL при ошибке
CONVERT(type, expr [, style]) -- T-SQL (style для дат/строк)

Генерация данных
-- PostgreSQL: generate_series
SELECT generate_series(1, 10) AS n;
SELECT generate_series('2025-01-01'::DATE, '2025-12-31'::DATE, '1 day'::INTERVAL);

-- T-SQL: рекурсивный CTE или tally-таблица
WITH nums(n) AS (
SELECT 1 UNION ALL SELECT n+1 FROM nums WHERE n < 10
)
SELECT n FROM nums;

14. Сравнение диалектов

Фича / СУБДPostgreSQL (PL/pgSQL)SQL Server (T-SQL)Oracle (PL/SQL)MySQL
Идентификаторы"quoted"[quoted] или "quoted""quoted"`quoted`
Комментарии--, /* */, /&#42;&#42;/--, /* */--, /* */-- , #, /* */
АвтоинкрементSERIAL, GENERATED ALWAYS AS IDENTITYIDENTITY(1,1), SEQUENCEIDENTITY, SEQUENCE + TRIGGERAUTO_INCREMENT
Строка → числоCAST('123' AS INT)CAST('123' AS INT), TRY_CASTTO_NUMBER('123')CAST('123' AS SIGNED)
Дата/время'2025-11-18'::DATE, timestamptzGETDATE(), SYSDATETIME(), DATETIME2SYSDATE, TIMESTAMP WITH TIME ZONENOW(), CURDATE(), DATETIME(6)
Оконные ф-цииполная поддержка ANSIполная (с 2012)полнаяс 8.0
Рекурсивные CTEWITH RECURSIVEWITH, без RECURSIVEWITH, без RECURSIVEс 8.0
Динамический SQLEXECUTE format('...', arg)EXEC sp_executesql @sql, @params, @p1=...EXECUTE IMMEDIATEPREPARE, EXECUTE, EXECUTE IMMEDIATE
Обработка исключенийEXCEPTION WHEN ... THENBEGIN TRY ... END TRY BEGIN CATCHEXCEPTION WHEN ... THENDECLARE EXIT HANDLER FOR SQLEXCEPTION
Возврат из ф-цииRETURN expr;RETURN expr; (в функциях), SELECT (в inline TVF)RETURN expr;RETURN expr;
Табличная ф-цияRETURNS TABLE (...)RETURNS @t TABLE (...) (multi-statement), RETURNS TABLE AS RETURN (...) (inline)PIPELINED TABLE FUNCTIONRETURNS TABLE (...) (с 8.0)
Проверка объектаIF NOT EXISTS (SELECT FROM pg_tables ...)IF NOT EXISTS (SELECT * FROM sys.objects ...)SELECT COUNT(*) FROM user_tables WHERE ...CREATE TABLE IF NOT EXISTS
LIMIT/OFFSETLIMIT n OFFSET mOFFSET m ROWS FETCH NEXT n ROWS ONLYOFFSET m ROWS FETCH NEXT n ROWS ONLY (с 12c)LIMIT n OFFSET m
JSON-операторы->, -&gt;&gt;, @>JSON_VALUE, JSON_QUERYJSON_VALUE, JSON_TABLE->, -&gt;&gt;, JSON_EXTRACT

🔹 Примечание по переносимости:

  • Избегайте диалект-специфичных конструкций (TOP, LIMIT, ::, [ ]) в библиотечном коде.
  • Используйте ANSI JOIN с ON, а не неявное соединение в WHERE:
SELECT *
FROM orders o
JOIN customers c ON c.id = o.customer_id;
  • Для автоинкремента — GENERATED ALWAYS AS IDENTITY (ANSI SQL:2016).

Ошибки

СитуацияЧто проверить
Команда не найденаPATH, установка пакета, alias
Permission deniedпользователь, группа, sudo, ACL
Неверная версиясм. "Совместимость", --version

Совместимость

ОбластьПримечание
Версииактуальные LTS/стабильные релизы SQL
Платформыофициальная матрица поддержки вендора
СтандартыRFC, ISO, спецификация API — см. таблицы выше

В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

СправочникиСправочник по Memcached, Справочник по HTML, Справочник по Cypher, Справочник по CSS, Справочник по Cassandra, Справочник-шпаргалка по Git.