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: customers və orders. 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 customers və orders 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 CASCADE və ON 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?
CASCADE və RESTRICT 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.
GO TO FULL VERSION