القيود: NOT NULL و UNIQUE و CHECK و DEFAULT
قواعد تحرسها قاعدة البيانات بنفسها، فلا تدخلها بيانات خاطئة من أي باب. ⏱ نحو 35 دقيقة.
- تشرح دور القيود في حماية صحة البيانات.
- تستخدم
NOT NULLوUNIQUEوCHECKوDEFAULT. - تكتب قيودًا على مستوى الجدول وتسمّيها.
- تفسّر رسائل مخالفة القيود.
١القيد: قاعدة لا تُخالف
التطبيق قد يخطئ، والمستخدم قد يدخل أي شيء. القيد Constraint قاعدة تفرضها قاعدة البيانات نفسها على كل إدخال وتعديل، من أي تطبيق جاء. هو آخر خط دفاع عن صحة البيانات.
| القيد | يمنع | مثال |
|---|---|---|
NOT NULL | القيمة الفارغة | اسم المنتج إلزامي |
UNIQUE | التكرار | لا يتكرر البريد الإلكتروني |
CHECK (شرط) | القيم المخالفة للشرط | السعر أكبر من صفر |
DEFAULT قيمة | (ليس منعًا) قيمة تلقائية إن لم تُرسل | الحالة الافتراضية new |
PRIMARY KEY | التكرار والفراغ معًا | المعرّف |
REFERENCES | الإشارة إلى صف غير موجود | الدرس القادم |
٢القيود في العمل
قاعدة المتجر مبنية بقيود. جرّب أن تخالفها:
INSERT INTO products (name, category_id, price, stock)VALUES ('قلم', 4, -5, 10);
INSERT INTO products (name, category_id, price, stock)VALUES ('قلم', 4, 5, 10);SELECT name, price, stock FROM products WHERE name = 'قلم';
| name | price | stock |
|---|---|---|
| قلم | 5 | 10 |
رسالة الخطأ تذكر اسم القيد products_price_check: PostgreSQL سمّاه تلقائيًّا من اسم الجدول والعمود.
INSERT INTO customers (name, city, email, joined)VALUES ('سارة الثانية', 'جدة', 'sara@mail.sa', current_date);
البريد مكرر: قيد UNIQUE رفض الإدخال كاملًا.
٣قيود الجدول وتسميتها
بعض القيود تشمل أكثر من عمود، فتُكتب في آخر الجدول. وتسمية القيد بنفسك تجعل رسالة الخطأ مفهومة:
CREATE TABLE promotions ( id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY, product_id int NOT NULL, starts_on date NOT NULL, ends_on date NOT NULL, percent int NOT NULL DEFAULT 10, CONSTRAINT promo_dates_ok CHECK (ends_on > starts_on), CONSTRAINT promo_percent_ok CHECK (percent BETWEEN 1 AND 70), CONSTRAINT promo_one_per_day UNIQUE (product_id, starts_on)); INSERT INTO promotions (product_id, starts_on, ends_on) VALUES (1, '2025-11-01', '2025-10-01');
اسم القيد في الرسالة promo_dates_ok يخبرك فورًا ما الخطأ: نهاية العرض قبل بدايته.
توقّع وتحقّق
أي قيد يمنع التكرار ويقبل NULL؟
ما الذي يفعله DEFAULT؟
قيد يقارن عمودين (النهاية بعد البداية) يُكتب:
لماذا نسمّي القيود بأنفسنا؟
الخلاصة
- القيد قاعدة تفرضها القاعدة على كل إدخال وتعديل من أي تطبيق.
NOT NULLللإلزام، وUNIQUEللتفرد، وCHECKللشروط، وDEFAULTللقيم التلقائية.- القيد على عدة أعمدة يُكتب في آخر الجدول.
- سمِّ القيود:
CONSTRAINTاسم … لتكون الأخطاء مفهومة.
تحدٍّ برمجي: قيود جدول الموظفين
متوسطأنشئ جدول staff لموظفي المتجر بالقيود المطلوبة.
idمفتاح أساسي مولَّد، وnameإلزامي.national_idنص من 10 أرقام بالضبط، فريد (CHECK بـ~ '^[0-9]{10}$').salarynumeric أكبر من 3000 وأقل من 50000.roleإحدى القيم cashier أو manager أو storekeeper، وافتراضيًّا cashier.
👀 اعرض الناتج المطلوب
- الكود يعمل بلا أخطاء
- موظف صحيح يُقبل، والدور افتراضيًّا cashier
- الدور الافتراضي cashier
- الاسم إلزامي
- رقم الهوية 9 أرقام يُرفض
- رقم الهوية لا يتكرر
- راتب 2000 يُرفض
- دور غير معروف يُرفض
💡 تلميح 1
CHECK (role IN ('cashier', 'manager', 'storekeeper')).💡 تلميح 2
national_id ~ '^[0-9]{10}$' يعني عشرة أرقام بالضبط.حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
CREATE TABLE staff ( id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name text NOT NULL, national_id text NOT NULL UNIQUE CHECK (national_id ~ '^[0-9]{10}$'), salary numeric(10,2) CHECK (salary > 3000 AND salary < 50000), role text NOT NULL DEFAULT 'cashier' CHECK (role IN ('cashier', 'manager', 'storekeeper')));