200 вопросов по SQL
200 вопросов по SQL
Основы SQL и реляционной модели
Вопрос
Что такое SQL?
Ответ
SQL — это язык структурированных запросов, предназначенный для управления данными в реляционных системах управления базами данных. Он позволяет создавать, изменять, запрашивать и удалять данные, а также управлять структурой базы данных и правами доступа.
Вопрос
Какие основные категории команд SQL существуют?
Ответ
Команды SQL делятся на четыре категории:
- DDL (Data Definition Language) — определение структуры данных: CREATE, ALTER, DROP.
- DML (Data Manipulation Language) — манипуляция данными: SELECT, INSERT, UPDATE, DELETE.
- DCL (Data Control Language) — управление доступом: GRANT, REVOKE.
- TCL (Transaction Control Language) — управление транзакциями: COMMIT, ROLLBACK, SAVEPOINT.
Вопрос
Что такое реляционная база данных?
Ответ
Реляционная база данных — это система хранения данных, организованная в виде таблиц, состоящих из строк и столбцов. Каждая таблица представляет собой отношение, строки — кортежи, столбцы — атрибуты. Таблицы связаны между собой через ключи.
Вопрос
Что такое первичный ключ (Primary Key)?
Ответ
Первичный ключ — это один или несколько столбцов таблицы, однозначно идентифицирующих каждую строку. Значения первичного ключа не могут быть NULL и должны быть уникальными.
Вопрос
Что такое внешний ключ (Foreign Key)?
Ответ
Внешний ключ — это столбец или набор столбцов в одной таблице, ссылающийся на первичный ключ другой таблицы. Он обеспечивает ссылочную целостность между таблицами.
Вопрос
Может ли первичный ключ содержать значение NULL?
Ответ
Нет. Первичный ключ не может содержать значение NULL, так как он должен однозначно идентифицировать строку, а NULL означает отсутствие значения.
Вопрос
Может ли внешний ключ содержать значение NULL?
Ответ
Да. Внешний ключ может содержать значение NULL, если это допускается при его определении. Это означает, что строка не связана с родительской записью.
Вопрос
Что такое нормализация базы данных?
Ответ
Нормализация — это процесс приведения структуры базы данных к форме, исключающей избыточность и аномалии при вставке, обновлении и удалении. Она осуществляется через последовательное применение нормальных форм (1NF, 2NF, 3NF и далее).
Вопрос
Что такое денормализация?
Ответ
Денормализация — это сознательное нарушение нормальных форм с целью повышения производительности запросов за счёт введения избыточности. Применяется в аналитических системах и хранилищах данных.
Вопрос
Какие типы данных чаще всего используются в SQL?
Ответ
Наиболее распространённые типы данных:
- Числовые: INTEGER, BIGINT, DECIMAL, FLOAT.
- Строковые: CHAR, VARCHAR, TEXT.
- Дата и время: DATE, TIME, DATETIME, TIMESTAMP.
- Логический: BOOLEAN.
- Бинарные: BLOB, BYTEA.
Вопрос
Что такое NULL в SQL?
Ответ
NULL — это специальное значение, обозначающее отсутствие данных. Оно не эквивалентно нулю, пустой строке или FALSE. Сравнение с NULL всегда даёт UNKNOWN, а не TRUE или FALSE.
Вопрос
Как проверить, является ли значение NULL?
Ответ
Для проверки используется оператор IS NULL или IS NOT NULL. Например:
SELECT * FROM users WHERE email IS NULL;
Вопрос
Почему сравнение с NULL через = не работает?
Ответ
Потому что NULL означает «неизвестно». Выражение column = NULL всегда возвращает UNKNOWN, а не TRUE. Поэтому такие условия никогда не выбирают строки. Правильный способ — использовать IS NULL.
Вопрос
Что такое ограничение (constraint) в SQL?
Ответ
Ограничение — это правило, накладываемое на данные в таблице для обеспечения целостности. Примеры: PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, NOT NULL.
Вопрос
Что делает ограничение UNIQUE?
Ответ
Ограничение UNIQUE гарантирует, что все значения в столбце (или комбинации столбцов) уникальны. В отличие от PRIMARY KEY, оно допускает одно значение NULL (в большинстве СУБД).
Вопрос
Что такое индекс в базе данных?
Ответ
Индекс — это структура данных, ускоряющая поиск строк по значениям одного или нескольких столбцов. Он работает аналогично оглавлению в книге.
Вопрос
Как создать таблицу в SQL?
Ответ
Таблица создаётся с помощью команды CREATE TABLE. Пример:
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
department_id INT,
salary DECIMAL(10, 2),
FOREIGN KEY (department_id) REFERENCES departments(id)
);
Вопрос
Как добавить новую запись в таблицу?
Ответ
Новая запись добавляется с помощью команды INSERT INTO. Пример:
INSERT INTO employees (id, name, department_id, salary)
VALUES (1, 'Анна Петрова', 5, 75000.00);
Вопрос
Как обновить существующие записи?
Ответ
Обновление выполняется с помощью команды UPDATE. Пример:
UPDATE employees
SET salary = 80000.00
WHERE id = 1;
Вопрос
Как удалить записи из таблицы?
Ответ
Удаление выполняется с помощью команды DELETE. Пример:
DELETE FROM employees
WHERE id = 1;
Если не указать WHERE, будут удалены все строки.
Фильтрация и сортировка данных
Вопрос
Что делает команда SELECT?
Ответ
Команда SELECT извлекает данные из одной или нескольких таблиц базы данных. Она указывает, какие столбцы следует вернуть, и может включать условия фильтрации, сортировки, группировки и объединения.
Вопрос
Как выбрать все столбцы из таблицы?
Ответ
Для выбора всех столбцов используется звёздочка (*). Пример:
SELECT * FROM employees;
Вопрос
Как выбрать только определённые столбцы?
Ответ
Указываются имена нужных столбцов через запятую. Пример:
SELECT first_name, last_name, salary FROM employees;
Вопрос
Как отфильтровать строки по условию?
Ответ
Фильтрация выполняется с помощью предложения WHERE. Пример:
SELECT * FROM employees WHERE salary > 50000;
Вопрос
Какие операторы сравнения поддерживаются в SQL?
Ответ
Поддерживаются следующие операторы:
=— равно<>или!=— не равно<,>,<=,>=— меньше, больше и их комбинацииBETWEEN— в диапазонеIN— среди перечисленных значенийLIKE— по шаблонуIS NULL/IS NOT NULL— проверка на NULL
Вопрос
Как использовать оператор BETWEEN?
Ответ
Оператор BETWEEN выбирает значения в указанном диапазоне, включая границы. Пример:
SELECT * FROM employees WHERE salary BETWEEN 40000 AND 60000;
Вопрос
Как проверить, принадлежит ли значение списку?
Ответ
Используется оператор IN. Пример:
SELECT * FROM employees WHERE department_id IN (1, 3, 5);
Вопрос
Как выполнить поиск по шаблону?
Ответ
Для поиска по шаблону используется оператор LIKE с символами % (любое количество символов) и _ (один символ). Пример:
SELECT * FROM employees WHERE last_name LIKE 'Smi%';
Вопрос
Как отсортировать результаты запроса?
Ответ
Сортировка выполняется с помощью предложения ORDER BY. По умолчанию — по возрастанию (ASC), можно указать DESC для убывания. Пример:
SELECT * FROM employees ORDER BY salary DESC;
Вопрос
Можно ли сортировать по нескольким столбцам?
Ответ
Да. Столбцы перечисляются через запятую. Сортировка применяется последовательно. Пример:
SELECT * FROM employees ORDER BY department_id ASC, salary DESC;
Вопрос
Как ограничить количество возвращаемых строк?
Ответ
В разных СУБД используются разные конструкции:
- В PostgreSQL, MySQL, SQLite:
LIMIT - В SQL Server:
TOP - В стандарте SQL:
FETCH FIRST n ROWS ONLY
Пример для PostgreSQL:
SELECT * FROM employees ORDER BY salary DESC LIMIT 10;
Вопрос
Как исключить дубликаты из результата?
Ответ
Используется ключевое слово DISTINCT после SELECT. Пример:
SELECT DISTINCT department_id FROM employees;
Вопрос
Можно ли использовать арифметические выражения в SELECT?
Ответ
Да. Например, можно вычислить годовой доход:
SELECT name, salary * 12 AS annual_salary FROM employees;
Здесь AS задаёт псевдоним (алиас) для вычисляемого столбца.
Вопрос
Что такое псевдоним столбца?
Ответ
Псевдоним — это временное имя, присваиваемое столбцу в результате запроса с помощью ключевого слова AS. Он упрощает чтение и позволяет ссылаться на вычисляемые поля.
Вопрос
Как обрабатывать регистр при сравнении строк?
Ответ
Поведение зависит от СУБД и параметров сортировки (collation). В большинстве случаев сравнение без учёта регистра требует явного преобразования:
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
Вопрос
Как найти записи, где значение начинается с цифры?
Ответ
Можно использовать регулярные выражения (в PostgreSQL, Oracle) или комбинацию LIKE и функций. Пример для PostgreSQL:
SELECT * FROM products WHERE name ~ '^[0-9]';
В MySQL:
SELECT * FROM products WHERE name REGEXP '^[0-9]';
Вопрос
Как выбрать записи, где поле не пустое и не NULL?
Ответ
Следует проверить оба условия:
SELECT * FROM comments WHERE content IS NOT NULL AND content != '';
Вопрос
Что произойдёт, если в WHERE использовать сравнение с NULL?
Ответ
Сравнение с NULL через =, <> и другие операторы всегда возвращает UNKNOWN, и такие строки не попадут в результат. Для проверки на NULL нужно использовать IS NULL или IS NOT NULL.
Вопрос
Как отсортировать NULL-значения в начало или конец?
Ответ
Поведение по умолчанию зависит от СУБД. В PostgreSQL можно явно указать:
SELECT * FROM employees ORDER BY commission NULLS LAST;
В SQL Server можно использовать CASE в ORDER BY.
Вопрос
Можно ли использовать псевдоним в предложении WHERE?
Ответ
Нет. Псевдонимы, заданные в SELECT, недоступны в WHERE, потому что WHERE вычисляется до SELECT. Используйте исходное выражение или подзапрос.
Агрегатные функции и группировка
Вопрос
Что такое агрегатная функция в SQL?
Ответ
Агрегатная функция — это функция, которая выполняет вычисления над набором значений и возвращает одно результирующее значение. Примеры: COUNT, SUM, AVG, MIN, MAX.
Вопрос
Как подсчитать количество строк в таблице?
Ответ
Используется функция COUNT. Чтобы подсчитать все строки, включая NULL-значения, применяется COUNT(*). Пример:
SELECT COUNT(*) FROM employees;
Вопрос
В чём разница между COUNT(*) и COUNT(column)?
Ответ
COUNT(*) считает все строки, включая те, где все поля NULL. COUNT(column) считает только строки, где указанное поле не равно NULL.
Вопрос
Как найти сумму значений в столбце?
Ответ
Используется функция SUM. Пример:
SELECT SUM(salary) FROM employees;
Вопрос
Как вычислить среднее значение?
Ответ
Среднее значение вычисляется с помощью функции AVG. Пример:
SELECT AVG(salary) FROM employees;
Вопрос
Как найти минимальное и максимальное значения?
Ответ
Минимальное значение возвращает функция MIN, максимальное — MAX. Пример:
SELECT MIN(salary), MAX(salary) FROM employees;
Вопрос
Можно ли использовать агрегатные функции вместе с обычными столбцами?
Ответ
Только если обычные столбцы включены в предложение GROUP BY. Без группировки использование неключевых столбцов с агрегатами вызовет ошибку в большинстве СУБД.
Вопрос
Что делает предложение GROUP BY?
Ответ
GROUP BY группирует строки, имеющие одинаковые значения в указанных столбцах, чтобы к каждой группе можно было применить агрегатные функции.
Вопрос
Как найти среднюю зарплату по каждому отделу?
Ответ
Нужно сгруппировать по department_id и применить AVG:
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id;
Вопрос
Можно ли группировать по нескольким столбцам?
Ответ
Да. Например, чтобы получить статистику по отделам и должностям:
SELECT department_id, job_title, AVG(salary)
FROM employees
GROUP BY department_id, job_title;
Вопрос
Что произойдёт, если в SELECT указать столбец, не входящий в GROUP BY и не обёрнутый в агрегатную функцию?
Ответ
Большинство СУБД вернут ошибку. Это нарушает правило функциональной зависимости: значение такого столбца не определено однозначно для группы.
Вопрос
Как отфильтровать результаты после группировки?
Ответ
Для фильтрации групп используется предложение HAVING. Оно применяется после GROUP BY. Пример:
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 50000;
Вопрос
В чём разница между WHERE и HAVING?
Ответ
WHERE фильтрует строки до группировки, HAVING — группы после агрегации. WHERE не может содержать агрегатные функции, HAVING — может.
Вопрос
Можно ли использовать псевдоним в HAVING?
Ответ
В большинстве СУБД — нет. Псевдонимы из SELECT недоступны в HAVING. Нужно повторить выражение целиком или использовать подзапрос.
Вопрос
Как подсчитать количество уникальных значений в столбце?
Ответ
Используется COUNT(DISTINCT column). Пример:
SELECT COUNT(DISTINCT department_id) FROM employees;
Вопрос
Поддерживают ли все СУБД COUNT(DISTINCT)?
Ответ
Большинство современных СУБД поддерживают: PostgreSQL, MySQL, SQL Server, Oracle. SQLite также поддерживает. Однако в очень старых системах может отсутствовать.
Вопрос
Как найти общую сумму зарплат и количество сотрудников за один запрос?
Ответ
Можно использовать несколько агрегатных функций в одном SELECT:
SELECT SUM(salary), COUNT(*) FROM employees;
Вопрос
Что вернёт агрегатная функция, если в таблице нет строк?
Ответ
Функции SUM, AVG, MIN, MAX вернут NULL. Функция COUNT вернёт 0.
Вопрос
Можно ли использовать агрегатные функции в подзапросах?
Ответ
Да. Например, чтобы найти сотрудников с зарплатой выше средней:
SELECT name FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Вопрос
Как обработать NULL при использовании SUM или AVG?
Ответ
NULL-значения автоматически игнорируются агрегатными функциями. Если нужно заменить NULL на 0, используется COALESCE:
SELECT AVG(COALESCE(salary, 0)) FROM employees;
Соединения (JOIN)
Вопрос
Что такое соединение (JOIN) в SQL?
Ответ
Соединение — это операция, объединяющая строки из двух или более таблиц на основе связанного столбца между ними. Оно позволяет получать данные, распределённые по разным таблицам, в одном результате.
Вопрос
Какие основные типы JOIN существуют?
Ответ
Основные типы:
- INNER JOIN — возвращает только совпадающие строки.
- LEFT JOIN (или LEFT OUTER JOIN) — возвращает все строки из левой таблицы и совпадающие из правой.
- RIGHT JOIN (или RIGHT OUTER JOIN) — возвращает все строки из правой таблицы и совпадающие из левой.
- FULL OUTER JOIN — возвращает все строки из обеих таблиц, дополняя NULL там, где нет совпадений.
Вопрос
Что делает INNER JOIN?
Ответ
INNER JOIN возвращает только те строки, для которых существует совпадение по условию соединения в обеих таблицах. Пример:
SELECT e.name, d.name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
Вопрос
Что делает LEFT JOIN?
Ответ
LEFT JOIN возвращает все строки из левой (первой) таблицы и соответствующие строки из правой. Если совпадения нет, поля из правой таблицы заполняются NULL. Пример:
SELECT e.name, d.name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
Вопрос
Когда использовать RIGHT JOIN?
Ответ
RIGHT JOIN используется редко. Он эквивалентен LEFT JOIN с перестановкой таблиц. Лучше переформулировать запрос с LEFT JOIN для лучшей читаемости.
Вопрос
Что такое FULL OUTER JOIN?
Ответ
FULL OUTER JOIN возвращает все строки из обеих таблиц. Если для строки нет совпадения в другой таблице, соответствующие столбцы заполняются NULL. Поддерживается не во всех СУБД (например, MySQL не поддерживает).
Вопрос
Можно ли соединять более двух таблиц?
Ответ
Да. Можно соединять любое количество таблиц, указывая каждое соединение отдельно. Пример:
SELECT e.name, d.name, p.project_name
FROM employees e
JOIN departments d ON e.department_id = d.id
JOIN projects p ON e.project_id = p.id;
Вопрос
Что такое самосоединение (self-join)?
Ответ
Самосоединение — это соединение таблицы с самой собой. Оно полезно, когда нужно сравнить строки внутри одной таблицы. Пример — поиск сотрудников и их менеджеров:
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
Вопрос
Чем отличается JOIN от WHERE при соединении таблиц?
Ответ
Использование JOIN делает запрос более читаемым и соответствует стандарту SQL. WHERE для соединения — устаревший подход (неявный JOIN), который может привести к ошибкам, особенно при смешивании с фильтрацией.
Вопрос
Что произойдёт, если не указать условие в JOIN?
Ответ
Будет выполнен CROSS JOIN — декартово произведение всех строк первой таблицы со всеми строками второй. Это часто приводит к огромному и бессмысленному результату.
Вопрос
Как избежать дубликатов при соединении?
Ответ
Убедиться, что условия соединения корректны и используют уникальные ключи. При необходимости применить DISTINCT или агрегацию.
Вопрос
Можно ли использовать алиасы в JOIN?
Ответ
Да. Алиасы упрощают чтение запросов с соединениями. Пример:
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id;
Вопрос
Как соединить таблицы, если связь не по первичному ключу?
Ответ
Можно соединять по любому столбцу, даже если он не является ключом. Однако это может привести к неоднозначным или избыточным результатам, если значения не уникальны.
Вопрос
Что такое неявное соединение?
Ответ
Неявное соединение — это запись нескольких таблиц в FROM с фильтрацией через WHERE. Пример:
SELECT * FROM employees e, departments d
WHERE e.department_id = d.id;
Этот стиль считается устаревшим.
Вопрос
Поддерживает ли SQLite FULL OUTER JOIN?
Ответ
Нет. SQLite не поддерживает FULL OUTER JOIN. Его можно эмулировать с помощью UNION и LEFT/RIGHT JOIN.
Вопрос
Как работает LEFT JOIN с условием в ON и в WHERE?
Ответ
Условие в ON фильтрует строки до соединения, а в WHERE — после. Например, WHERE d.name IS NOT NULL после LEFT JOIN превратит его в INNER JOIN.
Вопрос
Можно ли использовать функции в условии JOIN?
Ответ
Да, но это может снижать производительность, так как индексы не используются. Пример:
SELECT * FROM users u
JOIN logs l ON LOWER(u.email) = LOWER(l.user_email);
Вопрос
Что такое NATURAL JOIN?
Ответ
NATURAL JOIN автоматически соединяет таблицы по всем столбцам с одинаковыми именами. Использовать его не рекомендуется, так как поведение зависит от структуры таблиц и может быть непредсказуемым.
Вопрос
Как найти записи, которые есть в одной таблице, но отсутствуют в другой?
Ответ
Используется LEFT JOIN с проверкой на NULL:
SELECT e.*
FROM employees e
LEFT JOIN contracts c ON e.id = c.employee_id
WHERE c.employee_id IS NULL;
Вопрос
Можно ли соединять таблицы из разных баз данных?
Ответ
В некоторых СУБД (например, PostgreSQL, SQL Server) можно указывать полное имя: database.schema.table. В других (например, SQLite) — нельзя.
Подзапросы и вложенные запросы
Вопрос
Что такое подзапрос (subquery)?
Ответ
Подзапрос — это запрос, вложенный внутрь другого запроса. Он может находиться в SELECT, FROM, WHERE или HAVING и выполняется перед основным запросом.
Вопрос
Где можно использовать подзапрос?
Ответ
Подзапрос может использоваться:
- В WHERE для фильтрации строк.
- В SELECT как скалярное значение.
- В FROM как производная таблица (inline view).
- В HAVING для фильтрации групп.
Вопрос
Что такое скалярный подзапрос?
Ответ
Скалярный подзапрос — это подзапрос, возвращающий ровно одно значение (одну строку и один столбец). Он может использоваться в любом месте, где допустимо выражение. Пример:
SELECT name, (SELECT COUNT(*) FROM orders WHERE user_id = users.id) AS order_count
FROM users;
Вопрос
Что произойдёт, если скалярный подзапрос вернёт больше одной строки?
Ответ
Большинство СУБД вернут ошибку выполнения. Скалярный подзапрос обязан возвращать не более одного значения.
Вопрос
Как использовать подзапрос в WHERE с оператором IN?
Ответ
Оператор IN проверяет, входит ли значение в список, возвращаемый подзапросом. Пример:
SELECT * FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE location = 'Москва');
Вопрос
Как найти сотрудников с максимальной зарплатой?
Ответ
Можно использовать подзапрос с агрегатной функцией:
SELECT * FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
Вопрос
Что делает оператор EXISTS?
Ответ
EXISTS проверяет, возвращает ли подзапрос хотя бы одну строку. Если да — условие истинно. Пример:
SELECT * FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
Вопрос
Почему в EXISTS часто пишут SELECT 1?
Ответ
Потому что EXISTS проверяет только наличие строк, а не их содержимое. SELECT 1 — краткая и эффективная форма, не требующая чтения реальных данных.
Вопрос
В чём разница между IN и EXISTS?
Ответ
IN сравнивает значение со списком. EXISTS проверяет существование связанных строк. EXISTS обычно эффективнее при работе с большими таблицами и коррелированными подзапросами.
Вопрос
Что такое коррелированный подзапрос?
Ответ
Коррелированный подзапрос — это подзапрос, который ссылается на столбцы из внешнего запроса. Он выполняется отдельно для каждой строки внешнего запроса. Пример:
SELECT e1.name
FROM employees e1
WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = e1.department_id);
Вопрос
Может ли подзапрос возвращать несколько столбцов?
Ответ
Да, но только если он используется с операторами сравнения кортежей, например:
SELECT * FROM products
WHERE (category_id, price) IN (SELECT category_id, MAX(price) FROM products GROUP BY category_id);
Вопрос
Как использовать подзапрос в FROM?
Ответ
Подзапрос в FROM создаёт временную таблицу (производную таблицу), которую можно использовать как обычную. Пример:
SELECT dept_avg.department_id, dept_avg.avg_sal
FROM (SELECT department_id, AVG(salary) AS avg_sal FROM employees GROUP BY department_id) AS dept_avg
WHERE avg_sal > 50000;
Вопрос
Нужно ли давать алиас подзапросу в FROM?
Ответ
Да. Во всех современных СУБД подзапрос в FROM должен иметь алиас.
Вопрос
Как найти вторую по величине зарплату?
Ответ
Можно использовать подзапрос с DISTINCT и LIMIT (в PostgreSQL/MySQL):
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
Или через подзапрос:
SELECT MAX(salary)
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
Вопрос
Можно ли использовать агрегатные функции внутри коррелированного подзапроса?
Ответ
Да. Это распространённая практика для сравнения значений с групповыми метриками, например, выше среднего по отделу.
Вопрос
Как оптимизировать медленный подзапрос?
Ответ
Заменить его на JOIN, если возможно. Использовать индексы на столбцах, участвующих в условиях. Избегать коррелированных подзапросов в больших таблицах.
Вопрос
Что вернёт подзапрос, если таблица пуста?
Ответ
Если подзапрос возвращает агрегатную функцию, например MAX, он вернёт NULL. Если используется в IN — условие будет ложным. Если используется как скаляр — вернёт NULL.
Вопрос
Можно ли вложить подзапрос в другой подзапрос?
Ответ
Да. Уровень вложенности ограничен только читаемостью и возможностями СУБД. Однако глубокая вложенность затрудняет отладку и оптимизацию.
Вопрос
Как проверить, есть ли дубликаты записей с помощью подзапроса?
Ответ
Можно использовать EXISTS с самосоединением:
SELECT e1.id
FROM employees e1
WHERE EXISTS (
SELECT 1 FROM employees e2
WHERE e2.email = e1.email AND e2.id != e1.id
);
Вопрос
Что такое производная таблица?
Ответ
Производная таблица — это результат подзапроса, используемого в предложении FROM. Она существует временно в рамках выполнения запроса и должна иметь алиас.
Оконные функции и аналитические запросы
Вопрос
Что такое оконная функция в SQL?
Ответ
Оконная функция — это функция, которая выполняет вычисления по набору строк, связанных с текущей строкой, не сворачивая их в одну строку (в отличие от агрегатных функций). Она использует предложение OVER для определения окна.
Вопрос
Как объявить оконную функцию?
Ответ
Оконная функция записывается как функция(...) OVER (...). Внутри OVER указываются PARTITION BY (разделение), ORDER BY (сортировка) и, при необходимости, FRAME (границы окна). Пример:
SELECT name, department_id, salary,
AVG(salary) OVER (PARTITION BY department_id) AS dept_avg
FROM employees;
Вопрос
Что делает PARTITION BY в оконной функции?
Ответ
PARTITION BY разделяет строки на группы (партиции), внутри которых выполняется вычисление. Это аналог GROUP BY, но без свёртки строк.
Вопрос
Чем отличается оконная функция от агрегатной?
Ответ
Агрегатная функция сворачивает группу строк в одну. Оконная функция сохраняет все строки исходного результата и добавляет к каждой вычисленное значение, относящееся к её окну.
Вопрос
Как пронумеровать строки в результате запроса?
Ответ
Используется функция ROW_NUMBER() с OVER. Пример:
SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank, name, salary
FROM employees;
Вопрос
В чём разница между ROW_NUMBER(), RANK() и DENSE_RANK()?
Ответ
- ROW_NUMBER() присваивает уникальный номер каждой строке, даже при равенстве значений.
- RANK() присваивает одинаковый ранг равным значениям, но следующий ранг пропускает позиции (например, 1, 1, 3).
- DENSE_RANK() также даёт одинаковый ранг равным значениям, но не пропускает позиции (например, 1, 1, 2).
Вопрос
Как найти топ-3 сотрудников по зарплате в каждом отделе?
Ответ
Можно использовать оконную функцию с фильтрацией:
WITH ranked AS (
SELECT name, department_id, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
FROM employees
)
SELECT name, department_id, salary
FROM ranked
WHERE rn <= 3;
Вопрос
Что такое фрейм (frame) в оконной функции?
Ответ
Фрейм определяет подмножество строк внутри партиции, участвующих в вычислении. Например, ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW означает «все строки от начала партиции до текущей».
Вопрос
Как вычислить накопительную сумму?
Ответ
Используется SUM с порядком и фреймом по умолчанию или явным:
SELECT date, revenue,
SUM(revenue) OVER (ORDER BY date ROWS UNBOUNDED PRECEDING) AS running_total
FROM sales;
Вопрос
Можно ли использовать оконные функции в WHERE?
Ответ
Нет. Оконные функции вычисляются после предложения WHERE. Чтобы фильтровать по результату оконной функции, нужно использовать подзапрос или CTE.
Вопрос
Что такое CTE и зачем он нужен с оконными функциями?
Ответ
CTE (Common Table Expression) — это именованный временный результат запроса, определяемый через WITH. Он упрощает использование оконных функций, когда требуется фильтрация по их результату.
Вопрос
Как сравнить значение строки со следующей или предыдущей?
Ответ
Используются функции LAG (предыдущая) и LEAD (следующая). Пример:
SELECT date, revenue,
LAG(revenue) OVER (ORDER BY date) AS prev_revenue
FROM sales;
Вопрос
Можно ли использовать оконные функции без ORDER BY?
Ответ
Да, если функция не требует порядка (например, COUNT(*) OVER (PARTITION BY dept)). Но для ранжирования, LAG/LEAD и накопительных сумм ORDER BY обязателен.
Вопрос
Поддерживают ли все СУБД оконные функции?
Ответ
Современные СУБД поддерживают: PostgreSQL, SQL Server (с 2005), Oracle, MySQL (с 8.0), SQLite (с 3.25.0). В старых версиях MySQL и SQLite оконные функции недоступны.
Вопрос
Как вычислить процент от общего итога?
Ответ
Делится значение на сумму по всем строкам:
SELECT product, revenue,
revenue * 100.0 / SUM(revenue) OVER () AS pct_of_total
FROM sales;
Вопрос
Что означает OVER () без параметров?
Ответ
Это означает, что окно включает все строки результата запроса, без разделения и без сортировки. Такое окно используется, например, для расчёта общей суммы.
Вопрос
Как найти разницу между текущим и предыдущим значением?
Ответ
Комбинируются LAG и арифметика:
SELECT date, revenue,
revenue - LAG(revenue) OVER (ORDER BY date) AS delta
FROM sales;
Вопрос
Можно ли использовать несколько оконных функций в одном SELECT?
Ответ
Да. Каждая функция может иметь своё определение окна. Пример:
SELECT name,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS global_rank,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS dept_rank
FROM employees;
Вопрос
Как обработать первую строку при использовании LAG?
Ответ
LAG возвращает NULL для первой строки. Можно задать значение по умолчанию:
LAG(revenue, 1, 0) OVER (ORDER BY date)
Это вернёт 0 вместо NULL.
Вопрос
Что такое RANGE в определении окна?
Ответ
RANGE задаёт логические границы окна на основе значений столбца сортировки, а не количества строк. Например, RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW включает все строки за последние 7 дней.
Транзакции, целостность и блокировки
Вопрос
Что такое транзакция в базе данных?
Ответ
Транзакция — это последовательность операций с данными, выполняемых как единое логическое целое. Она гарантирует, что либо все изменения будут применены, либо ни одно из них не будет сохранено.
Вопрос
Какие свойства имеет транзакция (ACID)?
Ответ
Транзакция обладает четырьмя свойствами:
- Atomicity (Атомарность) — все операции выполняются или ни одна.
- Consistency (Согласованность) — транзакция переводит базу из одного согласованного состояния в другое.
- Isolation (Изолированность) — параллельные транзакции не мешают друг другу.
- Durability (Долговечность) — после подтверждения изменения сохраняются даже при сбое системы.
Вопрос
Как начать транзакцию в SQL?
Ответ
В большинстве СУБД транзакция начинается автоматически с первой модифицирующей команды (INSERT, UPDATE, DELETE). Явно можно указать:
BEGIN TRANSACTION;
-- или просто
BEGIN;
Вопрос
Как зафиксировать изменения транзакции?
Ответ
Используется команда COMMIT. После её выполнения изменения становятся постоянными и видимыми другим транзакциям. Пример:
COMMIT;
Вопрос
Как отменить изменения транзакции?
Ответ
Используется команда ROLLBACK. Все изменения, сделанные с начала транзакции, отменяются. Пример:
ROLLBACK;
Вопрос
Что такое точка сохранения (savepoint)?
Ответ
Точка сохранения — это промежуточная метка внутри транзакции, к которой можно откатиться, не отменяя всю транзакцию. Пример:
SAVEPOINT sp1;
-- ... какие-то действия ...
ROLLBACK TO sp1;
Вопрос
Что такое уровень изоляции транзакций?
Ответ
Уровень изоляции определяет, как транзакции взаимодействуют друг с другом при параллельном выполнении. Он влияет на видимость незафиксированных изменений и поведение при чтении.
Вопрос
Какие уровни изоляции поддерживаются в SQL?
Ответ
Стандарт SQL определяет четыре уровня:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
Реализация может отличаться в разных СУБД.
Вопрос
Что такое «грязное чтение» (dirty read)?
Ответ
Грязное чтение — это чтение данных, изменённых другой транзакцией, которая ещё не выполнила COMMIT. Это возможно только на уровне READ UNCOMMITTED.
Вопрос
Что такое «неповторяющееся чтение» (non-repeatable read)?
Ответ
Неповторяющееся чтение — это ситуация, когда при повторном чтении одной и той же строки в рамках одной транзакции возвращаются разные значения, потому что другая транзакция изменила и зафиксировала данные.
Вопрос
Что такое «фантомное чтение» (phantom read)?
Ответ
Фантомное чтение — это появление новых строк при повторном выполнении одного и того же запроса в рамках транзакции, вызванное вставкой и фиксацией другой транзакцией.
Вопрос
Какой уровень изоляции предотвращает фантомные чтения?
Ответ
SERIALIZABLE. На этом уровне система гарантирует полную изоляцию, эквивалентную последовательному выполнению транзакций.
Вопрос
Как установить уровень изоляции в PostgreSQL?
Ответ
Командой SET TRANSACTION:
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- ... запросы ...
COMMIT;
Вопрос
Что такое блокировка (lock) в СУБД?
Ответ
Блокировка — это механизм, предотвращающий одновременный доступ нескольких транзакций к одним и тем же данным, чтобы обеспечить целостность и изоляцию.
Вопрос
Какие типы блокировок существуют?
Ответ
Основные типы:
- Shared lock (S) — разрешает чтение, но не запись. Несколько транзакций могут удерживать shared-блокировки одновременно.
- Exclusive lock (X) — разрешает запись и запрещает любые другие блокировки на те же данные.
Вопрос
Что такое взаимоблокировка (deadlock)?
Ответ
Взаимоблокировка — это ситуация, когда две или более транзакций ожидают освобождения ресурсов, удерживаемых друг другом, и ни одна не может продолжиться.
Вопрос
Как СУБД обнаруживает и разрешает deadlocks?
Ответ
СУБД периодически проверяет граф ожиданий. При обнаружении цикла одна из транзакций выбирается в качестве «жертвы» и откатывается, чтобы разблокировать остальные.
Вопрос
Можно ли избежать взаимоблокировок?
Ответ
Можно снизить вероятность, если все транзакции обращаются к ресурсам в одинаковом порядке, удерживают блокировки минимально возможное время и используют более высокие уровни изоляции только при необходимости.
Вопрос
Что делает команда SELECT FOR UPDATE?
Ответ
SELECT FOR UPDATE ставит эксклюзивную блокировку на выбранные строки, чтобы другие транзакции не могли их изменить до завершения текущей транзакции. Пример:
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
Вопрос
Поддерживает ли SQLite транзакции?
Ответ
Да. SQLite поддерживает ACID-транзакции, но использует упрощённую модель блокировок на уровне всей базы данных в режиме WAL или на уровне страниц в других режимах.
Оптимизация запросов, индексы и планы выполнения
Вопрос
Что такое план выполнения запроса (execution plan)?
Ответ
План выполнения — это последовательность операций, которые СУБД выполняет для получения результата запроса. Он показывает, какие таблицы сканируются, какие индексы используются, как соединяются данные и сколько строк обработано.
Вопрос
Как получить план выполнения в PostgreSQL?
Ответ
Используется команда EXPLAIN. Для получения реальных времён и количества строк — EXPLAIN ANALYZE. Пример:
EXPLAIN ANALYZE SELECT * FROM employees WHERE department_id = 5;
Вопрос
Как получить план выполнения в MySQL?
Ответ
Используется команда EXPLAIN перед запросом. Пример:
EXPLAIN SELECT * FROM employees WHERE department_id = 5;
Вопрос
Как получить план выполнения в SQL Server?
Ответ
Можно использовать SET SHOWPLAN_TEXT ON или нажать кнопку «Display Estimated Execution Plan» в SSMS. Также работает команда:
SET STATISTICS IO ON;
-- затем сам запрос
Вопрос
Что означает «полное сканирование таблицы» (Seq Scan / Table Scan)?
Ответ
Это операция, при которой СУБД читает все строки таблицы подряд. Она используется, когда нет подходящего индекса или когда ожидается, что будет выбрано большинство строк.
Вопрос
Что такое индекс в базе данных?
Ответ
Индекс — это вспомогательная структура данных, ускоряющая поиск строк по значениям одного или нескольких столбцов. Он работает аналогично оглавлению в книге.
Вопрос
Какие типы индексов существуют?
Ответ
Основные типы:
- B-дерево (B-tree) — стандартный индекс для сравнений и диапазонов.
- Хеш-индекс — эффективен только для точного равенства (=).
- GIN — для массивов и полнотекстового поиска (PostgreSQL).
- GiST — для геометрических и нестандартных данных.
- Кластеризованный индекс — определяет физический порядок хранения строк (SQL Server, Oracle).
Вопрос
Когда индекс ускоряет запрос?
Ответ
Индекс ускоряет запрос, когда условие WHERE, JOIN или ORDER BY использует столбцы, входящие в индекс, особенно если выбирается небольшая часть строк.
Вопрос
Когда индекс не используется?
Ответ
Индекс не используется, если:
- запрос выбирает большую часть таблицы (СУБД предпочитает полное сканирование),
- в условии применяется функция к столбцу (
WHERE UPPER(name) = 'IVAN'), - используется
LIKEс маской, начинающейся с%(LIKE '%ivan'), - статистика устарела.
Вопрос
Что такое составной индекс?
Ответ
Составной индекс строится по нескольким столбцам. Порядок столбцов важен: индекс эффективен, если запрос фильтрует по первому столбцу, или по первому и второму и так далее.
Вопрос
Как создать индекс в SQL?
Ответ
Используется команда CREATE INDEX. Пример:
CREATE INDEX idx_employees_dept ON employees (department_id);
Для составного индекса:
CREATE INDEX idx_employees_dept_sal ON employees (department_id, salary);
Вопрос
Может ли индекс замедлить работу базы?
Ответ
Да. Индексы замедляют операции вставки, обновления и удаления, так как СУБД должна поддерживать их в актуальном состоянии. Чем больше индексов — тем выше накладные расходы на запись.
Вопрос
Что такое покрывающий индекс (covering index)?
Ответ
Покрывающий индекс содержит все столбцы, необходимые для выполнения запроса. Это позволяет СУБД получить результат, не обращаясь к самой таблице (только к индексу).
Вопрос
Как сделать индекс покрывающим в PostgreSQL?
Ответ
Можно использовать INCLUDE для добавления неключевых столбцов:
CREATE INDEX idx_emp_dept_covering ON employees (department_id) INCLUDE (name, salary);
Вопрос
Что такое кардинальность столбца?
Ответ
Кардинальность — это количество уникальных значений в столбце. Высокая кардинальность (например, email) делает индекс более эффективным для фильтрации.
Вопрос
Зачем нужна статистика в СУБД?
Ответ
Статистика помогает оптимизатору запросов оценить количество строк, соответствующих условию, и выбрать наиболее эффективный план выполнения.
Вопрос
Как обновить статистику в PostgreSQL?
Ответ
Командой ANALYZE:
ANALYZE employees;
Это собирает статистику по распределению значений в таблице.
Вопрос
Что такое cost в плане выполнения PostgreSQL?
Ответ
Cost — это относительная оценка затрат на выполнение операции, выраженная в абстрактных единицах. Она основана на времени чтения страниц и CPU-затратах. Низкий cost обычно означает более быстрый план.
Вопрос
Как оптимизировать медленный запрос?
Ответ
Шаги оптимизации:
- Получить план выполнения.
- Убедиться, что используются индексы.
- Переписать запрос, избегая функций над столбцами в WHERE.
- Рассмотреть возможность денормализации или материализованных представлений.
- Обновить статистику.
Вопрос
Что такое N+1 проблема?
Ответ
N+1 проблема возникает, когда для каждой из N строк основного запроса выполняется дополнительный запрос (например, в ORM). Это приводит к большому числу обращений к базе. Решение — использовать JOIN или eager loading.
Представления, процедуры, триггеры и расширенные возможности
Вопрос
Что такое представление (VIEW) в SQL?
Ответ
Представление — это виртуальная таблица, определённая запросом. Оно не хранит данные физически (за исключением материализованных представлений), а выполняет свой запрос при каждом обращении.
Вопрос
Как создать представление?
Ответ
Используется команда CREATE VIEW. Пример:
CREATE VIEW high_salary_employees AS
SELECT id, name, salary
FROM employees
WHERE salary > 70000;
Вопрос
Можно ли обновлять данные через представление?
Ответ
В некоторых случаях — да. Обновление возможно, если представление ссылается на одну таблицу, не содержит DISTINCT, GROUP BY, агрегатных функций и всех NOT NULL-столбцов базовой таблицы.
Вопрос
Что такое материализованное представление?
Ответ
Материализованное представление — это представление, результат которого сохраняется физически на диске. Оно обновляется по расписанию или вручную и позволяет ускорить сложные аналитические запросы.
Вопрос
Как обновить материализованное представление в PostgreSQL?
Ответ
Командой REFRESH MATERIALIZED VIEW. Пример:
REFRESH MATERIALIZED VIEW sales_summary;
Вопрос
Что такое хранимая процедура?
Ответ
Хранимая процедура — это именованный блок кода, сохранённый в базе данных и выполняемый по вызову. Она может принимать параметры, выполнять сложную логику и возвращать результаты.
Вопрос
Как создать хранимую процедуру в PostgreSQL?
Ответ
Используется CREATE PROCEDURE с языком PL/pgSQL. Пример:
CREATE PROCEDURE give_raise(emp_id INT, amount NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE employees SET salary = salary + amount WHERE id = emp_id;
COMMIT;
END;
$$;
Вопрос
Что такое функция в СУБД?
Ответ
Функция — это именованный блок кода, который возвращает значение и может использоваться в выражениях SQL (например, в SELECT). В отличие от процедуры, функция не может выполнять транзакции в некоторых СУБД.
Вопрос
Как вызвать хранимую процедуру?
Ответ
В PostgreSQL используется CALL:
CALL give_raise(101, 5000);
В MySQL и SQL Server — просто имя процедуры:
CALL give_raise(101, 5000); -- MySQL
EXEC give_raise 101, 5000; -- SQL Server
Вопрос
Что такое триггер?
Ответ
Триггер — это специальный вид хранимого кода, который автоматически выполняется при наступлении определённого события (INSERT, UPDATE, DELETE) над таблицей или представлением.
Вопрос
Когда срабатывает триггер?
Ответ
Триггер может срабатывать до (BEFORE) или после (AFTER) события, а также вместо (INSTEAD OF) операции — для представлений. Он может быть на уровне строки или на уровне оператора.
Вопрос
Как создать триггер в PostgreSQL?
Ответ
Сначала создаётся функция, затем триггер. Пример:
CREATE FUNCTION log_employee_change()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO employee_log (emp_id, action, changed_at)
VALUES (NEW.id, 'UPDATE', NOW());
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_employee_update
AFTER UPDATE ON employees
FOR EACH ROW
EXECUTE FUNCTION log_employee_change();
Вопрос
Что содержат переменные OLD и NEW в триггере?
Ответ
В триггерах на UPDATE и DELETE переменная OLD содержит старые значения строки. В триггерах на INSERT и UPDATE переменная NEW содержит новые значения строки.
Вопрос
Можно ли отключить триггер?
Ответ
Да. В PostgreSQL:
ALTER TABLE employees DISABLE TRIGGER tr_employee_update;
Это полезно при массовой загрузке данных.
Вопрос
Что такое временная таблица?
Ответ
Временная таблица существует только в течение сессии или транзакции и автоматически удаляется после её завершения. Она видна только текущему соединению. Пример:
CREATE TEMP TABLE temp_results (id INT, value TEXT);
Вопрос
Что такое рекурсивный CTE?
Ответ
Рекурсивный CTE — это обобщённое табличное выражение, ссылающееся само на себя. Он используется для обхода иерархических структур, например, дерева подразделений. Пример:
WITH RECURSIVE subordinates AS (
SELECT id, name, manager_id FROM employees WHERE id = 1
UNION ALL
SELECT e.id, e.name, e.manager_id
FROM employees e
INNER JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;
Вопрос
Поддерживает ли MySQL рекурсивные CTE?
Ответ
Да, начиная с версии 8.0. Ранние версии не поддерживают.
Вопрос
Что такое партиционирование таблицы?
Ответ
Партиционирование — это разделение большой таблицы на более мелкие физические части (партиции) по правилу (например, по диапазону дат). Это ускоряет запросы и упрощает обслуживание.
Вопрос
Какие типы партиционирования существуют?
Ответ
Основные типы:
- Range — по диапазону значений (например, дата).
- List — по явному списку значений.
- Hash — по хешу от значения, равномерно распределяя данные.
- Composite — комбинация нескольких методов.
Вопрос
Что такое каскадное удаление (ON DELETE CASCADE)?
Ответ
Каскадное удаление — это поведение внешнего ключа, при котором удаление родительской записи автоматически удаляет все связанные дочерние записи. Пример:
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
Специфика СУБД и продвинутые сценарии
Вопрос
Как в PostgreSQL получить текущую дату и время?
Ответ
Используется функция NOW() или CURRENT_TIMESTAMP. Пример:
SELECT NOW();
Вопрос
Как в MySQL получить текущую дату и время?
Ответ
Используется функция NOW(). Пример:
SELECT NOW();
Вопрос
Как в SQL Server получить текущую дату и время?
Ответ
Используется функция GETDATE() или SYSDATETIME(). Пример:
SELECT GETDATE();
Вопрос
Как преобразовать строку в дату в PostgreSQL?
Ответ
Используется приведение типов или функция TO_DATE. Пример:
SELECT '2025-03-27'::DATE;
-- или
SELECT TO_DATE('27/03/2025', 'DD/MM/YYYY');
Вопрос
Как объединить результаты двух запросов без дубликатов?
Ответ
Используется оператор UNION. Он автоматически удаляет дубликаты. Пример:
SELECT name FROM employees
UNION
SELECT name FROM contractors;
Вопрос
Как объединить результаты двух запросов с сохранением дубликатов?
Ответ
Используется оператор UNION ALL. Он не удаляет дубликаты и работает быстрее. Пример:
SELECT name FROM employees
UNION ALL
SELECT name FROM former_employees;
Вопрос
Что делает оператор INTERSECT?
Ответ
INTERSECT возвращает строки, присутствующие в результатах обоих запросов. Дубликаты удаляются. Пример:
SELECT product_id FROM orders_2024
INTERSECT
SELECT product_id FROM orders_2025;
Вопрос
Что делает оператор EXCEPT?
Ответ
EXCEPT возвращает строки из первого запроса, которых нет во втором. Дубликаты удаляются. Пример:
SELECT customer_id FROM all_customers
EXCEPT
SELECT customer_id FROM vip_customers;
Вопрос
Поддерживает ли MySQL INTERSECT и EXCEPT?
Ответ
Нет. MySQL не поддерживает INTERSECT и EXCEPT. Их можно эмулировать с помощью JOIN или подзапросов с NOT EXISTS.
Вопрос
Как вставить данные и сразу вернуть вставленную строку?
Ответ
В PostgreSQL используется RETURNING:
INSERT INTO users (name, email)
VALUES ('Анна', 'anna@example.com')
RETURNING id, name;
В SQL Server — OUTPUT. В MySQL такой возможности нет.
Вопрос
Как обновить данные на основе другой таблицы?
Ответ
В PostgreSQL и SQL Server можно использовать UPDATE с JOIN:
UPDATE employees e
SET salary = s.new_salary
FROM salary_updates s
WHERE e.id = s.employee_id;
В MySQL синтаксис немного отличается:
UPDATE employees e
JOIN salary_updates s ON e.id = s.employee_id
SET e.salary = s.new_salary;
Вопрос
Как удалить дубликаты строк, оставив одну?
Ответ
Можно использовать оконную функцию с CTE:
WITH duplicates AS (
SELECT ctid,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS rn
FROM users
)
DELETE FROM users
WHERE ctid IN (SELECT ctid FROM duplicates WHERE rn > 1);
(В PostgreSQL ctid — физический идентификатор строки.)
Вопрос
Как проверить существование таблицы перед её созданием?
Ответ
В PostgreSQL:
CREATE TABLE IF NOT EXISTS my_table (...);
В MySQL и SQL Server аналогичный синтаксис поддерживается.
Вопрос
Как получить список всех таблиц в базе?
Ответ
В PostgreSQL:
SELECT tablename FROM pg_tables WHERE schemaname = 'public';
В MySQL:
SHOW TABLES;
В SQL Server:
SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE';
Вопрос
Как получить структуру таблицы?
Ответ
В PostgreSQL: \d table_name в psql или запрос к information_schema.columns.
В MySQL: DESCRIBE table_name или SHOW CREATE TABLE table_name.
В SQL Server: sp_help table_name.
Вопрос
Что такое UPSERT?
Ответ
UPSERT — это операция «вставить или обновить». Если строка существует — она обновляется, если нет — вставляется новая.
Вопрос
Как реализовать UPSERT в PostgreSQL?
Ответ
Используется INSERT ... ON CONFLICT:
INSERT INTO users (id, email) VALUES (1, 'test@example.com')
ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email;
Вопрос
Как реализовать UPSERT в MySQL?
Ответ
Используется INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO users (id, email) VALUES (1, 'test@example.com')
ON DUPLICATE KEY UPDATE email = VALUES(email);
Вопрос
Как реализовать UPSERT в SQL Server?
Ответ
Используется MERGE:
MERGE users AS target
USING (SELECT 1 AS id, 'test@example.com' AS email) AS source
ON target.id = source.id
WHEN MATCHED THEN
UPDATE SET email = source.email
WHEN NOT MATCHED THEN
INSERT (id, email) VALUES (source.id, source.email);
Вопрос
Как экранировать спецсимволы в LIKE?
Ответ
Используется ESCAPE. Например, чтобы найти строку с символом %:
SELECT * FROM products WHERE name LIKE '%50\%%' ESCAPE '\';