Робота з базою даних — як життя програміста: повна несподіванок. Навіть найдосвідченіший розробник може помилитися, наприклад, випадково видалити дані, спробувати вставити дублікат або порушити обмеження цілісності. Але важливо не лише уникати таких помилок, а й знати, як їх виправити, якщо раптом щось пішло не так. Давай розглянемо кілька найтиповіших помилок.
Помилка №1: Брак умови WHERE
Найкласичніша помилка, яку роблять новачки (і, якщо чесно, іноді навіть досвідчені деви), — це забути додати WHERE у запит на оновлення або видалення даних. Запити без WHERE оновлюють або видаляють усі рядки таблиці.
-- Приклад, як не треба робити:
UPDATE students SET status = 'graduated';
-- Або ось так:
DELETE FROM students;
Наслідки: уяви, що після такого запиту твоя таблиця students, де були всі дані про студентів, стала порожньою. І найнеприємніше — дані не повернути, якщо у тебе немає бекапу або не використовувалися транзакції (і навіть тоді це вже стрес).
Як уникнути: завжди додавай умови у запити UPDATE та DELETE, щоб чітко визначити, які рядки ти хочеш змінити або видалити.
-- Як треба робити:
UPDATE students
SET status = 'graduated'
WHERE year_of_study = 4;
DELETE FROM students
WHERE status = 'expelled';
Ще один лайфхак — перед видаленням завжди запускай SELECT, щоб переконатися, що умова налаштована правильно:
-- Спочатку перевіряємо:
SELECT * FROM students WHERE status = 'expelled';
-- Потім видаляємо:
DELETE FROM students WHERE status = 'expelled';
Помилка №2: Порушення унікальності даних (UNIQUE)
Якщо на таблицю накладено обмеження UNIQUE, то спроба вставити дублікат закінчиться помилкою.
-- Помилка через дублювання email:
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
INSERT INTO students (name, email) VALUES ('Peter Pen', 'otto.lin@email.com');
Помилка:
ERROR: duplicate key value violates unique constraint "students_email_key"
Як уникнути: перед вставкою даних треба перевірити, чи немає вже рядка з такими ж значеннями.
-- Один із способів:
SELECT * FROM students WHERE email = 'otto.lin@email.com';
-- Або використати UPSERT:
INSERT INTO students (name, email)
VALUES ('Peter Pen', 'otto.lin@email.com')
ON CONFLICT (email) DO NOTHING;
Помилка №3: Порушення обмежень цілісності (FOREIGN KEY)
Уяви, у тебе є дві таблиці: students і enrollments, де student_id у таблиці enrollments пов'язаний зовнішнім ключем з id таблиці students. Якщо ти спробуєш вставити запис у enrollments, вказавши student_id, якого немає у students, отримаєш помилку.
INSERT INTO enrollments (student_id, course_id)
VALUES (999, 101); -- Помилка, бо student_id 999 не існує
Як уникнути?
- Завжди перевіряй наявність запису у батьківській таблиці перед вставкою у пов'язану таблицю:
SELECT * FROM students WHERE id = 999;
- Використовуй обмеження
ON DELETE CASCADE, щоб записи у пов'язаних таблицях автоматично видалялися при видаленні запису з батьківської таблиці (але обережно).
CREATE TABLE enrollments (
id SERIAL PRIMARY KEY,
student_id INT REFERENCES students(id) ON DELETE CASCADE,
course_id INT
);
Помилка №4: Невірні типи даних
При вставці або оновленні даних PostgreSQL суворо перевіряє сумісність типів. Якщо ти спробуєш вставити рядок у числове поле, отримаєш помилку.
-- Помилка через несумісність типів:
INSERT INTO students (id, name) VALUES ('abc', 'Alex Go');
Помилка:
ERROR: invalid input syntax for type integer
Як уникнути? Слідкуй за типами даних у значеннях, які вставляєш. Якщо дані приходять з форми користувача, обов'язково валідуй їх на стороні застосунку.
Помилка №5: Проблеми з паралельним доступом (витік даних)
Уяви, що двоє користувачів одночасно намагаються оновити один і той самий запис у таблиці. Без належної ізоляції транзакцій велика ймовірність конфліктів.
-- Користувач A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- Користувач B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 1;
Як уникнути? Використовуй транзакції та рівні ізоляції, щоб запобігти одночасній зміні даних.
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
Помилка №6: Втрата даних через TRUNCATE
TRUNCATE видаляє всі рядки з таблиці без можливості відновлення, бо для цієї команди не передбачено підтримку ROLLBACK (вона не викликає тригери і виконується миттєво).
-- Видаляє все безповоротно:
TRUNCATE TABLE students;
Як уникнути: використовуй DELETE з умовою замість TRUNCATE, якщо треба зберегти можливість відкату.
BEGIN;
DELETE FROM students WHERE year_of_study = 1;
-- Якщо передумав:
ROLLBACK;
Помилка №7: Відсутність транзакцій для важливих операцій
Якщо виконується складна операція з кількох кроків, і посередині виникає помилка, дані можуть залишитися у неконсистентному стані.
-- Крок 1: додаємо студента
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
-- Крок 2: записуємо його на курс
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101); -- помилка
Як уникнути? Об'єднуй такі операції у транзакцію:
BEGIN;
INSERT INTO students (name, email) VALUES ('Іван Іванов', 'ivan.ivanov@email.com');
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101);
COMMIT;
Якщо на будь-якому етапі виникне помилка, ти можеш відкотити зміни:
ROLLBACK;
Помилка №8: Випадкова робота з NULL
NULL часто підкидає сюрпризи, бо він не дорівнює ні нулю, ні порожньому рядку, і порівняння з ним можуть дати неочікувані результати.
-- Це не спрацює:
SELECT * FROM students WHERE email = NULL;
Як уникнути? Використовуй IS NULL або IS NOT NULL:
SELECT * FROM students WHERE email IS NULL;
Типові помилки неминучі, але знаючи, як їх розпізнати і як їх уникати, ти зможеш працювати з даними безпечно й ефективно. PostgreSQL — суворий, але справедливий страж твоїх даних, і він завжди готовий повернути помилку, якщо щось не так. Просто пам'ятай: помилки — це не вороги, а вчителі.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ