Логотип коледжу
Оптико-механічний фаховий коледж

DML: INSERT, UPDATE, DELETE і простий SELECT

Структуру таблиць створюють командами DDL, але порожня схема ще не розв'язує прикладних задач. Інформаційна система повинна додавати нові факти, змінювати актуальний стан, вилучати непотрібні записи та читати дані. Для цього використовують команди маніпулювання даними.

У цій лекції всі приклади виконуються в PostgreSQL на одній таблиці інтернет-магазину. Їх можна послідовно запускати в pgAdmin або DBeaver.

Цілі лекції

Після опрацювання матеріалу ви зможете:

  • додавати один або кілька рядків командою INSERT INTO;
  • отримувати результат зміни за допомогою PostgreSQL RETURNING;
  • безпечно застосовувати UPDATE і DELETE з умовою;
  • пояснювати призначення основних частин простого SELECT;
  • вибирати окремі стовпці, задавати псевдоніми та обчислювати вирази;
  • сортувати результат за одним або кількома критеріями через ORDER BY.

Передумови

Потрібні базові знання про таблиці, рядки, стовпці, первинний ключ, типи даних і команду CREATE TABLE. Також потрібне підключення до PostgreSQL із редактором SQL.

1. Навчальний стенд

Щоб усі приклади давали узгоджений результат, створимо одну таблицю products. Команди DROP TABLE і CREATE TABLE тут лише готують стенд; їхню роль як DDL розглянуто в попередніх лекціях.

DROP TABLE IF EXISTS products;

CREATE TABLE products (
    product_id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name varchar(100) NOT NULL,
    category varchar(50) NOT NULL,
    price numeric(10, 2) NOT NULL CHECK (price >= 0),
    stock integer NOT NULL DEFAULT 0 CHECK (stock >= 0),
    is_active boolean NOT NULL DEFAULT true
);

PostgreSQL сам генерує product_id. Для stock та is_active визначено типові значення, а перевірки не дозволяють зберігати від'ємну ціну або кількість.

2. DML і життєвий цикл рядка

DML (Data Manipulation Language) - частина SQL для роботи з даними всередині вже створених таблиць. У цій лекції розглядаємо чотири базові дії:

ДіяКомандаРезультат
ДодатиINSERTУ таблиці з'являється новий рядок
ПрочитатиSELECTСКБД формує таблицю результату
ЗмінитиUPDATEЗначення в наявних рядках оновлюються
ВидалитиDELETEВибрані рядки вилучаються

Ці дії часто називають CRUD: Create, Read, Update, Delete. Це зручна відповідність, але SQL-команди мають власні точні назви й правила.

3. Додавання одного рядка: INSERT INTO

Загальна форма додавання одного рядка:

INSERT INTO table_name (column_1, column_2)
VALUES (value_1, value_2);

Додамо перший товар:

INSERT INTO products (name, category, price, stock)
VALUES ('Підставка для ноутбука', 'Аксесуари', 899.00, 12);

Порядок значень у VALUES відповідає порядку стовпців після назви таблиці. Рядкові значення записують в одинарних лапках, а десяткові числа в SQL - із крапкою.

Стовпці product_id та is_active не вказано навмисно. Ідентифікатор згенерує PostgreSQL, а is_active отримає типове значення true.

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

4. Додавання кількох рядків

Одна команда може додати одразу кілька товарів. Набори значень відокремлюють комами:

INSERT INTO products (name, category, price, stock)
VALUES
    ('Бездротова миша', 'Периферія', 749.00, 25),
    ('Механічна клавіатура', 'Периферія', 1599.00, 10),
    ('Кабель USB-C', 'Аксесуари', 299.00, 40),
    ('Вебкамера', 'Периферія', 2199.00, 7);

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

Багаторядковий INSERT коротший за серію однакових команд і чітко показує, що дані додаються однією операцією. Проте кожен рядок усе одно перевіряється за типами та обмеженнями таблиці.

5. PostgreSQL RETURNING

Після зміни часто потрібно дізнатися, який ідентифікатор отримав новий рядок або які значення фактично збережено. У PostgreSQL для цього є RETURNING:

INSERT INTO products (name, category, price, stock)
VALUES ('USB-мікрофон', 'Аудіо', 2799.00, 5)
RETURNING product_id, name, price, stock;

Очікуваний результат після чистого запуску стенда й попередніх вставок:

product_idnamepricestock
6USB-мікрофон2799.005

RETURNING не є окремим читанням усієї таблиці. Воно повертає стовпці саме тих рядків, яких торкнулася команда. Запис RETURNING * повертає всі їхні стовпці:

INSERT INTO products (name, category, price)
VALUES ('Килимок для миші', 'Аксесуари', 399.00)
RETURNING *;

Тут stock матиме типове значення 0, а is_active - true.

RETURNING можна використовувати також після UPDATE і DELETE. Це розширення PostgreSQL особливо зручне для застосунків і для перевірки навчальних запитів.

6. Безпечне оновлення: UPDATE

Команда UPDATE змінює значення в наявних рядках:

UPDATE table_name
SET column_1 = new_value,
    column_2 = new_value
WHERE condition;

Оновимо ціну й залишок кабелю з ідентифікатором 4:

UPDATE products
SET price = 329.00,
    stock = 35
WHERE product_id = 4
RETURNING product_id, name, price, stock;

Очікуємо один рядок із новими значеннями. Умова WHERE product_id = 4 визначає, який саме рядок потрібно змінити.

Чому WHERE критично важливий

Синтаксично WHERE для UPDATE не є обов'язковим. Але команда без умови змінює кожен рядок таблиці:

-- Небезпечно: деактивує всі товари.
UPDATE products
SET is_active = false;

PostgreSQL не здогадається, який рядок мав на увазі автор. Відсутність WHERE не є синтаксичною помилкою.

Безпечна звичка перед зміною:

  1. сформулювати умову;
  2. перевірити нею рядок через SELECT;
  3. перенести ту саму умову в UPDATE;
  4. додати RETURNING і перевірити фактичний результат.
SELECT product_id, name, price, stock
FROM products
WHERE product_id = 4;

UPDATE products
SET price = 329.00,
    stock = 35
WHERE product_id = 4
RETURNING product_id, name, price, stock;

У цій лекції використано лише просту перевірку рівності за первинним ключем. Складні оператори фільтрації та поєднання умов розглянемо в лекції 13.

7. Безпечне видалення: DELETE

DELETE видаляє рядки, але не стовпці й не саму таблицю:

DELETE FROM table_name
WHERE condition;

Спочатку переглянемо товар, потім видалимо його та попросимо PostgreSQL показати вилучений рядок:

SELECT product_id, name
FROM products
WHERE product_id = 5;

DELETE FROM products
WHERE product_id = 5
RETURNING product_id, name;

Результат RETURNING підтвердить видалення вебкамери. Після цього звичайний SELECT із тією самою умовою не поверне рядків.

Як і UPDATE, команда DELETE без WHERE діє на всю таблицю:

-- Небезпечно: видаляє всі рядки products.
DELETE FROM products;

Таблиця після цього продовжить існувати, але буде порожньою. Перед DELETE завжди перевіряйте умову окремим SELECT. У реальних системах додатковий захист дають транзакції, резервні копії, права доступу та правила предметної області; ці механізми розглядатимуться пізніше.

8. Простий SELECT

SELECT читає дані та формує результат запиту. Результат виглядає як таблиця, але не обов'язково зберігається в базі як нова таблиця.

Базова структура запиту цієї лекції:

SELECT expressions
FROM table_name
WHERE condition
ORDER BY sort_expression;

Не всі частини обов'язкові. Для перегляду всіх стовпців використовують *:

SELECT *
FROM products;

Для прикладного запиту краще явно вибирати потрібні стовпці:

SELECT product_id, name, price
FROM products;

Явний перелік робить результат передбачуваним, не передає зайвих даних і показує призначення запиту.

Запис запиту і концептуальний порядок

SQL записують, починаючи із SELECT, але для розуміння простого запиту корисно уявляти інший концептуальний порядок:

  1. FROM - визначити джерело рядків;
  2. WHERE - залишити рядки, що відповідають умові;
  3. SELECT - сформувати потрібні стовпці та вирази;
  4. ORDER BY - упорядкувати готовий результат.

Це навчальна модель, а не буквальний опис внутрішнього алгоритму PostgreSQL. Оптимізатор може фізично виконувати операції інакше, зберігаючи той самий правильний результат.

9. Псевдоніми й обчислювані вирази

Псевдонім AS задає зрозумілу назву стовпця в результаті, не перейменовуючи стовпець у таблиці:

SELECT
    name AS product_name,
    price AS unit_price
FROM products;

У списку SELECT можна виконувати обчислення. Вартість усього запасу товару дорівнює ціні одиниці, помноженій на кількість:

SELECT
    name AS product_name,
    price,
    stock,
    price * stock AS inventory_value
FROM products;

Вираз обчислюється для кожного рядка. inventory_value існує в результаті цього запиту; команда не додає однойменного стовпця до products і не зберігає обчислені числа.

Ще один приклад - навчальний розрахунок ціни з коефіцієнтом 1.20:

SELECT
    name,
    price AS price_without_tax,
    price * 1.20 AS price_with_tax
FROM products;

Це лише демонстрація виразу. Реальні правила податків і округлення потрібно задавати відповідно до вимог предметної області.

10. Основи ORDER BY

Без ORDER BY порядок рядків результату не гарантований. Те, що сьогодні рядки відобразилися за ідентифікатором, не створює правила на майбутнє.

Сортування за зростанням задають ASC; це типовий напрям:

SELECT name, price
FROM products
ORDER BY price ASC;

Сортування за спаданням задають DESC:

SELECT name, price
FROM products
ORDER BY price DESC;

Можна визначити кілька критеріїв. Наступний критерій застосовується до рядків, у яких попередній має однакове значення:

SELECT category, name, price
FROM products
ORDER BY category ASC, price DESC;

Сортувати можна й за псевдонімом обчисленого стовпця:

SELECT
    name,
    price * stock AS inventory_value
FROM products
ORDER BY inventory_value DESC;

ORDER BY змінює порядок рядків лише в результаті запиту. Фізично «пересортувати таблицю» цією командою не можна.

Практичні завдання

Перед виконанням завдань повторно запустіть код із розділу «Навчальний стенд», а потім багаторядковий INSERT із п'ятьма товарами: спочатку підставку для ноутбука, далі мишу, клавіатуру, кабель і вебкамеру. Так ідентифікатори знову будуть від 1 до 5.

Завдання 1. Додайте товар і перевірте результат

Додайте товар Навушники категорії Аудіо із ціною 1899.00, залишком 8 і типовим активним станом. Не задавайте product_id та is_active вручну. За допомогою RETURNING виведіть усі стовпці створеного рядка.

Перевірте, що товар отримав ідентифікатор 6, а is_active дорівнює true.

Завдання 2. Безпечно змініть і видаліть рядок

Продовжуйте працювати зі станом після завдання 1.

  1. Через SELECT перевірте товар із product_id = 6.
  2. Змініть його ціну на 1799.00, а залишок - на 11.
  3. Використайте ту саму умову та RETURNING product_id, name, price, stock.
  4. Ще раз перевірте рядок через SELECT.
  5. Видаліть лише цей товар і поверніть його product_id та name.
  6. Переконайтеся, що повторний SELECT за ідентифікатором 6 не повертає рядків.

Завдання 3. Сформуйте звіт про запас

Для товарів, що залишилися після завдання 2, сформуйте результат із такими стовпцями:

  • назва товару з псевдонімом product_name;
  • ціна з псевдонімом unit_price;
  • кількість stock;
  • обчислена вартість запасу price * stock із псевдонімом inventory_value.

Відсортуйте результат за inventory_value від найбільшого значення до найменшого. Таблицю products змінювати не потрібно.

Підсумок

  • INSERT INTO додає рядки; явний перелік стовпців робить команду зрозумілішою та надійнішою.
  • Один INSERT може містити кілька наборів у VALUES.
  • PostgreSQL RETURNING показує дані рядків, яких торкнулися INSERT, UPDATE або DELETE.
  • UPDATE змінює, а DELETE видаляє всі рядки, що відповідають умові; без WHERE вони діють на всю таблицю.
  • Перед зміною або видаленням умову варто перевіряти через SELECT, а результат - через RETURNING.
  • SELECT формує результат із вибраних стовпців і виразів; псевдонім не змінює схему таблиці.
  • Спрощений концептуальний порядок простого запиту: FROMWHERESELECTORDER BY.
  • Лише ORDER BY гарантує потрібне впорядкування результату.
  • Розширені оператори фільтрації, поєднання умов, LIMIT та OFFSET належать до лекції 13. Агрегації та JOIN розглядатимуться пізніше.

Завдання

1. Який запит явно задає стовпці та правильно додає один товар?

2. Як у одному INSERT відокремлюють набори значень для кількох нових рядків?

3. Що дає PostgreSQL-конструкція RETURNING після INSERT, UPDATE або DELETE?

4. Що станеться, якщо виконати UPDATE products SET is_active = false без WHERE?

5. Яка послідовність правильно описує спрощений концептуальний порядок простого SELECT з умовою та сортуванням?

6. Який фрагмент обчислює вартість запасу та називає результат inventory_value?