JavaRush /Курси /SQL SELF /Обробка помилок під час вставки та оновлення даних

Обробка помилок під час вставки та оновлення даних

SQL SELF
Рівень 22 , Лекція 3
Відкрита

Давай розберемо типові помилки при вставці нових даних у таблицю.

Помилка 1: Спроба вставити NULL в обов'язкове поле

PostgreSQL уважно стежить, щоб правила бази даних виконувались. Ось приклади обмежень, які можуть стати джерелом помилок:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL, -- Ім'я не може бути NULL
    age INT
);

-- Помилка: поле name обов'язкове для заповнення
INSERT INTO students (name, age) VALUES (NULL, 20);

Результат: помилка null value in column "name" of relation "students" violates not-null constraint`.

Треба слідкувати, які дані ти додаєш. Можливо, ця колонка раніше дозволяла NULL, але тепер це обов'язкове поле.

Помилка 2: Дублювання даних в унікальному стовпці.

CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    course_name TEXT UNIQUE -- Назва курсу має бути унікальною
);

-- Перша вставка успішна
INSERT INTO courses (course_name) VALUES ('SQL Basics');

-- Друга вставка викликає помилку
INSERT INTO courses (course_name) VALUES ('SQL Basics');

Результат: помилка duplicate key value violates unique constraint`.

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

Помилка 3: Порушення зовнішньої цілісності.

CREATE TABLE enrollments (
    enrollment_id SERIAL PRIMARY KEY,
    student_id INT REFERENCES students(id), -- Має існувати студент з таким ID
    course_id INT REFERENCES courses(course_id)
);

-- Помилка: студент з ID = 99 не існує
INSERT INTO enrollments (student_id, course_id) VALUES (99, 1);

Результат: помилка insert or update on table "enrollments" violates foreign key constraint`.

Дуже добре, що виникла помилка. Немає нічого гіршого, ніж порушення цілісності бази. Скоріш за все, в коді, який працює з базою, є помилка або якісь дані застаріли. В будь-якому випадку, якщо база даних не дала порушити свою цілісність — це дуже круто.

Обробка помилок у PostgreSQL

Так, помилки трапляються. Але важливо не просто їх помічати, а вміти з ними працювати.

Транзакції як інструмент захисту

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

Приклад: додавання даних у дві таблиці.

BEGIN; -- Починаємо транзакцію

-- Вставляємо дані в таблицю students
INSERT INTO students (name, age) VALUES ('Otto Lin', 21);

-- Вставляємо запис у таблицю enrollments
-- Тут виникне помилка, якщо курсу з ID=10 не існує
INSERT INTO enrollments (student_id, course_id) VALUES (1, 10);

-- Якщо все пройшло успішно
COMMIT;
-- Якщо сталася помилка, "відкочуємо" зміни
ROLLBACK;

Якщо курс з course_id = 10 не існує, вставка в таблицю students теж буде скасована.

Обробка помилок у транзакціях

У PostgreSQL можна передбачити помилки і обробляти їх прямо в запитах з використанням блоків EXCEPTION.

Приклад: додаємо студента і записуємо його на курс. Якщо виникає помилка, запис про помилку додається в лог.

DO $$
BEGIN
    -- Пробуємо вставити дані
    INSERT INTO students (name, age) VALUES ('Anna Song', 22);
    INSERT INTO enrollments (student_id, course_id) VALUES (2, 999); -- Помилка

    -- Якщо все успішно
    RAISE NOTICE 'Запис успішно додано!';
EXCEPTION
    WHEN foreign_key_violation THEN
        -- Обробляємо порушення зовнішнього ключа
        RAISE WARNING 'Курс з вказаним course_id не існує.';
END $$;

Перевірка унікальності за допомогою ON CONFLICT

Ти можеш заздалегідь запобігти помилці, пов'язаній з порушенням обмеження UNIQUE, використовуючи конструкцію ON CONFLICT. Це дозволяє вказати, як діяти при конфлікті.

Приклад: при спробі вставити дубльований курс пропускаємо вставку.

INSERT INTO courses (course_name)
    VALUES ('SQL Basics')
ON CONFLICT (course_name) DO NOTHING; -- Пропустити дубльовані дані

Або оновимо існуючий рядок:

INSERT INTO courses (course_name)
    VALUES ('SQL Basics')
ON CONFLICT (course_name) DO UPDATE     
    SET course_name = EXCLUDED.course_name || ' (Updated)';

Детальніше про оператор ON CONFLICT я розповім на наступному рівні, коли будемо розбирати масове завантаження даних :P

Типові помилки роботи з даними та їх запобігання

Ти вже бачив, що головні джерела помилок — це:

  1. Порушення обмежень (NOT NULL, UNIQUE, FOREIGN KEY).
  2. Відсутність умов у запитах (WHERE) при оновленні або видаленні даних.
  3. Помилки у порядку виконання транзакцій.

Щоб убезпечити себе:

  • Використовуй транзакції та відкати ROLLBACK для великих операцій.
  • Завжди перевіряй дані перед вставкою.
  • Логуй помилки для аналізу.
  • Застосовуй ON CONFLICT, щоб уникати повторюваних записів.

Тепер ти озброєний знаннями для боротьби з помилками! Пам'ятай: хороший розробник — не той, хто не робить помилок, а той, хто вміє їх виправляти.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ