CodeGym /Kurslar /SQL SELF /Məlumatların yüklənməsi zamanı səhvlərin işlənməsi (`ON C...

Məlumatların yüklənməsi zamanı səhvlərin işlənməsi (`ON CONFLICT`)

SQL SELF
Səviyyə , Dərs
Mövcuddur

Xoş gəldin, kütləvi məlumat yükləmələrinin ən dramatik ssenarilərinin mərkəzinə! Bu gün məlumat yüklənməsi zamanı yaranan səhvlərlə necə effektiv davranmaq lazım olduğunu ON CONFLICT konstruksiyası ilə öyrənəcəyik. Bu, sanki təyyarədə autopilot-u qoşmaq kimidir: nəsə səhv getsə belə, nə edəcəyini biləcəksən və fəlakətin qarşısını alacaqsan. Gəlin PostgreSQL-in fəndlərini araşdıraq!

Heç kim sürprizləri sevmir, xüsusən də məlumatlar yüklənməkdən imtina edəndə! Kütləvi yükləmə prosesində bir neçə tipik problemə rast gələ bilərsən:

  • Məlumatların təkrarlanması. Məsələn, cədvəldə UNIQUE məhdudiyyəti varsa, və sənin məlumat faylında bol-bol təkrarlar varsa.
  • Məhdudiyyətlərlə konfliktlər. Məsələn, NOT NULL məhdudiyyəti olan sütuna boş dəyər yükləməyə çalış. Nəticə? Səhv. PostgreSQL belə hallarda həmişə ciddi olur.
  • Təkrarlanan əsas məlumat. Cədvəldə artıq sənin CSV faylındakı kimi eyni identifikatorlu məlumatlar ola bilər.

Gəlin baxaq, bu "gizli daşlardan" ON CONFLICT ilə necə yayınmaq olar.

Səhvlərin işlənməsi üçün ON CONFLICT-dən istifadə

ON CONFLICT konstruksiyasının sintaksisi konflikt zamanı (məsələn, UNIQUE və ya PRIMARY KEY məhdudiyyəti ilə) nə etmək lazım olduğunu göstərməyə imkan verir. PostgreSQL sənə ya mövcud məlumatı yeniləmək, ya da konfliktli sətri görməməzliyə vurmaq imkanı verir.

Budur, ON CONFLICT konstruksiyasının əsas sintaksisi:

INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_target)
DO UPDATE SET column1 = new_value1, column2 = new_value2;

Əgər sadəcə konflikti görməməzliyə vurmaq istəyirsənsə, DO UPDATE-i DO NOTHING ilə əvəz edə bilərsən.

Nümunə: konflikt zamanı məlumatların yenilənməsi

Tutaq ki, bizdə students adlı cədvəl var:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    age INT
);

İndi yeni məlumatlar yükləmək istəyirik, amma bəziləri artıq bazada var:

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22),  -- Bu tələbə artıq var
    (2, 'Anna', 20),  -- Yeni tələbə
    (3, 'Mal', 25) -- Yeni tələbə
ON CONFLICT (id) DO UPDATE SET 
    name = EXCLUDED.name, 
    age = EXCLUDED.age;

Bu nümunədə, əgər əlavə etmək istədiyimiz ID-li tələbə artıq varsa, onun məlumatları yenilənəcək:

ON CONFLICT (id) DO UPDATE SET
    name = EXCLUDED.name, 
    age = EXCLUDED.age;

Burada EXCLUDED sehrli sözünə fikir ver. Bu, "sən əlavə etməyə çalışdığın, amma konfliktə görə istisna olunan dəyərlər" deməkdir.

Nəticə:

  • id = 1 olan tələbənin məlumatları (ad və yaş) yenilənəcək.
  • id = 2id = 3 olan tələbələr cədvələ əlavə olunacaq.

Nümunə: konfliktlərin görməməzliyə vurulması

Əgər məlumatları yeniləmək istəmirsənsə və sadəcə konflikti yaradan sətrləri görməməzliyə vurmaq istəyirsənsə, DO NOTHING istifadə et:

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22),  -- Bu tələbə artıq var
    (2, 'Anna', 20),  -- Yeni tələbə
    (3, 'Mal', 25) -- Yeni tələbə
ON CONFLICT (id) DO NOTHING;

İndi konfliktli sətrlər sadəcə əlavə olunmayacaq, qalanlar isə rahatlıqla bazada yerləşəcək.

Səhvlərin log-lanması

Bəzən görməməzliyə vurmaq və ya yeniləmək kifayət etmir. Məsələn, konfliktləri sonradan analiz üçün qeyd etmək lazımdır. Bunun üçün xüsusi log cədvəli yarada bilərik:

CREATE TABLE conflict_log (
    conflict_time TIMESTAMP DEFAULT NOW(),
    id INT,
    name TEXT,
    age INT,
    conflict_reason TEXT
);

Sonra log-lama ilə səhvlərin işlənməsini əlavə edirik:

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22), 
    (2, 'Anna', 20), 
    (3, 'Mal', 25)
ON CONFLICT (id) DO UPDATE SET 
    name = EXCLUDED.name, 
    age = EXCLUDED.age
RETURNING EXCLUDED.id, EXCLUDED.name, EXCLUDED.age
INTO conflict_log;

Bu sonuncu nümunə yalnız stored procedures içində işləyəcək. Bunun necə işlədiyini biz PL-SQL öyrənəndə biləcəksən. Bir az qabağa getdim, sadəcə məlumat yükləmə konfliktini həll etməyin başqa bir yolunu göstərmək istədim: bütün problemli sətrlərin log-lanması.

İndi konfliktlərin səbəblərini analiz edə bilərsən. Bu texnika xüsusilə mürəkkəb sistemlərdə faydalıdır, çünki kütləvi yükləmələr zamanı "izləri" saxlamaq vacibdir.

Praktik nümunə

Gəlin bütün bildiklərimizi bir sadə tapşırıqda birləşdirək. Təsəvvür et ki, səndə tələbələrin yenilənməsi üçün CSV faylı var və onu cədvələ yükləmək istəyirsən:

students_update.csv faylı

id name age
1 Otto 23
2 Anna 21
4 Wally 30

Məlumatların yüklənməsi və konfliktlərin işlənməsi

  1. Əvvəlcə tmp_students adlı müvəqqəti cədvəl yaradırıq:
CREATE TEMP TABLE tmp_students (
  id   INTEGER,
  name TEXT,
  age  INTEGER
);
  1. Fayldan məlumatları \COPY ilə yükləyirik:
\COPY tmp_students FROM 'students_update.csv' DELIMITER ',' CSV HEADER
  1. Müvəqqəti cədvəldən əsas cədvələ INSERT ON CONFLICT ilə məlumatları əlavə edirik:
INSERT INTO students (id, name, age)
SELECT id, name, age FROM tmp_students
ON CONFLICT (id) DO UPDATE
  SET name = EXCLUDED.name,
      age = EXCLUDED.age;

İndi bütün məlumatlar, o cümlədən yenilənmələr (id = 1 sətri), uğurla yükləndi.

Tipik səhvlər və onlardan necə yayınmaq olar

Səhvlər hətta ən təcrübəli proqramçılarda da olur, amma necə yayınmaq lazım olduğunu bilsən, saatlarla (bəlkə də günlərlə) əsəbini qoruyarsan.

  • UNIQUE məhdudiyyəti ilə konflikt. ON CONFLICT-də düzgün sahəni göstərdiyinə əmin ol. Məsələn, səhv açar (id əvəzinə email) göstərsən, PostgreSQL sadəcə sorğunu "əlvida" deyəcək.
  • EXCLUDED-un səhv istifadəsi. Bu alias yalnız cari sorğuda ötürülən dəyərlərə aiddir. Onu başqa kontekstlərdə istifadə etməyə çalışma.
  • Sütunların buraxılması. SET-də göstərilən bütün sütunların cədvəldə olduğuna əmin ol. Məsələn, SET non_existing_column = 'value' əlavə etsən, səhv alacaqsan.

ON CONFLICT-dən istifadə PostgreSQL-də kütləvi məlumat yükləmələrini çevik və təhlükəsiz edir. Sən təkcə konfliktlərə görə sorğuların "uçub getməsinin" qarşısını almırsan, həm də məlumatlarının necə işlənəcəyinə tam nəzarət edirsən. İstifadəçilərin (və serverlərin!) sənə minnətdar olacaq.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION