CodeGym /Kurslar /SQL SELF /İstifadə ON DELETE CASCADE və ...

İstifadə ON DELETE CASCADEON UPDATE RESTRICT

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

Təsəvvür elə ki, bir database yaratmısan, orda müştərilər üçün bir cədvəl (customers) və onlarla əlaqəli sifarişlər (orders) var. Amma bir anda belə bir məsələ çıxır: əgər müştəri customers cədvəlindən silinsə, nə olacaq? Onun sifarişləri də silinməlidir, yoxsa "yetim" kimi qalacaq və mövcud olmayan müştəriyə referans verəcək? Bəs əgər müştərinin ID-sini dəyişmək istəsən? Bax, burada cascade əməliyyatları (CASCADE) və məhdudiyyətlər (RESTRICT) köməyə gəlir ki, database-in davranışını idarə edəsən.

ON DELETE CASCADE — bu mexanizm avtomatik olaraq əlaqəli qeydləri silir, əgər parent cədvəldən bir qeyd silinirsə. Başqa sözlə, əgər müştərini sildinsə, onunla bağlı bütün sifarişlər də silinir.

Bu belə işləyir: Sən foreign key təyin edəndə ON DELETE CASCADE əlavə edirsən və database "başa düşür" ki, əlaqəli qeyd avtomatik silinməlidir.

Nümunə

Güman edək ki, iki cədvəlimiz var: customersorders. Müştərilər (customers) bir neçə sifariş (orders) edə bilər, bu da ONE-TO-MANY əlaqəsinə uyğundur. İstəyirik ki, müştəri silinəndə onun bütün sifarişləri də silinsin.

-- Müştərilər üçün cədvəl yaradırıq
CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- Sifarişlər üçün cədvəl yaradırıq, foreign key ilə müştərilərə referans veririk
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE,
    order_date DATE NOT NULL
);

Cədvəllərə data əlavə edirik

-- Müştərilər cədvəlinə data əlavə edirik
INSERT INTO customers (name) VALUES ('İvan'), ('Anna');

-- Sifarişlər cədvəlinə data əlavə edirik
INSERT INTO orders (customer_id, order_date) VALUES
(1, '2023-10-01'),
(1, '2023-10-02'),
(2, '2023-10-03');

orders cədvəli:

order_id customer_id order_date
1 1 2023-10-01
2 1 2023-10-02
3 2 2023-10-03

Müştərini silirik və baxırıq nə baş verir

-- ID-si 1 olan müştərini silirik
DELETE FROM customers WHERE customer_id = 1;

-- Sifarişlər cədvəlində nə qaldığını yoxlayırıq
SELECT * FROM orders;
order_id customer_id order_date
3 2 2023-10-03

Gördüyün kimi, silinən müştəriyə aid sifarişlər də silindi.

Dəyişikliklərə məhdudiyyət: ON UPDATE RESTRICT

ON UPDATE RESTRICT parent cədvəldəki dəyəri dəyişməyə imkan vermir, əgər child cədvəldə bu dəyərə referans varsa. Bu bir növ "qoruyucu baryer"dir, hansı ki, məlumatın bütövlüyünü poza biləcək dəyişikliklərin qarşısını alır.

Necə işləyir? Sən ON UPDATE RESTRICT əlavə edəndə, database parent cədvəldəki açarı dəyişməyə icazə vermir, əgər ona child cədvəldə referans varsa.

Nümunə

Yenə də eyni customersorders cədvəllərini götürürük, amma foreign key-ə update məhdudiyyəti əlavə edirik.

-- Sifarişlər cədvəlini update məhdudiyyəti ilə yenidən yaradırıq
DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

Müştərinin ID-sini dəyişməyə çalışırıq

-- Müştərinin ID-sini 2-dən 5-ə dəyişməyə cəhd
UPDATE customers 
SET customer_id = 5 
WHERE customer_id = 2;

Nəticə:

ERROR:  update or delete on table "customers" violates foreign key constraint
DETAIL:  Key (customer_id)=(2) is still referenced from table "orders".

Gördüyün kimi, database error atdı, çünki açarın dəyişməsi cədvəllər arasındakı əlaqəni poza bilərdi.

UPDATE və onun incəlikləri barədə daha ətraflı növbəti səviyyədə danışacam :P

ON DELETE CASCADEON UPDATE RESTRICT bir yerdə

Təbii ki, cascade əməliyyatları (CASCADE) və məhdudiyyətləri (RESTRICT) birləşdirmək olar. Məsələn, parent qeyd silinəndə əlaqəli datanı avtomatik silmək (ON DELETE CASCADE), amma onun ID-sini dəyişməyə icazə verməmək (ON UPDATE RESTRICT) mümkündür ki, arzuolunmaz nəticələr olmasın.

Nümunə

Bir daha sifarişlər cədvəlini hər iki mexanizmlə yaradaq:

DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
        ON DELETE CASCADE
        ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

İndi:

  • Əgər müştərini silsən, onun bütün sifarişləri də silinəcək.
  • Əgər müştərinin ID-sini dəyişməyə çalışsan, error alacaqsan.

Bu real layihələrdə niyə vacibdir?

CASCADERESTRICT istifadə etmək böyük sistemlərdə, çoxlu əlaqəli cədvəllər olanda çox vacibdir. Məsələn:

Online mağazada müştərinin sifarişləri ola bilər. Əgər müştəri profilini silmək istəsə, database-də artıq heç nəyə referans verməyən sifarişləri saxlamaq istəmirsən. Burda ON DELETE CASCADE köməyə gəlir.

Eyni zamanda, unikal açarların təsadüfi dəyişməsinin qarşısını almaq istəyirsən ki, cədvəllər arasındakı əlaqələr pozulmasın. Bunun üçün ON UPDATE RESTRICT işə yarayır.

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