CodeGym /Kursy /SQL SELF /Typowe błędy podczas pracy z danymi

Typowe błędy podczas pracy z danymi

SQL SELF
Poziom 22 , Lekcja 4
Dostępny

Praca z bazą danych to trochę jak życie programisty: pełne niespodzianek. Nawet najbardziej doświadczony dev może się pomylić — przypadkowo usunąć dane, próbować wrzucić duplikat albo złamać ograniczenia spójności. Ale ważne jest nie tylko unikać takich wpadek, ale też wiedzieć, jak je naprawić, jeśli już się zdarzą. Zobaczmy kilka najbardziej typowych błędów.

Błąd nr 1: Brak warunku WHERE

Najbardziej klasyczny błąd, który robią początkujący (i, bądźmy szczerzy, czasem nawet starzy wyjadacze), to zapomnieć o WHERE w zapytaniu do update'a albo kasowania danych. Zapytania bez WHERE aktualizują albo usuwają wszystkie wiersze w tabeli.

-- Przykład, jak NIE robić:
UPDATE students SET status = 'absolwent';

-- Albo tak:
DELETE FROM students;

Konsekwencje: wyobraź sobie, że po takim zapytaniu twoja tabela students z wszystkimi danymi o studentach jest pusta. Najgorsze — nie odzyskasz tych danych, jeśli nie masz backupu albo nie używasz transakcji (a nawet wtedy to już stres).

Jak tego uniknąć: zawsze dodawaj warunki do zapytań UPDATE i DELETE, żeby dokładnie określić, które wiersze chcesz zmienić albo usunąć.

-- Tak powinno być:
UPDATE students
SET status = 'absolwent'
WHERE year_of_study = 4;

DELETE FROM students
WHERE status = 'wydalony';

Jeszcze jeden trik — przed usunięciem zawsze odpal SELECT, żeby upewnić się, że warunek jest dobrze ustawiony:

-- Najpierw sprawdzamy:
SELECT * FROM students WHERE status = 'wydalony';

-- Potem kasujemy:
DELETE FROM students WHERE status = 'wydalony';

Błąd nr 2: Złamanie unikalności danych (UNIQUE)

Jeśli na tabeli jest ograniczenie UNIQUE, próba wrzucenia duplikatu skończy się błędem.

-- Błąd przez duplikację 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');

Błąd:

ERROR: duplicate key value violates unique constraint "students_email_key"

Jak tego uniknąć: przed wrzuceniem danych sprawdź, czy już nie ma wiersza z taką samą wartością.

-- Jeden ze sposobów:
SELECT * FROM students WHERE email = 'otto.lin@email.com';

-- Albo użyj UPSERT:
INSERT INTO students (name, email)
VALUES ('Peter Pen', 'otto.lin@email.com')
ON CONFLICT (email) DO NOTHING;

Błąd nr 3: Złamanie ograniczeń spójności (FOREIGN KEY)

Załóżmy, że masz dwie tabele: students i enrollments, gdzie student_id w tabeli enrollments jest powiązany przez foreign key z id z tabeli students. Jeśli spróbujesz wrzucić rekord do enrollments z student_id, którego nie ma w students, dostaniesz błąd.

INSERT INTO enrollments (student_id, course_id)
VALUES (999, 101); -- Błąd, bo student_id 999 nie istnieje

Jak tego uniknąć?

  1. Zawsze sprawdzaj, czy rekord istnieje w tabeli nadrzędnej przed wrzuceniem do powiązanej tabeli:
SELECT * FROM students WHERE id = 999;
  1. Używaj ograniczenia ON DELETE CASCADE, żeby rekordy w powiązanych tabelach kasowały się automatycznie przy usunięciu z tabeli nadrzędnej (ale ostrożnie z tym!).
CREATE TABLE enrollments (
    id SERIAL PRIMARY KEY,
    student_id INT REFERENCES students(id) ON DELETE CASCADE,
    course_id INT
);

Błąd nr 4: Złe typy danych

Przy wrzucaniu albo aktualizacji danych PostgreSQL ostro pilnuje zgodności typów. Jeśli spróbujesz wrzucić stringa do pola liczbowego, dostaniesz błąd.

-- Błąd przez niezgodność typów:
INSERT INTO students (id, name) VALUES ('abc', 'Alex Go');

Błąd:

ERROR: invalid input syntax for type integer

Jak tego uniknąć? Pilnuj typów danych w wrzucanych wartościach. Jeśli dane przychodzą z formularza użytkownika, zawsze je waliduj po stronie aplikacji.

Błąd nr 5: Problemy z równoczesnym dostępem (wycieki danych)

Wyobraź sobie, że dwóch userów jednocześnie próbuje zaktualizować ten sam rekord w tabeli. Bez odpowiedniej izolacji transakcji łatwo o konflikty.

-- Użytkownik A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- Użytkownik B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 1;

Jak tego uniknąć? Używaj transakcji i poziomów izolacji, żeby nie dopuścić do jednoczesnych zmian tych samych danych.

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

Błąd nr 6: Utrata danych przez TRUNCATE

TRUNCATE kasuje wszystkie wiersze z tabeli bez możliwości cofnięcia, bo ta komenda nie wspiera ROLLBACK (nie odpala triggerów i działa natychmiast).

-- Kasuje wszystko bezpowrotnie:
TRUNCATE TABLE students;

Jak tego uniknąć: używaj DELETE z warunkiem zamiast TRUNCATE, jeśli chcesz mieć możliwość cofnięcia zmian.

BEGIN;
DELETE FROM students WHERE year_of_study = 1;
-- Jeśli się rozmyślisz:
ROLLBACK;

Błąd nr 7: Brak transakcji przy ważnych operacjach

Jeśli robisz złożoną operację z kilku kroków i w środku pojawi się błąd, dane mogą zostać w niespójnym stanie.

-- Krok 1: dodajemy studenta
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');

-- Krok 2: zapisujemy go na kurs
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101); -- błąd

Jak tego uniknąć? Zawijaj takie operacje w transakcję:

BEGIN;

INSERT INTO students (name, email) VALUES ('Ivan Ivanov', 'ivan.ivanov@email.com');
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101);

COMMIT;

Jeśli na którymś etapie pojawi się błąd, możesz cofnąć zmiany:

ROLLBACK;

Błąd nr 8: Przypadkowa praca z NULL

NULL często robi niespodzianki, bo nie jest równy ani zeru, ani pustemu stringowi, a porównania z nim mogą dać dziwne wyniki.

-- To nie zadziała:
SELECT * FROM students WHERE email = NULL;

Jak tego uniknąć? Używaj IS NULL albo IS NOT NULL:

SELECT * FROM students WHERE email IS NULL;

Typowe błędy są nieuniknione, ale jak wiesz, jak je rozpoznać i jak ich unikać, możesz pracować z danymi bezpiecznie i skutecznie. PostgreSQL to surowy, ale sprawiedliwy strażnik twoich danych i zawsze rzuci błędem, jeśli coś pójdzie nie tak. Pamiętaj tylko, że błędy to nie wrogowie, tylko nauczyciele.

1
Ankieta/quiz
Wprowadzenie do transakcji, poziom 22, lekcja 4
Niedostępny
Wprowadzenie do transakcji
Wprowadzenie do transakcji
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION