Давай розберемо типові помилки при вставці нових даних у таблицю.
Помилка 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
Типові помилки роботи з даними та їх запобігання
Ти вже бачив, що головні джерела помилок — це:
- Порушення обмежень (
NOT NULL,UNIQUE,FOREIGN KEY). - Відсутність умов у запитах (
WHERE) при оновленні або видаленні даних. - Помилки у порядку виконання транзакцій.
Щоб убезпечити себе:
- Використовуй транзакції та відкати
ROLLBACKдля великих операцій. - Завжди перевіряй дані перед вставкою.
- Логуй помилки для аналізу.
- Застосовуй
ON CONFLICT, щоб уникати повторюваних записів.
Тепер ти озброєний знаннями для боротьби з помилками! Пам'ятай: хороший розробник — не той, хто не робить помилок, а той, хто вміє їх виправляти.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ