الدرس 1 من 14 · الخطوات الأولى في SQL
قواعد البيانات العلائقية: الجداول، والصفوف، والمفاتيح، ونظم إدارة قواعد البيانات
الهدف
أن تفهم كيف ترتّب قاعدة بيانات علائقية معلومات متجر (الزبناء، المنتجات، الطلبيات)، وأن تستعمل المصطلحات الصحيحة، وأن تعرف فيمَ تُستعمل PostgreSQL وMySQL/MariaDB وSQLite وSQL Server. ستنفّذ أولى استعلاماتك بلغة SQL على قاعدة بيانات متجر إلكتروني حقيقي.
أهم النقاط
- قاعدة البيانات العلائقية (relational database) ترتّب البيانات في جداول (tables)؛ لكل جدول أعمدة (columns) (اسم ونوع)، ويحتوي على صفوف (rows) (السجلات).
- يُعرَّف كل صف بواسطة مفتاح أساسي (primary key) فريد (غالبًا
id). أما المفتاح الأجنبي (foreign key) فيشير إلى المفتاح الأساسي لجدول آخر: إنه «الرابط» في القاعدة العلائقية. - نظام إدارة قواعد البيانات (SGBD / DBMS) هو البرنامج الذي يخزّن البيانات، ويطبّق القواعد، ويدبّر الولوج المتزامن، وينفّذ استعلاماتك.
- SQL هي اللغة المعيارية للتخاطب مع جميع نظم إدارة قواعد البيانات العلائقية:
SELECTللقراءة، وINSERT/UPDATE/DELETEللتعديل، وCREATE TABLEللتعريف. - PostgreSQL وMySQL/MariaDB وSQL Server خوادم (servers)؛ أما SQLite فهي مكتبة تقرأ ملفًا بسيطًا. لغة SQL الأساسية هي نفسها في كل مكان؛ والتفاصيل هي التي تتغيّر.
المشكلة: الدفتر وجدول البيانات
المتجر الإلكتروني «Souk Atlas»، الموجود بالدار البيضاء، يبيع منتجات الصناعة التقليدية ومستحضرات التجميل والبقالة الراقية في جميع أنحاء المغرب. في البداية، كان المسيّر يدوّن كل شيء في جدول بيانات (tableur):
| التاريخ | الزبون | المدينة | الهاتف | المنتج | الكمية | الثمن |
|---|---|---|---|---|---|---|
| 03/09 | Amina Benali | Casablanca | 06 … | Huile d'argan 250 ml | 2 | 180 |
| 03/09 | Amina Benali | Casablanca | 06 … | Savon noir 500 g | 3 | 45 |
| 18/09 | Amina Benalli | Casa | 06 … | Tapis berbère | 1 | 2800 |
سرعان ما تظهر ثلاث مشكلات:
- التكرار: يُعاد نسخ اسم أمينة ومدينتها وهاتفها في كل عملية شراء.
- عدم الاتساق: «Benalli»، «Casa»… كم عدد الزبونات المختلفات؟ يستحيل الجزم.
- التحديث المحفوف بالمخاطر: إذا انتقلت أمينة إلى الرباط، يجب تصحيح جميع صفوفها دون نسيان أي واحد منها.
تحلّ القاعدة العلائقية هذه المشكلة عبر فصل المواضيع في جداول مرتبطة فيما بينها بمفاتيح.
الجداول، والصفوف، والأعمدة
إليك قاعدة بيانات المتجر التي ستستعملها في جميع تمارين هذه الدورة:
clients produits
+----+--------------+------------+ +----+----------------------+------------+---------+-------+
| id | nom | ville | | id | nom | categorie | prix_ht | stock |
+----+--------------+------------+ +----+----------------------+------------+---------+-------+
| 1 | Amina Benali | Casablanca | | 3 | Huile d'argan 250 ml | Cosmétique | 180.00 | 40 |
| 2 | Youssef … | Rabat | | 4 | Savon noir 500 g | Cosmétique | 45.00 | 120 |
+----+--------------+------------+ +----+----------------------+------------+---------+-------+
commandes lignes_commande
+----+-----------+---------------+--------+ +-------------+------------+----------+---------------+
| id | client_id | date_commande | statut | | commande_id | produit_id | quantite | prix_unitaire |
+----+-----------+---------------+--------+ +-------------+------------+----------+---------------+
| 1 | 1 | 2025-09-03 | livree | | 1 | 3 | 2 | 180.00 |
| 3 | 1 | 2025-09-18 | livree | | 1 | 4 | 3 | 45.00 |
+----+-----------+---------------+--------+ +-------------+------------+----------+---------------+
المصطلحات:
| المصطلح | المعنى | مثال |
|---|---|---|
| الجدول (table) (أو العلاقة (relation)) | مجموعة من البيانات تخص موضوعًا واحدًا | clients |
| العمود (column) (أو الخاصية (attribute)) | خاصية، لها نوع | ville، من نوع نصي |
| الصف (row) (أو السجل (record)، tuple) | عنصر ملموس | الزبونة رقم 1، أمينة |
| القيمة (value) | محتوى خانة واحدة | 'Casablanca' |
| المخطّط (schema) | وصف الجداول والأعمدة والأنواع والقواعد | «للجدول clients خمسة أعمدة…» |
| NULL | غياب القيمة (غير معروفة) | زبون بلا بريد إلكتروني |
في الجدول، ليس لترتيب الصفوف أي معنى: لا تضمن القاعدة أي ترتيب ما لم تطلبه (باستعمال ORDER BY، في الدرس الموالي).
المفاتيح: ما يربط الجداول
المفتاح الأساسي
يُعرِّف المفتاح الأساسي (primary key) كل صف بطريقة فريدة وغير فارغة أبدًا. قد تحمل زبونتان اسم «Amina Benali»؛ لكن سيكون لهما id مختلفان.
-- الطلبية رقم 7، وهي وحدها
SELECT * FROM commandes WHERE id = 7;
غالبًا ما نختار رقمًا بلا دلالة (id 1، 2، 3…) بدلًا من معطًى من معطيات النشاط: فرقم الهاتف أو البريد الإلكتروني قد يتغيّر، أما الـ id فلا يتغيّر أبدًا.
المفتاح الأجنبي
يحتوي العمود client_id في commandes على id زبون ما: إنه مفتاح أجنبي (foreign key). وهو يجيب عن سؤال «أيّ زبونة قدّمت هذه الطلبية؟» دون إعادة نسخ اسمها.
commandes.client_id ───► clients.id
lignes_commande.commande_id ───► commandes.id
lignes_commande.produit_id ───► produits.id
يستطيع نظام إدارة قواعد البيانات التحقق من هذه الروابط: يستحيل تسجيل طلبية للزبون رقم 999 إذا لم يكن موجودًا، أو حذف زبون لا تزال لديه طلبيات. هذا ما يُسمّى التكامل المرجعي (intégrité référentielle) (الدرس 2.4).
المعلومة في مكان واحد
إذا انتقلت أمينة إلى الرباط، نعدّل خانةً واحدة فقط: clients.ville في الصف 1. وجميع طلبياتها «تتبع» ذلك تلقائيًا، لأنها لا تحتوي إلا على رقمها. هذه هي الفائدة الكاملة للنموذج العلائقي.
نظام إدارة قواعد البيانات: أكثر بكثير من مجرد ملف
يقوم نظام إدارة قواعد البيانات نيابةً عنك بما لا يقوم به جدول البيانات:
- تخزين أحجام كبيرة والعثور على صف من بين ملايين الصفوف في بضع أجزاء من الثانية (الفهارس (index))؛
- فرض احترام القواعد: الأنواع، والقيم الإلزامية، والتفرّد، والروابط بين الجداول؛
- تدبير التزامن: عشرة بائعين والموقع الإلكتروني يكتبون في الوقت نفسه دون أن يمحو أحدهم عمل الآخر؛
- ضمان المعاملات (transactions): تُسجَّل عملية الأداء كاملةً أو لا تُسجَّل إطلاقًا، حتى في حالة انقطاع التيار الكهربائي؛
- مراقبة الولوج: المحاسب يقرأ الفواتير، والموقع لا يستطيع حذف الجداول؛
- النسخ الاحتياطي والاسترجاع.
العميل والخادم
تعمل PostgreSQL وMySQL/MariaDB وSQL Server بنموذج عميل-خادم (client-server): برنامج خادم يشتغل باستمرار (على الـ VPS الخاص بالمتجر)، ويحتفظ بملفات البيانات وينصت على الشبكة (المنفذ 5432 بالنسبة لـ PostgreSQL، و3306 بالنسبة لـ MySQL). ثم يتصل به العملاء: التطبيق الإلكتروني، وأداة سطر الأوامر psql، وبرنامج رسومي مثل DBeaver أو pgAdmin.
Site web (Node, PHP, Python) ─┐
psql (administrateur) ─┼──► serveur PostgreSQL :5432 ──► fichiers de données
Outil de reporting ─┘ (un processus par connexion)
(Site web = الموقع الإلكتروني؛ psql (administrateur) = psql (المسؤول)؛ Outil de reporting = أداة التقارير؛ serveur PostgreSQL = خادم PostgreSQL؛ fichiers de données = ملفات البيانات؛ un processus par connexion = عملية (process) واحدة لكل اتصال.)
يدبّر خادم PostgreSQL عدة قواعد (databases)؛ وكل قاعدة تحتوي على مخطّطات (schemas)، تحتوي بدورها على الجداول. سنعود إلى ذلك في الدرس 3.3.
SQLite: القاعدة داخل ملف
ليس لـ SQLite خادم: إنها مكتبة مدمجة في البرنامج، والقاعدة بأكملها توجد في ملف واحد (boutique.db). وهي موجودة في هواتف Android وiOS، وفي المتصفحات، وفي كثير من تطبيقات سطح المكتب… كما أن Python تتضمّنها افتراضيًا (الوحدة sqlite3). إنها مثالية للتعلّم، ولتطبيق على الهاتف أو أداة صغيرة؛ لكنها أقل ملاءمة لموقع يكتب فيه مئات المستخدمين في الوقت نفسه.
نظرة عامة على نظم إدارة قواعد البيانات
| النظام | النموذج | الرخصة | نقاط القوة | الاستعمال المعتاد في المغرب |
|---|---|---|---|---|
| PostgreSQL | خادم | حرة (رخصة PostgreSQL، متساهلة جدًا) | احترام معيار SQL، أنواع غنية (JSONB، المصفوفات، التواريخ)، الامتدادات (extensions)، الموثوقية | تطبيقات الويب الحديثة، SaaS، الشركات الناشئة، الإدارات |
| MySQL | خادم | حرة (GPL) + إصدارات Oracle | واسعة الانتشار، بسيطة، سريعة في القراءة | الاستضافة المشتركة، WordPress، PrestaShop |
| MariaDB | خادم | حرة (GPL) | تفرّع (fork) مجتمعي من MySQL، متوافق معها | توزيعات Linux، بديل لـ MySQL |
| SQLite | ملف (مدمج) | ملك عام (domaine public) | دون أي تثبيت، ملف واحد، خفيفة جدًا | تطبيقات الهاتف، صناديق الأداء دون اتصال، النماذج الأولية |
| SQL Server | خادم | مملوكة (Microsoft)، مع إصدار Express مجاني | الاندماج مع Windows و.NET، أدوات ذكاء الأعمال (BI) | أنظمة ERP، الأبناك، المقاولات الكبرى |
تعتمد هذه الدورة PostgreSQL مرجعًا وSQLite للتمارين التطبيقية (دون أي تثبيت، والقاعدة توجد في ملف واحد). وفي كل مرة يكون فيها فرق مهمّ، سينبّهك إليه إطار «SQLite / PostgreSQL».
ما الذي يتغيّر من نظام إلى آخر
جوهر SQL (SELECT، WHERE، JOIN، GROUP BY، INSERT…) مشترك. وتنصبّ الفروق أساسًا على:
| الموضوع | PostgreSQL | MySQL/MariaDB | SQLite | SQL Server |
|---|---|---|---|---|
| تحديد عدد الصفوف | LIMIT 10 |
LIMIT 10 |
LIMIT 10 |
TOP 10 أو OFFSET … FETCH |
| الترقيم التلقائي | GENERATED ALWAYS AS IDENTITY |
AUTO_INCREMENT |
INTEGER PRIMARY KEY |
IDENTITY(1,1) |
| التواريخ | أنواع حقيقية date وtimestamp |
DATE وDATETIME |
نص '2025-09-03' + دوالّ |
date وdatetime2 |
| ضمّ النصوص (concaténation) | 'a' || 'b' |
CONCAT('a','b') |
'a' || 'b' |
'a' + 'b' |
| الأنواع | صارمة | صارمة نوعًا ما | مرنة («الألفة» (affinité)) | صارمة |
SQL في ثلاثين ثانية
SQL لغة تصريحية (declarative): تصف ما تريده، لا كيفية العثور عليه. ونظام إدارة قواعد البيانات هو الذي يختار الطريقة (المرور على الجدول كاملًا، استعمال فهرس…).
-- القراءة: زبناء الرباط
SELECT nom, email FROM clients WHERE ville = 'Rabat';
-- عدّ المنتجات
SELECT COUNT(*) FROM produits;
-- الإضافة والتعديل والحذف (الدرس 1.4)
INSERT INTO clients (nom, email, ville, inscrit_le)
VALUES ('Imane Fassi', 'imane.fassi@exemple.ma', 'Meknès', '2025-10-01');
UPDATE produits SET stock = 35 WHERE id = 3;
DELETE FROM commandes WHERE id = 4;
قواعد الكتابة:
- تنتهي كل تعليمة بـ فاصلة منقوطة
;؛ - الكلمات المفتاحية (
SELECT،FROM) لا تتأثر بحالة الأحرف؛ ونكتبها بأحرف كبيرة اصطلاحًا، لتمييزها عن أسماء الجداول والأعمدة؛ - السلاسل النصية (strings) تُكتب بين علامتي اقتباس مفردتين (apostrophes):
'Rabat'(أما علامات الاقتباس المزدوجة فتُستعمل لأسماء الكائنات في PostgreSQL)؛ - يبدأ التعليق بـ
--ويمتد إلى آخر السطر؛ - الأسطر الجديدة والمسافات حرّة: نظّم استعلاماتك بحيث تكون سهلة القراءة.
غالبًا ما تُصنَّف التعليمات في عائلات:
| العائلة | الدور | التعليمات |
|---|---|---|
| DQL (الاستعلام) | القراءة | SELECT |
| DML (المعالجة) | تعديل البيانات | INSERT، UPDATE، DELETE |
| DDL (التعريف) | تعريف البنية | CREATE، ALTER، DROP |
| DCL (المراقبة) | تدبير الصلاحيات | GRANT، REVOKE |
| TCL (المعاملات) | التأكيد أو الإلغاء | BEGIN، COMMIT، ROLLBACK |
الفهرس (catalogue): القاعدة تصف نفسها
يرتّب نظام إدارة قواعد البيانات وصف الجداول… داخل جداول. لذلك يمكننا الاستعلام عن البنية بلغة SQL:
-- SQLite: جداول القاعدة
SELECT name FROM sqlite_schema WHERE type = 'table';
-- PostgreSQL (معيار SQL): جداول المخطّط public
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
في أداة psql الخاصة بـ PostgreSQL، توجد اختصارات تؤدي الشيء نفسه: \dt يسرد الجداول، و\d clients يصف الجدول clients.
أخطاء متكررة
- الخلط بين القاعدة وجدول البيانات: إعادة نسخ اسم الزبون في كل طلبية. يجب تخزين كل معلومة في مكان واحد، وتشير إليها الجداول الأخرى عبر المفتاح.
- الاعتقاد بأن للصفوف ترتيبًا: دون
ORDER BY، يكون الترتيب المعروض وليد الصدفة وقد يتغيّر من يوم لآخر. - اختيار مفتاح أساسي قابل للتغيّر (الهاتف، البريد الإلكتروني، الاسم): فضّل معرّفًا تقنيًا.
- استعمال علامات الاقتباس المزدوجة للنصوص:
WHERE ville = "Rabat"يشتغل أحيانًا في SQLite أو MySQL، لكنه في PostgreSQL اسم عمود. اعتد على علامات الاقتباس المفردة.
التطبيق العملي (Lab)
يحتوي جهاز الـ lab على قاعدة بيانات المتجر في الملف /root/boutique.db (ويمكن قراءة سكربت إنشائها في /root/boutique.sql) وعلى أمر sql لتنفيذ استعلاماتك:
sql "SELECT * FROM produits;" # تنفيذ استعلام مكتوب مباشرة
sql /root/sql/clients.sql # تنفيذ محتوى ملف .sql
cat /root/boutique.sql # قراءة البنية والبيانات الأولية
python3 -m sqlite3 /root/boutique.db # وحدة تحكم SQLite تفاعلية (Ctrl+D للخروج)
اكتب كل استعلام في الملف المطلوب (مثلًا باستعمال echo "SELECT …;" > /root/sql/clients.sql)، ونفّذه باستعمال sql، ثم اطلب التحقق. ستقوم بما يلي:
- عرض الجدول
clientsبأكمله؛ - عدّ منتجات الكتالوج؛
- العثور على طلبية بواسطة مفتاحها الأساسي؛
- الاستعلام في فهرس القاعدة لسرد جداولها.
اختبار قصير
- ما الفرق بين صف وعمود في جدول؟
- ما فائدة المفتاح الأساسي، ولماذا نفضّل
idعلى رقم الهاتف؟ - في قاعدة بيانات المتجر، أيّ عمود هو مفتاح أجنبي يشير إلى
clients؟ - اذكر فرقًا في طريقة الاشتغال بين SQLite وPostgreSQL.
- في PostgreSQL، ماذا يعني
"Rabat"(بين علامتي اقتباس مزدوجتين) داخل استعلام؟
الأجوبة
- العمود خاصية من النوع نفسه لجميع العناصر (المدينة)؛ أما الصف فهو عنصر ملموس (الزبونة أمينة، بجميع قيمها).
- يُعرِّف كل صف بطريقة فريدة وغير فارغة؛ فالهاتف قد يتغيّر أو يكون مشتركًا، في حين أن المعرّف التقني لا يتغيّر أبدًا.
commandes.client_id، الذي يحتوي علىidزبون ما.- PostgreSQL خادم نتصل به عبر الشبكة، مع مستخدمين وصلاحيات؛ أما SQLite فمكتبة تقرأ ملفًا مباشرة، دون خادم (أجوبة أخرى ممكنة: الأنواع المرنة في SQLite، والتواريخ المخزّنة على شكل نص).
- اسم كائن (عمود أو جدول يُسمّى Rabat)، وليس سلسلة نصية: النصوص تُكتب
'Rabat'.
المراجع: التوثيق الرسمي لـ PostgreSQL (postgresql.org، رخصة PostgreSQL). نص أصلي من MasterLinux.