Məlumatlarla işləyərkən tipik səhvlər
Verilənlər bazası ilə işləmək — proqramçının həyatı kimidir: sürprizlərlə doludur. Hətta ən təcrübəli developer belə səhv edə bilər, məsələn, təsadüfən məlumatları silmək, dublikat əlavə etmək və ya integrity constraint-ləri pozmaq. Amma əsas məsələ təkcə bu səhvlərdən qaçmaq deyil, həm də baş verəndə onları necə düzəltməyi bilməkdir. Gəlin ən tipik səhvlərə baxaq.
Səhv №1: WHERE şərtinin olmaması
Ən klassik səhv, hansı ki, yeni başlayanlar (və, düzünü desək, bəzən təcrübəli developer-lər də) edir — WHERE şərtini update və ya delete sorğusunda unutmaqdır. WHERE olmadan sorğular cədvəldəki bütün sətirləri yeniləyir və ya silir.
-- Necə etmək olmaz:
UPDATE students SET status = 'mezun oldu';
-- Və ya belə:
DELETE FROM students;
Nəticə: təsəvvür elə ki, belə bir sorğunu işə saldın və birdən gördün ki, students cədvəlin tamamilə boşdur. Ən pis tərəfi — backup yoxdursa və ya transaction istifadə etməmisənsə, məlumatları qaytarmaq olmur (hətta olsa belə, artıq stressdir).
Necə qarşısını almaq olar: həmişə UPDATE və DELETE sorğularında şərt əlavə et, dəqiq hansı sətirləri dəyişmək və ya silmək istədiyini göstər.
-- Necə etmək lazımdır:
UPDATE students
SET status = 'mezun oldu'
WHERE year_of_study = 4;
DELETE FROM students
WHERE status = 'qovuldu';
Bir fənd də var — silmə əməliyyatından əvvəl həmişə SELECT işə sal, şərtin düzgün olduğuna əmin ol:
-- Əvvəlcə yoxlayırıq:
SELECT * FROM students WHERE status = 'qovuldu';
-- Sonra silirik:
DELETE FROM students WHERE status = 'qovuldu';
Səhv №2: Unikalığın pozulması (UNIQUE)
Əgər cədvəldə UNIQUE constraint varsa, dublikat əlavə etməyə cəhd edəndə səhv alacaqsan.
-- Email dublikatına görə səhv:
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
INSERT INTO students (name, email) VALUES ('Peter Pen', 'otto.lin@email.com');
Səhv:
ERROR: duplicate key value violates unique constraint "students_email_key"
Necə qarşısını almaq olar: əlavə etməzdən əvvəl yoxla ki, belə dəyərli sətir artıq var, ya yox.
-- Bir variant:
SELECT * FROM students WHERE email = 'otto.lin@email.com';
-- Və ya UPSERT istifadə et:
INSERT INTO students (name, email)
VALUES ('Peter Pen', 'otto.lin@email.com')
ON CONFLICT (email) DO NOTHING;
Səhv №3: Integrity constraint-lərin pozulması (FOREIGN KEY)
Tutaq ki, səndə iki cədvəl var: students və enrollments, burada enrollments cədvəlindəki student_id xarici açarla students cədvəlinin id-sına bağlıdır. Əgər enrollments-ə elə bir student_id əlavə etməyə çalışsan ki, students-də yoxdur, səhv alacaqsan.
INSERT INTO enrollments (student_id, course_id)
VALUES (999, 101); -- Səhv, çünki student_id 999 mövcud deyil
Necə qarşısını almaq olar?
- Əlaqəli cədvələ əlavə etməzdən əvvəl həmişə parent cədvəldə qeyd var, ya yox, yoxla:
SELECT * FROM students WHERE id = 999;
ON DELETE CASCADEconstraint istifadə et ki, parent cədvəldə qeyd silinəndə əlaqəli cədvəldə də avtomatik silinsin (amma ehtiyatlı ol).
CREATE TABLE enrollments (
id SERIAL PRIMARY KEY,
student_id INT REFERENCES students(id) ON DELETE CASCADE,
course_id INT
);
Səhv №4: Yanlış data type-lar
Insert və ya update zamanı PostgreSQL data type-ların uyğunluğunu ciddi yoxlayır. Əgər string-i rəqəm sahəsinə yazmağa çalışsan, səhv alacaqsan.
-- Type uyğunluğuna görə səhv:
INSERT INTO students (id, name) VALUES ('abc', 'Alex Go');
Səhv:
ERROR: invalid input syntax for type integer
Necə qarşısını almaq olar? Daxil etdiyin dəyərlərin data type-larına diqqət yetir. Əgər məlumat user form-dan gəlirsə, mütləq application tərəfində validasiya et.
Səhv №5: Paralel giriş problemləri (məlumat sızması)
Təsəvvür elə ki, iki user eyni anda cədvəldə eyni sətri yeniləməyə çalışır. Transaction isolation düzgün qurulmayıbsa, konfliktlər ola bilər.
-- İstifadəçi A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- İstifadəçi B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 1;
Necə qarşısını almaq olar? Transaction və isolation level-lərdən istifadə et ki, eyni anda məlumat dəyişməsin.
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
Səhv №6: TRUNCATE səbəbindən məlumat itkisi
TRUNCATE cədvəldəki bütün sətirləri bərpa imkanı olmadan silir, çünki bu komanda üçün ROLLBACK dəstəklənmir (trigger-lər işə düşmür və dərhal icra olunur).
-- Hər şeyi geri dönmədən silir:
TRUNCATE TABLE students;
Necə qarşısını almaq olar: TRUNCATE əvəzinə şərtli DELETE istifadə et, əgər rollback etmək istəyirsənsə.
BEGIN;
DELETE FROM students WHERE year_of_study = 1;
-- Fikrin dəyişdi:
ROLLBACK;
Səhv №7: Vacib əməliyyatlarda transaction istifadə etməmək
Əgər bir neçə addımdan ibarət mürəkkəb əməliyyat icra edirsənsə və ortada səhv baş verərsə, məlumatlar inkonsistent qala bilər.
-- Addım 1: tələbəni əlavə edirik
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
-- Addım 2: onu kursa yazırıq
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101); -- səhv
Necə qarşısını almaq olar? Belə əməliyyatları transaction-a yığ:
BEGIN;
INSERT INTO students (name, email) VALUES ('İvan İvanov', 'ivan.ivanov@email.com');
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101);
COMMIT;
Əgər istənilən mərhələdə səhv olsa, dəyişiklikləri geri qaytara bilərsən:
ROLLBACK;
Səhv №8: NULL ilə təsadüfi işləmək
NULL tez-tez sürprizlər yaradır, çünki nə sıfıra, nə də boş string-ə bərabər deyil və onunla müqayisələr gözlənilməz nəticə verə bilər.
-- Bu işləməyəcək:
SELECT * FROM students WHERE email = NULL;
Necə qarşısını almaq olar? IS NULL və ya IS NOT NULL istifadə et:
SELECT * FROM students WHERE email IS NULL;
Tipik səhvlər qaçılmazdır, amma onları necə tanımaq və qarşısını almağı bilsən, məlumatlarla əməliyyatları təhlükəsiz və effektiv edə bilərsən. PostgreSQL — məlumatlarının ciddi, amma ədalətli qoruyucusudur və nəsə səhv getsə, həmişə səhv mesajı qaytarmağa hazırdır. Sadəcə unutma ki, səhvlər düşmən deyil, müəllimdir.
GO TO FULL VERSION