Kodax

مقدمة في قواعد البيانات — SQL الأساسيات

مقدمة في قواعد البيانات العلائقية

قاعدة البيانات العلائقية تخزن البيانات في جداول مترابطة: كل جدول يمثل نوعاً من الأشياء (مستخدمون، طلبات)، وكل صف عنصر واحد، وكل عمود خاصية.

لماذا لا نحفظ كل شيء في ملف JSON؟

قاعدة البيانات تعطيك: استعلامات سريعة على ملايين الصفوف، وكتابة متزامنة من مستخدمين كثيرين دون تلف، وقيوداً تحمي صحة البيانات، ومعاملات (كل شيء أو لا شيء).

الأنظمة الشائعة

| النظام | ملاحظات |

|---|---|

| PostgreSQL | الأقوى والأكثر ميزات؛ يستخدمه Supabase |

| MySQL / MariaDB | منتشر جداً في الاستضافات |

| SQLite | ملف واحد بلا خادم — ممتاز للتعلم والتطبيقات الصغيرة والجوال؛ أمثلة هذه الدورة تعمل عليه |

| SQL Server / Oracle | بيئات الشركات |

لغة SQL متشابهة بينها بنسبة كبيرة، مع فروق في التفاصيل (مثل الترقيم التلقائي).

تصميم جدول

CREATE TABLE users (
  id INTEGER PRIMARY KEY,                 -- مفتاح أساسي: فريد لكل صف
  name TEXT NOT NULL,                     -- إلزامي
  email TEXT NOT NULL UNIQUE,             -- لا يتكرر
  age INTEGER CHECK (age >= 13),          -- شرط على القيمة
  created_at TEXT NOT NULL DEFAULT (datetime('now'))
);

| القيد | يضمن |

|---|---|

| PRIMARY KEY | هوية فريدة لكل صف |

| NOT NULL | القيمة موجودة |

| UNIQUE | لا تكرار (البريد) |

| CHECK | شرط منطقي |

| DEFAULT | قيمة تلقائية |

| REFERENCES (مفتاح أجنبي) | القيمة موجودة في جدول آخر |

القيود خط الدفاع الأخير: حتى لو أخطأ كود التطبيق، ترفض القاعدة البيانات الفاسدة.

الترقيم التلقائي: فرق بين الأنظمة

| النظام | الصيغة |

|---|---|

| SQLite | id INTEGER PRIMARY KEY |

| PostgreSQL | id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY (أو SERIAL القديم) |

| MySQL | id INT AUTO_INCREMENT PRIMARY KEY |

العلاقات بالمفتاح الأجنبي

CREATE TABLE authors (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
CREATE TABLE books (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  author_id INTEGER NOT NULL REFERENCES authors(id) ON DELETE RESTRICT
);

| نوع العلاقة | التنفيذ |

|---|---|

| واحد لمتعدد (مؤلف ← كتب) | مفتاح أجنبي في جدول "المتعدد" |

| متعدد لمتعدد (طلاب ↔ دورات) | جدول وسيط (enrollments) فيه مفتاحان أجنبيان |

| واحد لواحد | مفتاح أجنبي فريد |

ON DELETE: RESTRICT (امنع حذف مؤلف له كتب)، CASCADE (احذف كتبه معه)، SET NULL. (في SQLite فعّل المفاتيح الأجنبية بـ PRAGMA foreign_keys = ON;.)

التطبيع باختصار

لا تكرر المعلومة: اسم المدينة لا يُكتب نصاً في 10,000 صف ثم يُعدَّل في بعضها فقط. ضع الأشياء المستقلة في جداولها واربطها بالمعرّفات.

تمرين

صمم جداول لمكتبة: مؤلفون، كتب، أعضاء، واستعارات (عضو يستعير كتاباً بتاريخ ويعيده لاحقاً). حدد المفاتيح والقيود، ونفّذها على SQLite.

PRAGMA foreign_keys = ON;

CREATE TABLE authors (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL
);

CREATE TABLE books (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  published_year INTEGER CHECK (published_year BETWEEN 1400 AND 2100),
  author_id INTEGER NOT NULL REFERENCES authors(id) ON DELETE RESTRICT
);

CREATE TABLE members (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE
);

-- متعدد لمتعدد عبر جدول وسيط مع بيانات إضافية (التواريخ)
CREATE TABLE loans (
  id INTEGER PRIMARY KEY,
  book_id INTEGER NOT NULL REFERENCES books(id),
  member_id INTEGER NOT NULL REFERENCES members(id) ON DELETE CASCADE,
  borrowed_at TEXT NOT NULL DEFAULT (date('now')),
  returned_at TEXT
);

INSERT INTO authors (id, name) VALUES (1, 'طه حسين'), (2, 'نجيب محفوظ');
INSERT INTO books (title, published_year, author_id) VALUES
  ('الأيام', 1929, 1), ('اللص والكلاب', 1961, 2), ('بين القصرين', 1956, 2);
INSERT INTO members (name, email) VALUES ('سارة', 'sara@example.com'), ('عمر', 'omar@example.com');
INSERT INTO loans (book_id, member_id) VALUES (2, 1), (3, 2);

SELECT b.title, a.name AS author FROM books b JOIN authors a ON a.id = b.author_id;
اختبر فهمك