PROGRAMMING · DATABASE DESIGN

قواعد البيانات للمبتدئين: كيف تصمم الجداول والعلاقات لمشروع ويب؟

قبل أن تبدأ في كتابة كود موقعك، فكّر في المكان الذي ستُحفظ فيه بيانات المستخدمين والمنتجات والطلبات. تصميم قاعدة البيانات بطريقة صحيحة يجعل المعلومات أسهل في الإدارة، ويقلل التكرار والأخطاء عندما يكبر المشروع.

تصميم قواعد البيانات للمبتدئين مع جداول مترابطة لمشروع ويب
التصميم الجيد يوضح أين تُخزّن البيانات وكيف ترتبط ببعضها.

ما قاعدة البيانات، ولماذا يحتاج إليها موقعك؟

قاعدة البيانات نظام منظم لحفظ المعلومات واسترجاعها وتحديثها. يحتاج المتجر الإلكتروني إلى بيانات العملاء والمنتجات والطلبات، بينما يحتاج الموقع التعليمي إلى بيانات الطلاب والدروس والنتائج. بدلًا من وضع كل شيء في ملف واحد، تتيح قاعدة البيانات تقسيم المعلومات إلى جداول مترابطة.

من الأنظمة العلائقية الشائعة MySQL وPostgreSQL وMariaDB، كما تُستخدم SQLite في تطبيقات كثيرة لا تحتاج إلى خادم قاعدة بيانات مستقل. اختيار النظام يعتمد على متطلبات المشروع والاستضافة، لكن مفاهيم الجداول والعلاقات متشابهة إلى حد كبير.

الخطوة الأولى: حدد البيانات التي يحتاج إليها المشروع

سنستخدم متجرًا إلكترونيًا بسيطًا مثالًا. يحتاج المتجر إلى معرفة العملاء والمنتجات والطلبات، كما يحتاج إلى معرفة المنتجات الموجودة داخل كل طلب والكمية والسعر وقت الشراء.

  • العملاء: الاسم والبريد الإلكتروني وتاريخ التسجيل.
  • المنتجات: الاسم والوصف والسعر وحالة التوفر.
  • الطلبات: العميل صاحب الطلب وحالته وتاريخ إنشائه.
  • تفاصيل الطلب: المنتجات المرتبطة بالطلب والكمية وسعر الوحدة.

هذه العناصر كيانات مستقلة، وغالبًا يتحول كل كيان إلى جدول. أما خصائص الكيان فتتحول إلى أعمدة. تحديد المتطلبات أولًا يمنعك من إنشاء جداول عشوائية أو تخزين معلومات لا تعرف كيف ستستخدمها.

اختيار الأعمدة وأنواع البيانات

يحدد كل عمود نوع المعلومة التي يخزنها. استخدم INT أو نوعًا صحيحًا مناسبًا للمعرّفات، وVARCHAR للنصوص القصيرة، وTEXT للنصوص الطويلة، وDATE للتاريخ. أما الأسعار فمن الأفضل تمثيلها بنوع عشري دقيق مثل DECIMAL بدلًا من نوع تقريبي مثل FLOAT.

استخدم NOT NULL عندما تكون القيمة إلزامية، وUNIQUE عندما يجب ألا تتكرر، مثل البريد الإلكتروني إذا كانت قواعد المشروع تمنع تسجيل العنوان نفسه أكثر من مرة. تختلف تفاصيل أنواع البيانات بين أنظمة قواعد البيانات، لذا راجع توثيق النظام الذي تستخدمه.

المفتاح الأساسي والمفتاح الخارجي

المفتاح الأساسي Primary Key

المفتاح الأساسي يميز كل سجل عن غيره. يُستخدم غالبًا عمود id مستقل لكل جدول، ويجب أن تكون قيمه فريدة وغير فارغة. لا تعتمد على الاسم وحده بوصفه معرّفًا، لأنه قد يتكرر أو يتغير.

المفتاح الخارجي Foreign Key

المفتاح الخارجي يربط سجلًا في جدول بسجل في جدول آخر. على سبيل المثال، يحتوي الطلب على customer_id يشير إلى العميل صاحب الطلب. وتساعد هذه القيود على منع إنشاء علاقات تشير إلى سجلات غير موجودة.

أنواع العلاقات بين الجداول

واحد إلى واحد One-to-One

يرتبط كل سجل في الجدول الأول بسجل واحد في الجدول الثاني. قد يناسب ذلك فصل إعدادات الحساب عن بيانات المستخدم الأساسية، إذا كان لهذا الفصل سبب عملي واضح.

واحد إلى متعدد One-to-Many

يمكن للعميل إنشاء عدة طلبات، لكن كل طلب يعود إلى عميل واحد. في هذه الحالة يوضع customer_id في جدول الطلبات، لأنه جانب العلاقة الذي يحتوي على عدة سجلات.

متعدد إلى متعدد Many-to-Many

يمكن للطلب أن يحتوي على عدة منتجات، ويمكن للمنتج أن يظهر في طلبات كثيرة. نستخدم جدولًا وسيطًا مثل order_items لتسجيل كل منتج ضمن كل طلب، مع الكمية وسعر الوحدة.

مثال عملي: إنشاء جداول متجر باستخدام SQL

الأوامر التالية مكتوبة بصياغة مناسبة لـ MySQL. قد تحتاج إلى تعديلات بسيطة عند استخدام PostgreSQL أو نظام آخر.

1. جدول العملاء

CREATE TABLE customers (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  full_name VARCHAR(150) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

يحصل كل عميل على معرّف مستقل، ويُمنع تكرار البريد الإلكتروني وفق هذا التصميم.

2. جدول المنتجات

CREATE TABLE products (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(200) NOT NULL,
  description TEXT,
  price DECIMAL(10, 2) NOT NULL,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

يمثل price السعر بدقة عشرية، بينما يسمح is_active بإيقاف عرض المنتج دون حذفه بالضرورة. أضف قيدًا يمنع الأسعار السالبة إذا كانت قواعد عملك تتطلب ذلك.

3. جدول الطلبات

CREATE TABLE orders (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  customer_id BIGINT UNSIGNED NOT NULL,
  status VARCHAR(30) NOT NULL DEFAULT 'pending',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT fk_orders_customer
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

يربط customer_id الطلب بعميله. فكّر في سياسة الحذف والتحديث قبل إضافة خيارات مثل ON DELETE CASCADE، لأن حذف سجل قد يؤدي عندها إلى حذف سجلات مرتبطة به.

4. جدول تفاصيل الطلب

CREATE TABLE order_items (
  order_id BIGINT UNSIGNED NOT NULL,
  product_id BIGINT UNSIGNED NOT NULL,
  quantity INT UNSIGNED NOT NULL,
  unit_price DECIMAL(10, 2) NOT NULL,
  PRIMARY KEY (order_id, product_id),
  FOREIGN KEY (order_id) REFERENCES orders(id),
  FOREIGN KEY (product_id) REFERENCES products(id)
);

المفتاح الأساسي المركب يمنع تكرار المنتج نفسه في الطلب الواحد. إذا كان المشروع يسمح بتعدد سطور المنتج الواحد بسبب خيارات أو خصومات مختلفة، فاستخدم معرّفًا مستقلًا لسطر الطلب بدلًا من هذا المفتاح المركب.

احتفظنا بـ unit_price حتى يبقى سعر الشراء التاريخي ثابتًا حتى لو تغيّر السعر الحالي في جدول المنتجات.

استخراج البيانات باستخدام JOIN

يمكنك جمع معلومات من أكثر من جدول باستخدام JOIN. يعرض المثال التالي رقم الطلب واسم العميل وحالة الطلب:

SELECT
  orders.id AS order_id,
  customers.full_name,
  orders.status,
  orders.created_at
FROM orders
INNER JOIN customers
  ON orders.customer_id = customers.id
ORDER BY orders.created_at DESC;

يربط شرط ON الطلب بالعميل الذي يطابق معرّفه، ويرتب ORDER BY النتائج من الأحدث إلى الأقدم. وعند تمرير قيم من المستخدم، استخدم الاستعلامات المعلّمة (Parameterized Queries) بدلًا من دمج النصوص مباشرة داخل SQL.

ما التطبيع Normalization؟

التطبيع هو تنظيم البيانات لتقليل التكرار ومشكلات الإضافة والتعديل والحذف. تخيّل تخزين اسم العميل وبريده الإلكتروني داخل كل طلب؛ إذا تغير البريد، فستحتاج إلى تحديث سجلات متعددة وقد تظهر معلومات متضاربة. فصل بيانات العملاء في جدول مستقل وربط الطلبات بهم يجعل التحديث أوضح وأكثر اتساقًا.

  • اجعل كل عمود مسؤولًا عن معلومة واضحة.
  • تجنب تخزين قوائم قيم داخل عمود واحد إذا كنت تحتاج إلى البحث فيها أو ربطها.
  • لا تكرر المعلومات نفسها دون حاجة واضحة.
  • استخدم القيود للحفاظ على اتساق العلاقات.
  • لا تبالغ في تقسيم البيانات إلى جداول إذا كان ذلك يزيد التعقيد دون فائدة.

الفهارس Indexes وتحسين الاستعلامات

تساعد الفهارس قاعدة البيانات على العثور على السجلات بسرعة في استعلامات كثيرة. إذا كنت تسترجع طلبات العميل باستمرار، فقد يفيدك فهرس على customer_id:

CREATE INDEX idx_orders_customer_id
ON orders(customer_id);

الفهارس تستهلك مساحة وقد تزيد تكلفة عمليات الإدخال والتحديث، لذلك لا تضف فهرسًا لكل عمود بشكل عشوائي. افحص الاستعلامات الفعلية وخطة التنفيذ باستخدام EXPLAIN، ثم قِس التحسن بعد التعديل.

أخطاء شائعة يجب تجنبها

  • وضع كل البيانات في جدول واحد: يؤدي إلى التكرار وصعوبة التحديث؛ افصل الكيانات المستقلة.
  • إهمال المفاتيح الخارجية: قد يسمح بعلاقات تشير إلى سجلات غير موجودة.
  • اختيار نوع بيانات غير مناسب: استخدم نوعًا دقيقًا للقيم المالية ونوعًا مناسبًا للتواريخ.
  • الإفراط في الفهارس: قد يبطئ عمليات الكتابة ويستهلك مساحة.
  • تخزين كلمات المرور كنص واضح: استخدم خوارزمية مخصصة لتجزئة كلمات المرور مثل Argon2id أو bcrypt بإعدادات مناسبة.
  • تجاهل الاختبارات: اختبر القيم الفارغة والمكررة والعلاقات والحذف وتحديث السجلات.

اختبر التصميم قبل إطلاق الموقع

  1. أضف بيانات تجريبية تمثل الاستخدام الحقيقي.
  2. اختبر إنشاء السجلات وتعديلها وحذفها واسترجاعها.
  3. تحقق من القيود مثل البريد الفريد والمفاتيح الخارجية.
  4. اختبر الكميات والأسعار والمدخلات غير الصالحة.
  5. قِس الاستعلامات المهمة بحجم بيانات قريب من المتوقع.
  6. جهّز نسخًا احتياطية واختبر استعادة البيانات فعليًا.

استخدم المعاملات (Transactions) في العمليات التي يجب أن تنجح كوحدة واحدة. عند تسجيل طلب مثلًا، قد تحتاج إلى حفظ الطلب وتفاصيله وتحديث المخزون ضمن معاملة واحدة، حتى لا تبقى بيانات جزئية إذا فشلت إحدى الخطوات.

كيف تتصل قاعدة البيانات بتطبيق الويب؟

ترسل الواجهة طلبًا إلى الخادم، ويتحقق الخادم من المدخلات والصلاحيات، ثم ينفذ الاستعلامات ويعيد النتيجة المناسبة. لا تعرض بيانات اتصال قاعدة البيانات أو كلمات المرور داخل JavaScript الذي يصل إلى المتصفح. احتفظ بالأسرار في بيئة الخادم، وامنح حساب قاعدة البيانات أقل الصلاحيات اللازمة، واستخدم الاستعلامات المعلّمة للحماية من حقن SQL.

للتوسع في بناء المشروع، اقرأ دليل إنشاء موقع إلكتروني من الصفر، وتعرّف على طلبات الواجهة عبر شرح Fetch API في JavaScript.

قائمة مراجعة قبل اعتماد قاعدة البيانات

  • هل حددت الكيانات والبيانات المطلوبة؟
  • هل لكل جدول مفتاح أساسي مناسب؟
  • هل العلاقات محمية بقيود مناسبة؟
  • هل أنواع البيانات ملائمة لكل عمود؟
  • هل قللت التكرار غير الضروري؟
  • هل الفهارس مبنية على استعلامات فعلية؟
  • هل التطبيق يتحقق من الصلاحيات والمدخلات؟
  • هل اختبرت النسخ الاحتياطي والاستعادة؟

الخلاصة

ابدأ تصميم قاعدة البيانات بفهم المتطلبات، ثم حدد الكيانات والجداول والعلاقات بينها. استخدم المفاتيح الأساسية والخارجية، واختر أنواع البيانات بعناية، وراجع الاستعلامات والقيود قبل إطلاق الموقع. يمكنك توسيع نموذج المتجر لاحقًا لإضافة الشحن والمدفوعات والمخزون، مع التأكد من أن كل إضافة تعكس حاجة حقيقية في المشروع.

الكاتب وصاحب الموقع: imad limrani

مقالات ذات صلة