СИЭУиП • Методическое руководство преподавателя

Тема 5. Организация запросов SQL — Операторы манипулирования данными

Развернутые методические указания к проведению теоретического занятия по синтаксису, механизмам выполнения, транзакционному протоколированию и оптимизации DML-операторов (INSERT, UPDATE, DELETE, TRUNCATE) в СУБД PostgreSQL.

Дисциплина ОП.08 Основы проектирования баз данных
Раздел программы Тема 5 (§2.2 с.7–8 рабочей программы)
Порядковый номер Занятие №31 (4-й семестр)
Регламент времени 80 мин (основной) / 60 мин (сокращенный)

1. Педагогическая концепция и целеполагание

Настоящее занятие открывает фундаментальный блок языка манипулирования данными (Data Manipulation Language — DML). Если предыдущие занятия были сфокусированы на проектировании статических схем и декларативных ограничениях целостности (DDL), то данное занятие переводит студентов в плоскость динамической обработки информации в промышленных реляционных СУБД.

Дидактические цели:

Формируемые профессиональные компетенции (ФГОС СПО 09.02.07):

2. Детальный хронометраж учебного занятия (80 и 60 минут)

В зависимости от графика учебного процесса преподаватель применяет основной 80-минутный регламент пары (двойной академический час) либо сокращенный 60-минутный регламент. Структура этапов сохраняется, оптимизируется глубина разбора кейсов и длительность дискуссионной части.

Этап занятия Основной (80 мин) Сокращенный (60 мин) Ключевая деятельность преподавателя и студентов
1. Организационный момент и мотивация 5 минут 3 минуты Приветствие, фиксация явки. Мотивационный кейс: аварийное выполнение UPDATE без WHERE на 1.5 млн записей биллинга и сбой продакшна. Формулировка целей.
2. Актуализация опорных знаний 8 минут 5 минут Блиц-опрос: ограничения PRIMARY KEY, UNIQUE, FOREIGN KEY, поведение автоинкрементных полей (SERIAL, IDENTITY) и назначение транзакций.
3. Сообщение новых знаний: Лекция 37 минут 27 минут Интерактивная лекция с презентацией: синтаксис INSERT (одиночный, batch, INSERT...SELECT), псевдотаблица EXCLUDED и UPSERT, UPDATE с FROM/JOIN, подзапросы, RETURNING, DELETE vs TRUNCATE, влияние на WAL и B-Tree индексы.
4. Разбор эталонного инженерного кейса 12 минут 10 минут Демонстрация сквозного кейса на проекторе в psql: пакетная вставка накладной склада, разрешение коллизии остатка товара через UPSERT, отбор удаляемых записей с фиксацией в аудите через RETURNING.
5. Первичное закрепление материала 12 минут 11 минут Индивидуальная экспресс-работа с интерактивным рабочим листом zanyatie.html по 4 вариантам, проектирование комплексных DML-запросов, самопроверка.
6. Подведение итогов, рефлексия, ДЗ 6 минут 4 минуты Разбор слайда 15 с культовым интернет-мемом Bobby Tables (xkcd #327), анализ типичных ошибок, инструктаж по резервному ДЗ domashnee_zadanie.html.

3. Фундаментальный технологический стек: Язык манипулирования данными (DML)

3.1. Оператор INSERT INTO: Архитектура и синтаксические конструкции

Оператор INSERT INTO предназначен для добавления новых строк в таблицу. В современных высоконагруженных системах одиночные вставки уступают место пакетированным и декларативно-безопасным операциям.

-- Одиночная вставка с явным указанием целевых атрибутов
INSERT INTO warehouse_inventory (sku, product_name, quantity, unit_price)
VALUES ('SKU-00124', 'SSD NVMe 1TB Samsung 980', 45, 8490.00);
-- Пакетная вставка (Batch / Multi-row INSERT) 5 позиций
INSERT INTO warehouse_inventory (sku, product_name, quantity, unit_price)
VALUES 
  ('SKU-101', 'Процессор Intel Core i5-13400', 15, 18200.00),
  ('SKU-102', 'Материнская плата B760 DDR5', 20, 12500.00),
  ('SKU-103', 'Модуль памяти DDR5 32GB Kit', 35, 9800.00),
  ('SKU-104', 'Блок питания 750W Gold', 18, 8100.00),
  ('SKU-105', 'Корпус ATX Mesh Black', 12, 5400.00)
RETURNING id, sku, created_at;
-- Перенос закрытых договоров в архивную таблицу
INSERT INTO contracts_archive (contract_id, client_id, close_date, final_balance)
SELECT c.id, c.client_id, c.closed_at, c.balance
FROM active_contracts c
WHERE c.status = 'CLOSED' AND c.closed_at < CURRENT_DATE - INTERVAL '1 year';
-- Идемпотентный UPSERT складских остатков при повторной поставке
INSERT INTO warehouse_inventory (sku, product_name, quantity, unit_price)
VALUES ('SKU-101', 'Процессор Intel Core i5-13400', 10, 17900.00)
ON CONFLICT (sku) 
DO UPDATE SET 
  quantity = warehouse_inventory.quantity + EXCLUDED.quantity,
  unit_price = EXCLUDED.unit_price,
  updated_at = CURRENT_TIMESTAMP
RETURNING warehouse_inventory.id, warehouse_inventory.sku, warehouse_inventory.quantity;

3.2. Оператор UPDATE: Модификация по предикату и реляционные соединения

Оператор UPDATE изменяет существующие кортежи. В реляционной архитектуре СУБД с моделью многоверсионности (MVCC) операция UPDATE физически представляет собой связку «пометить старую версию мертвой (dead tuple) + вставить новую версию (new tuple)».

-- Обновление статуса медицинского приема по состоянию счета в таблице Оплаты
UPDATE doctor_appointments AS a
SET 
  status = 'CONFIRMED',
  updated_at = CURRENT_TIMESTAMP
FROM payment_invoices AS p
WHERE a.id = p.appointment_id
  AND p.payment_status = 'PAID'
  AND a.status = 'PENDING_PAYMENT'
RETURNING a.id, a.patient_id, a.doctor_id, a.status;
-- Массовое начисление процентов по кредитам на основе статуса профиля заемщика
UPDATE credit_contracts AS c
SET accrued_interest = accrued_interest + (c.principal_debt * c.interest_rate / 365)
WHERE c.status = 'ACTIVE'
  AND EXISTS (
    SELECT 1 FROM client_profiles p 
    WHERE p.id = c.client_id AND p.is_blocked = FALSE
  )
RETURNING c.id, c.client_id, c.accrued_interest;

3.3. Оператор DELETE: Селективное удаление и аудит

Оператор DELETE удаляет строки, удовлетворяющие условию предиката WHERE. В PostgreSQL удаленные строки не освобождают место на диске немедленно: кортеж помечается удаленным в заголовке строки (устанавливается метка xmax, равная идентификатору текущей транзакции). Пространство очищается фоновым процессом VACUUM.

-- Селективное удаление отмененных приемов старше 1 года с возвратом данных
DELETE FROM doctor_appointments
WHERE status = 'CANCELLED' 
  AND appointment_date < CURRENT_DATE - INTERVAL '1 year'
RETURNING id, patient_fio, appointment_date, cancellation_reason;

3.4. Архитектурное сравнение: DELETE vs TRUNCATE

Сравнение операторов DELETE и TRUNCATE — классический вопрос инженерных собеседований и важный раздел дисциплины. Студенты часто ошибочно считают TRUNCATE синтаксическим сахаром для «DELETE без WHERE».

Характеристика Оператор DELETE Оператор TRUNCATE
Категория языка DML (Data Manipulation Language) DDL (Data Definition Language)
Уровень блокировки ROW EXCLUSIVE (позволяет параллельные SELECT и чтение других строк) ACCESS EXCLUSIVE (полная монопольная блокировка таблицы, блокирует любые SELECT)
Журналирование WAL (Write-Ahead Log) Записывает в журнал каждую удаляемую строку (высокая нагрузка на дисковый ввод/вывод при миллионах строк) Записывает только факт отсечения страниц и выделения нового файлового узла (минимальный объем WAL)
Физическое освобождение диска Дисковое пространство НЕ возвращается ОС; образуются «мертвые кортежи» (bloat), требующие VACUUM Мгновенно освобождает дисковые страницы путем пересоздания файла таблицы (новый relfilenode)
Индексные структуры Обходит B-Tree индексы, помечая ссылки; размер индексных файлов не уменьшается до REINDEX/VACUUM Мгновенно пересоздает B-Tree индексы как абсолютно пустые структуры
Счетчики автоинкремента Не сбрасывает значение IDENTITY / SEQUENCE (следующая вставка продолжит счетчик) Поддерживает опцию RESTART IDENTITY (по умолчанию CONTINUE IDENTITY)
Поддержка условий (WHERE) Да, удаляет любые селективные подмножества данных Нет, очищает таблицу целиком (или указанные партиции)
Срабатывание триггеров Вызывает триггеры уровня строки (FOR EACH ROW) и уровня оператора Вызывает ТОЛЬКО триггеры TRUNCATE уровня оператора (FOR EACH STATEMENT)

4. Педагогические приемы и сценарии вовлечения

5. Классификатор типовых студенческих ошибок

Типовая ошибка Симптомы и поведение СУБД Педагогическое исправление
UPDATE / DELETE без секции WHERE СУБД модифицирует или очищает абсолютно все строки таблицы. Приучать студентов перед запуском UPDATE/DELETE писать проверочный SELECT COUNT(*) FROM table WHERE condition; и использовать явные транзакции BEGIN...ROLLBACK.
Синтаксическая ошибка в JOIN при UPDATE Попытка написать UPDATE a JOIN b ON ... (синтаксис MySQL/MS SQL), что вызывает синтаксическую ошибку в PostgreSQL. Разъяснить стандартную для PostgreSQL конструкцию UPDATE a SET ... FROM b WHERE a.id = b.a_id.
Путаница между именами колонок в UPSERT Написание SET col = col + quantity вместо SET col = table.col + EXCLUDED.quantity. Показать, что без префикса EXCLUDED СУБД либо сошлется на старое значение, либо выдаст ошибку неоднозначности (ambiguous column).
Несоответствие столбцов в INSERT...SELECT Ошибка несовместимости типов datatype mismatch либо запись данных не в те поля из-за несовпадения порядка. Требовать строгого явного указания списка колонок в круглых скобках как у целевой таблицы, так и в SELECT-проекции.

6. Критерии оценивания практической работы (4-балльная шкала)

Контроль сформированности знаний и умений осуществляется по прозрачной 4-балльной шкале в соответствии с паспортом занятия:

Итоговая дифференциация: 4 балла — отлично (материал освоен в полном объеме); 3 балла — хорошо (допущены незначительные синтаксические погрешности); 2 балла — удовлетворительно (выполнены только базовые команды); 1-0 баллов — не зачтено.