تصميم الجداول ومعلومات المخطط وترتيب تنفيذ الاستعلامات في SQL


يا هلا بالجميع! اليوم راح نتكلم عن أساسيات قوية في SQL تخلي شغلك احترافي أكثر: تصميم الجداول، كيف تشوف معلومات المخطط، والأهم من كذا، كيف تتنفذ الاستعلامات حقتك.

1. تصميم الجداول (Table Design)

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

  • التحويل (Normalization): هدفها تقليل تكرار البيانات وضمان سلامتها. في العادة، توصل للـ 3rd Normal Form (3NF). يعني كل عمود يعتمد على المفتاح الأساسي، ولا يعتمد على عمود آخر غير المفتاح.
  • أنواع البيانات (Data Types): اختار النوع المناسب لكل عمود. لا تستخدم VARCHAR(255) لكل شيء! لو عندك رقم صحيح، استخدم INT، لو تاريخ، استخدم DATE أو DATETIME. هذا يوفر مساحة ويحسن الأداء.
  • المفاتيح الأساسية والخارجية (Primary & Foreign Keys): المفتاح الأساسي PRIMARY KEY يضمن أن كل صف فريد. المفتاح الخارجي FOREIGN KEY يربط الجداول ببعضها ويحافظ على التكامل المرجعي للبيانات.
  • الفهارس (Indexes): زي فهرس الكتاب، يسرع عملية البحث عن البيانات. بس لا تبالغ فيها، لأنها تزيد من وقت الكتابة (INSERT/UPDATE/DELETE) وتستهلك مساحة. حط فهارس على الأعمدة اللي تستخدمها كثير في جمل WHERE أو JOIN.

مثال على إنشاء جدول بسيط:


CREATE TABLE Users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    registration_date DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE Posts (
    post_id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES Users(user_id) ON DELETE CASCADE
);
ملاحظة: لما تحتاج تخزن نصوص طويلة، استخدم TEXT بدل VARCHAR بحجم كبير. TEXT مصمم للنصوص الطويلة، بينما VARCHAR أفضل للنصوص اللي حجمها محدد وقصير نسبياً (زي الأسماء أو العناوين).

2. معلومات المخطط (Schema Information)

كيف تعرف ايش الجداول اللي عندك؟ ايش الأعمدة اللي فيها؟ ايش المفاتيح؟ كل قاعدة بيانات لها طرقها، لكن المفهوم واحد.

  • INFORMATION_SCHEMA (معظم قواعد البيانات): هذا مخطط قياسي يوفر معلومات عن كل شيء في قاعدة البيانات.

أمثلة:

للحصول على كل الجداول في قاعدة البيانات الحالية (مثال MySQL/PostgreSQL):


SELECT table_name
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';
-- أو في PostgreSQL:
-- WHERE table_schema = CURRENT_SCHEMA() AND table_type = 'BASE TABLE';

للحصول على أعمدة جدول معين (مثال MySQL/PostgreSQL):


SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'Users';

في SQL Server:


SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE';

SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Users';

في PostgreSQL (طرق أخرى غير INFORMATION_SCHEMA):


\dt  -- لعرض الجداول (من psql console)
\d Users -- لعرض تفاصيل جدول Users (من psql console)
SELECT * FROM pg_catalog.pg_tables WHERE schemaname = 'public';
SELECT * FROM pg_catalog.pg_columns WHERE tablename = 'users';
نصيحة: INFORMATION_SCHEMA هي الطريقة القياسية، لكن بعض قواعد البيانات توفر طرقها الخاصة (زي pg_catalog في PostgreSQL أو إجراءات النظام المخزنة في SQL Server) اللي ممكن تكون أسرع أو توفر تفاصيل أكثر.

3. ترتيب تنفيذ الاستعلامات (Query Execution Order)

هذا الجزء مهم جداً عشان تفهم كيف قاعدة البيانات تشتغل على استعلامك، وليش بعض الاستعلامات بطيئة وبعضها سريع. الترتيب العام لتنفيذ جمل SQL هو:

  1. FROM و JOINs: أول شيء، قاعدة البيانات تحدد من وين تجيب البيانات. تبدأ بالجداول المذكورة في FROM، ثم تطبق عمليات JOIN لدمج الصفوف من الجداول المختلفة.
  2. ON (للـ JOINs): شروط الربط بين الجداول يتم تقييمها هنا.
  3. WHERE: بعد ما تتجمع البيانات من الجداول، يتم تصفية الصفوف اللي ما تحقق الشروط المذكورة في WHERE. هنا يتم تقليل عدد الصفوف اللي راح يشتغل عليها الاستعلام بشكل كبير.
  4. GROUP BY: الصفوف المتبقية يتم تجميعها بناءً على الأعمدة المحددة.
  5. HAVING: بعد التجميع، يتم تصفية المجموعات (Groups) اللي ما تحقق الشروط المذكورة في HAVING. لاحظ الفرق بينها وبين WHERE؛ WHERE ت فلتر الصفوف قبل التجميع، HAVING ت فلتر المجموعات بعد التجميع.
  6. SELECT: يتم اختيار الأعمدة المطلوبة، وتطبيق أي دوال تجميعية (aggregate functions) زي SUM(), COUNT(), AVG().
  7. DISTINCT: إذا طلبت DISTINCT، يتم إزالة الصفوف المكررة من النتائج النهائية.
  8. ORDER BY: يتم ترتيب الصفوف بناءً على الأعمدة المحددة (تصاعدي ASC أو تنازلي DESC).
  9. LIMIT / OFFSET (أو TOP في SQL Server): أخيراً، يتم تحديد عدد الصفوف اللي راح ترجع كناتج نهائي، وإذا كان فيه إزاحة (offset).

مثال على استعلام يوضح الترتيب:


SELECT
    u.username,
    COUNT(p.post_id) AS total_posts
FROM
    Users u
JOIN
    Posts p ON u.user_id = p.user_id
WHERE
    u.registration_date >= '2023-01-01'
GROUP BY
    u.username
HAVING
    COUNT(p.post_id) > 5
ORDER BY
    total_posts DESC
LIMIT 10;

كيف يتنفذ الاستعلام أعلاه؟

  1. FROM Users u JOIN Posts p: يجيب كل المستخدمين وكل منشوراتهم ويربطها ببعض.
  2. ON u.user_id = p.user_id: يطبق شرط الربط بين Users.user_id و Posts.user_id.
  3. WHERE u.registration_date >= '2023-01-01': يفلتر المستخدمين اللي سجلوا قبل تاريخ معين.
  4. GROUP BY u.username: يجمع الصفوف حسب اسم المستخدم.
  5. HAVING COUNT(p.post_id) > 5: يفلتر المجموعات اللي عدد منشوراتها أكثر من 5.
  6. SELECT u.username, COUNT(p.post_id) AS total_posts: يختار اسم المستخدم ويحسب عدد المنشورات لكل مجموعة.
  7. ORDER BY total_posts DESC: يرتب النتائج تنازلياً حسب عدد المنشورات.
  8. LIMIT 10: يرجع أول 10 صفوف فقط.
مهم جداً: لفهم أداء استعلاماتك، استخدم أدوات تحليل خطة التنفيذ (Execution Plan) اللي توفرها قواعد البيانات. مثلاً، في MySQL/PostgreSQL استخدم EXPLAIN أو EXPLAIN ANALYZE، وفي SQL Server استخدم SHOW ACTUAL PLAN. هذا بيوريك بالضبط كيف قاعدة البيانات قررت تنفذ استعلامك، وهل استخدمت فهارس، وكم الوقت اللي استغرقته كل خطوة.

أتمنى يكون الدرس واضح ومفيد. فهمك لهذه الأساسيات راح يخليك تكتب SQL أفضل وأكثر كفاءة!