اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'سلسلة تعلم sql'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 11 نتائج

  1. سنتعرف في مقال اليوم على طريقة استخدام بنى WHERE في بعض تعليمات لغة الاستعلام البنيوية SQL لتحديد سجلات معينة ستتأثر بكل عملية نجريها، وذلك بتعريف معايير محددة تُعرف باسم شروط البحث، إذ يجب أن يستوفيها كل سجل ليتأثر بالعملية. وما شرط البحث سوى مجموعة من التوابع الشرطية أو التعبيرات القادرة على تقييم تعبير قيمة واحد أو أكثر لتعيد نتيجة تكون إمّا "صحيحة True" أو "خاطئة False" أو "غير محددة Unknown"، إذ تؤثر العمليات فقط على تلك السجلات التي يُقيّم من أجلها كل تابع شرطي في بنية WHERE على أنّه "صحيح True". تتيح لغة SQL للمستخدمين استرجاع مجموعات نتائج دقيقة من قاعدة البيانات، وذلك بتوفيرها مجموعة متنوعة من أنماط التوابع الشرطية، إذ يستخدم كل منها عاملًا محددًا لتقييم السجلات. وسنوضّح في هذا المقال نمطين من التوابع الشرطية وهي: التوابع الشرطية للنطاق والتي تستخدم عامل BETWEEN. والتوابع الشرطية لعضوية المجموعة التي تستخدم عامل IN. رغم أننا سنستخدم في أمثلتنا بهذا المقال تعليمات SELECT على وجه التحديد، إلّا أنّه من الممكن استخدام المفاهيم الموضحة فيه في العديد من عمليات SQL. إذ تعد بنى WHERE في الواقع مكونات أساسية في عمليات التحديث UPDATE والحذف DELETE. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز كمبيوتر يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، كما هو موضح في مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال. ستحتاج أيضًا إلى قاعدة بيانات بجداول مُحمّلة ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على كتابة استعلامات تتضمّن بنى WHERE. لذا ننصحك بقراءة القسم القادم الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية الاتصال بخادم MySQL وإنشاء قاعدة البيانات التجريبية المُستخدمة في الأمثلة خلال هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الخرج عند تنفيذها على أنظمة مختلفة عن MySQL. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو: $ ssh ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p الآن ومن نافذة سطر الأوامر، أنشئ قاعدة بيانات باسم between_in_db: mysql> CREATE DATABASE between_in_db; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات between_in_db، نفّذ تعليمة USE التالية: mysql> USE between_in_db; الخرج Database changed بعد اختيار قاعدة البيانات between_in_db، أنشئ جدولًا ضمنها. لمتابعة الأمثلة المستخدمة في هذا المقال، لنفرض أننا نرغب بإدارة فريق مبيعات لشركة ما، وبفرض أن هذه الشركة تبيع ثلاث منتجات فقط: أجهزة صغيرة، وأدوات متنوعة، وأجهزة مبتكرة. وقررنا تتبع عدد الوحدات من كل منتج يبيعه كل عضو في الفريق ضمن قاعدة بيانات SQL. وارتأينا أنّ هذه القاعدة ستحتوي على جدول واحد بأربعة أعمدة: name: أسماء أعضاء فريق المبيعات، معبرًا عنها باستخدام نمط البيانات varchar بحد أقصى 20 محرفًا. widgets: العدد الإجمالي للأجهزة الصغيرة التي باعها كل بائع، معبرًا عنها بنمط بيانات الأعداد الصحيحة int. doodads: عدد الأدوات المتنوعة التي باعها كل بائع، معبرًا عنها أيضًا بنمط بيانات الأعداد الصحيحة int. gizmos: عدد الأجهزة المبتكرة التي باعها كل بائع، معبرًا عنها أيضًا بنمط بيانات الأعداد الصحيحة int. لننفّذ تعليمة CREATE TABLE التالية لإنشاء جدول باسم sales يحتوي على هذه الأعمدة الأربعة: mysql> CREATE TABLE sales ( mysql> name varchar(20), mysql> widgets int, mysql> doodads int, mysql> gizmos int mysql> ); الخرج Query OK, 0 rows affected (0.01 sec) الآن سنملأ جدول sales بعض البيانات التجريبية. نفّذ العملية INSERT INTO التالية لإضافة سبع سجلات من البيانات تمثل أعضاء فريق المبيعات وعدد ما باعوه من كل منتج: mysql> INSERT INTO sales mysql> VALUES mysql> ('Tyler', 12, 22, 18), mysql> ('Blair', 19, 8, 13), mysql> ('Lynn', 7, 29, 3), mysql> ('Boris', 16, 16, 15), mysql> ('Lisa', 17, 2, 31), mysql> ('Maya', 5, 9, 7), mysql> ('Henry', 14, 2, 0); وبذلك غدوتَ جاهزًا للمتابعة بباقي أقسام المقال وبدء تعلم كيفية استخدام عوامل BETWEEN وIN لتصفية البيانات. فهم التوابع الشرطية الخاصة ببنية WHERE يمكنك إدراج بنية WHERE بعد بنية FROM في أي عملية SQL تقرأ البيانات من جدول موجود أصلًا وذلك لتحديد البيانات التي ستتأثر بهذه العملية، إذ تُعرّف بنى WHERE شرط بحث، وأي سجل لا يحقق هذا الشرط سيُستثنى من العملية، على عكس السجلات التي تحققه. وما شرط البحث سوى مجموعة من التوابع الشرطية أو التعبيرات القادرة على تقييم تعبير قيمة واحد أو أكثر لتعيد نتيجة تكون إمّا "صحيحة True" أو "خاطئة False" أو "غير محددة Unknown". يُعرّف تعبير القيمة في لغة SQL - والذي يُشار إليه أحيانًا باسم التعبير ذو القيمة المفردة - بأنّه أي تعبير يُعيد قيمة واحدة. ويمكن أن يكون تعبير القيمة عبارة عن قيمة مُصنفة النوع من قبيل سلسلة نصية أو قيمة عددية، أو تعبير رياضي. ولكن غالبًا ما يكون على الأقل أحد تعبيرات القيمة في شرط بحث بنية WHERE هو اسم عمود. ومن الجدير بالملاحظة أنّه في معظم الأحيان نستخدم على الأقل اسم عمود من الجدول المُشار إليه ضمن بنية FROM من العملية كأحد تعابير القيمة في التابع الشرطي ضمن بنية WHERE ولدى تشغيل استعلامات SQL المُتضمّنة لبنية WHERE، سيطبق نظام إدارة قاعدة البيانات (DBMS) شرط البحث على كل سجل في الجدول المنطقي المحدد في بنية FROM ليُعيد فقط السجلات التي يُقيّم من أجلها كل تابع شرطي في شرط البحث على أنه "محقق TRUE". يُحدّد معيار SQL ثمانية عشر نمطًا مختلفًا من التوابع الشرطية، وعلى الرغم من أنّها لا تتوفر كاملةً في كافّة أنظمة إدارة قواعد البيانات العلاقية RDBMS. إليك خمسة من أكثر أنواع التوابع المستخدمة في شروط البحث والعوامل المستخدمة في كل منها: المقارنة: تقارن التوابع الشرطية المقارنِة بين تعبيري قيمة، وفي معظم الاستعلامات يكون أحد هذين التعبيرين هو اسم عمود. وعوامل المقارنة الستة هي: =: يختبر ما إذا كانت القيمتان متساويتين. <>: يختبر ما إذا كانت القيمتان غير متساويتين. <: يختبر ما إذا كانت القيمة الأولى أقل من الثانية. >: يختبر ما إذا كانت القيمة الأولى أكبر من الثانية. <=: يختبر ما إذا كانت القيمة الأولى أقل من أو تساوي الثانية. >=: يختبر ما إذا كانت القيمة الأولى أكبر من أو تساوي الثانية. القيم الفارغة: تختبر التوابع الشرطية التي تستخدم عامل IS NULL ما إذا كانت القيم في عمود معين فارغة. النطاق: تستخدم التوابع الشرطية النطاقية عامل BETWEEN لاختبار ما إذا كان تعبير قيمة ما يقع بين تعبيري قيمة آخرين. العضوية: يستخدم هذا النوع من التوابع الشرطية عامل IN لاختبار ما إذا كانت قيمة ما تُمثّل عضوًا في مجموعة معينة. تطابق الأنماط: تستخدم توابع مطابقة الأنماط الشرطية عامل LIKE لاختبار ما إذا كانت قيمة ما تطابق نمطًا نصيًا يحتوي على محارف بدل. وكما ذكرنا في المقدمة، يركز هذا المقال على توضيح كيفية استخدام عوامل BETWEEN وIN في SQL لتصفية البيانات. فإذا كنت ترغب في معرفة كيفية استخدام عوامل المقارنة أو عامل IS NULL، ننصحك بقراءة مقالنا حول كيفية استخدام عوامل المقارنة وIS NULL في لغة الاستعلام البنيوية SQL. أمّا إذا كنت ترغب في معرفة كيفية استخدام عامل LIKE لتصفية البيانات بناءً على نمط نصي يحتوي على محارف بدل، فننصحك بقراءة المقال كيفية استخدام محارف البدل في SQL. وللاطلاع على المزيد حول بنى WHERE عمومًا، ننصحك بقراءة مقالنا حول كيفية استخدام بنى WHERE في لغة الاستعلام البنيوية SQL. التوابع الشرطية النطاقية تستخدم التوابع الشرطية النطاقية عامل BETWEEN لاختبار ما إذا كان تعبير قيمة محصور بين تعبيري قيمة آخرين. وتتبع بنية WHERE المُتضمنة لتابع شرطي نطاقي في شرط البحث الخاص بها الصيغة العامة التالية: mysql> SELECT column_list mysql> FROM table_name mysql> WHERE column_name BETWEEN value_expression1 AND value_expression2; ويأتي بعد كلمة WHERE المفتاحية تعبير قيمة، والذي يكون في معظم عمليات SQL عبارة عن اسم عمود. وبما أن نظام قاعدة البيانات يطبق شروط البحث على كل سجل تباعًا، فإن توفير اسم عمود كتعبير قيمة في شرط البحث يخبر نظام إدارة قواعد البيانات العلاقية RDBMS باستخدام قيمة كل سجل من العمود المحدد كجزء من تعبير القيمة للتكرار الخاص بكل سجل في شرط البحث. ويأتي بعد اسم العمود عامل BETWEEN وتعبيري قيمة آخرين مفصولين بعامل AND. وسيُقيّم شرط البحث على أنه "صحيح True" لأي سجلات تكون قيمتها في العمود المحدد أكبر من أو تساوي القيمة الأولى من القيمتين المفصولتين بعامل AND وأقل من أو تساوي القيمة الثانية. لتوضيح كيفية عمل التوابع الشرطية النطاقية، لننفّذ الاستعلام التالي. والذي سيُعيد قيم عمودي name وwidgets لأي سجلات تكون فيها قيمة widgets محصورة بين 14 و19ضمنًا: mysql> SELECT name, widgets mysql> FROM sales mysql> WHERE widgets BETWEEN 14 AND 19; الخرج +-------+---------+ | name | widgets | +-------+---------+ | Blair | 19 | | Boris | 16 | | Lisa | 17 | | Henry | 14 | +-------+---------+ 4 rows in set (0.00 sec) تذكر أن النطاق الذي تحدده بعد عامل BETWEEN يمكن أن يتكون من أي زوج من تعابير القيمة، بما في ذلك أسماء الأعمدة. يعيد الاستعلام التالي جميع الأعمدة من جدول sales. وفيه، وبدلًا من تحديد كل عمود على حدة، ألحقنا الكلمة المفتاحية SELECT بعلامة النجمة (*) مباشرةً، وهي الطريقة المختصرة في SQL للإشارة إلى "جميع الأعمدة". وتحدّ بنية WHERE في هذا الاستعلام من إرجاعه للسجلات التي تكون فيها قيمة gizmos أكبر من قيمة doodads لكنها أقل من قيمة widgets: mysql> SELECT * mysql> FROM sales mysql> WHERE gizmos BETWEEN doodads AND widgets; لا يمتلك سوى عضو واحد من فريق المبيعات قيمة في عمود gizmos محصورة بين القيمتين widgets وdoodads. لذا فإنّ السجل الخاص به فقط هو الذي يظهر في مجموعة النتائج. الخرج +-------+---------+---------+--------+ | name | widgets | doodads | gizmos | +-------+---------+---------+--------+ | Blair | 19 | 8 | 13 | +-------+---------+---------+--------+ 1 row in set (0.00 sec) ويجب أن تكون على دراية بترتيب تعابير القيمة المُحدّدة للنطاق: فالقيمة الأولى بعد عامل BETWEEN تُمثّل دائمًا الحد الأدنى للنطاق، أمّا القيمة الثانية فتُمثّل الحد الأعلى. الاستعلام التالي مطابق للسابق، باستثناء أنه يعكس ترتيب الأعمدة التي تُحدد طرفيّ النطاق: mysql> SELECT * mysql> FROM sales mysql> WHERE gizmos BETWEEN widgets AND doodads; يعيد الاستعلام هذه المرة سجلين حيث تكون في كل منهما قيمة gizmos أكبر من أو تساوي قيمة widgets للسجل ولكنها أقل من أو تساوي قيمة doodads. وكما تدل النتائج، يمكن أن يؤدي تغيير الترتيب بهذه الطريقة إلى استرجاع مجموعة نتائج مختلفة تمامًا. الخرج +-------+---------+---------+--------+ | name | widgets | doodads | gizmos | +-------+---------+---------+--------+ | Tyler | 12 | 22 | 18 | | Maya | 5 | 9 | 7 | +-------+---------+---------+--------+ 2 rows in set (0.00 sec) وعلى نحوٍ مشابه لحالة استخدام عوامل المقارنة <، >، <=، و >= لتقييم عمود مُتضمّن لقيم من نمط السلاسل النصية، سيُحدد العامل BETWEEN ما إذا كانت هذه القيم تقع أبجديًا بين قيمتين من نمط السلاسل النصية. لتوضيح الفكرة، لنُنفّذ الاستعلام التالي الذي يعيد قيم العمود name الموافقة لأي سجل من الجدول sales حيث تكون قيمة name محصورة أبجديَا بين الحرفين A و M. استخدمنا في هذا المثال سلسلتين نصيتين مجردتين كتعبيريّ قيمة يمثلان طرفي النطاق. ومن الجدير بالملاحظة أنّه يجب حصر هذه القيم المحرفية بين علامات اقتباس مفردة أو مزدوجة، وإلا سيبحث نظام إدارة قواعد البيانات عن أعمدة باسم A و M، مما قد يؤدي إلى فشل الاستعلام. mysql> SELECT name mysql> FROM sales mysql> WHERE name BETWEEN 'A' AND 'M'; الخرج +-------+ | name | +-------+ | Blair | | Lynn | | Boris | | Lisa | | Henry | +-------+ 5 rows in set (0.00 sec) نلاحظ أن مجموعة النتائج هذه لا تتضمن الاسم Maya رغم كون النطاق المحدد في شرط البحث يمتد من A إلى M. السبب في ذلك هو أن الحرف M يأتي أبجديًا قبل أي سلسلة نصية تبدأ بالحرف M وتحتوي على أكثر من حرف، لذا يُستثنى الاسم Maya من مجموعة النتائج هذه، بالإضافة إلى أي بائعين آخرين لا تقع أسماؤهم ضمن النطاق المحدد. التوابع الشرطية للعضوية تتيح التوابع الشرطية للعضوية إمكانية تصفية نتائج الاستعلام بناءً على ما إذا كانت قيمة ما تُمثّل عضوًا من مجموعة محددة من البيانات. وعادةً ما تتبع الصيغة التالية في بنى WHERE: mysql>. . . mysql> WHERE column_name IN (set_of_data) mysql>. . . يأتي بعد الكلمة المفتاحية WHERE تعبير القيمة، وعادةً ما يكون هذا التعبير عبارة عن اسم عمود. يلي ذلك عامل IN، الذي يُتبع بدوره بمجموعة من البيانات. يمكن تحديد هذه المجموعة بوضوح عن طريق إدراج أي عدد من تعابير القيمة الصالحة مفصولةً بعلامات فاصلة، سواء كانت قيمًا مجردة أو أسماء أعمدة أو تعابير رياضية تتضمن أيًا من العناصر آنفة الذكر. لتوضيح الأمر، لنُنفذ الاستعلام التالي. والذي سيعيد قيم عموديّ name وgizmos لكل سجل تُمثّل فيه قيمة gizmos عضوًا من المجموعة المعرّفة بعد عامل IN: mysql> SELECT name, doodads mysql> FROM sales mysql> WHERE doodads IN (1, 2, 11, 12, 21, 22); نلاحظ أن قيم العمود doodads لثلاثة أعضاء فقط من فريق المبيعات تساوي أي من القيم الموجودة ضمن هذه المجموعة، ولذلك فإن السجلات الخاصة بهم فقط هي المُسترجعة. الخرج +-------+---------+ | name | doodads | +-------+---------+ | Tyler | 22 | | Lisa | 2 | | Henry | 2 | +-------+---------+ 3 rows in set (0.00 sec) وبدلًا من كتابة كل عنصر في مجموعة بنفسك، يُمكنك تكوين مجموعة من خلال إلحاق عامل IN بالاستعلام الفرعي. يُعرف الاستعلام الفرعي أيضًا بالاستعلام المُدمج أو الداخلي، وهو تعليمة SELECT مُدرجة ضمن إحدى بنى تعليمة SELECT أخرى. يُمكن للاستعلام الفرعي أن يستخرج المعلومات من أي جدول ضمن نفس قاعدة البيانات المحددة في بنية FROM للعملية الرئيسة 'الخارجية'. ملاحظة: عند كتابة استعلام فرعي لتحديد مجموعة ضمن التابع الشرطي للعضوية، تأكد من استخدام استعلام فرعي ذو قيمة مفردة، أي استعلام يُعيد عمودًا واحدًا فقط. تميل أنظمة إدارة قواعد البيانات إلى عدم السماح باستعلامات فرعية تُعيد عدة أعمدة ضمن التابع الشرطي للعضوية، نظرًا لعدم وضوح العمود الذي يجب تقييمه لتحديد العناصر المنتمية للمجموعة. كمثال على استخدام الاستعلام الفرعي لتحديد مجموعة في تابع شرطي للعضوية، نفذ التعليمة التالية لإنشاء جدول يُسمى example_set_table يحتوي على عمود واحد فقط. سنسمى هذا العمود prime_numbers وسيحتوي على قيم من نمط البيانات int، على النحو: mysql> CREATE TABLE example_set_table ( mysql> prime_numbers int mysql> ); لنملأ الآن هذا الجدول ببضعة سجلات من البيانات التجريبية النموذجية. وفقًا لاسم العمود الوحيد في الجدول، ستُضيف التعليمة INSERT التالية عشرة سجلات إلى الجدول، ويحتوي كل منها على أحد الأعداد الأولية العشرة الأولى: mysql>INSERT INTO example_set_table mysql>VALUES mysql> (2), mysql> (3), mysql> (5), mysql> (7), mysql> (11), mysql> (13), mysql> (17), mysql> (19), mysql> (23), mysql> (29); لنُشغّل الآن الاستعلام التالي الذي يُعيد قيمًا من أعمدة name و widgets في جدول sales، إذ تختبر بنية WHERE ما إذا كانت كل قيمة في عمود widgets تنتمي للمجموعة التي حصلنا عليها من الاستعلام الفرعي SELECT prime_numbers FROM example_set_table: mysql> SELECT name, widgets mysql> FROM sales mysql> WHERE widgets IN (SELECT prime_numbers FROM example_set_table); الخرج +-------+---------+ | name | widgets | +-------+---------+ | Blair | 19 | | Lynn | 7 | | Lisa | 17 | | Maya | 5 | +-------+---------+ 4 rows in set (0.00 sec) بما أنّ أربعة فقط من أعضاء فريق المبيعات باعوا عددًا من الأجهزة الصغيرة يُطابق أحد الأعداد الأولية الموجودة في جدول example_set_table، سيُعيد هذا الاستعلام تلك السجلات الأربعة فقط. الخلاصة باطلاعك على هذا المقال، ستكون قد اكتسبت المعرفة حول كيفية استخدام العامل BETWEEN في SQL لتحديد ما إذا كانت قيم في عمود ما تندرج ضمن نطاق محدد، كما تعلمت كيفية استخدام عامل IN لتحديد ما إذا كانت قيم في عمود ما تنتمي إلى مجموعة معينة. ومن المفترض أن تعمل الأوامر المشروحة في هذا المقال مع أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن تذكر أن لكل قاعدة بيانات SQL تقديمها الخاص للغة، لذا ينبغي مراجعة التوثيق الرسمي لنظام إدارة قواعد البيانات الخاص بك للحصول على وصف أكثر تفصيلاً لكل أمر فيها ومجموعة خياراته الكاملة. وللمزيد حول SQL، نشجعك على متابعة المقالات المنشورة تحت وسم سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Use the BETWEEN and IN Operators in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية استخدام بنى WHERE في لغة الاستعلام البنيوية SQL الاستعلام عن البيانات في SQL الاستعلامات الفرعية والإجراءات في SQL التوثيق العربي للغة SQL
  2. سنتعرف في مقال اليوم على دور البنية WHERE في تعليمات لغة الاستعلام البنيوية SQL لتحديد السجلات التي ستتأثر بكل عملية استعلام، وذلك بتعريف معايير أو شروط محددة تُعرف باسم شروط البحث والتي يجب أن يستوفيها كل سجل ليتأثر بالعملية المطلوب تنفيذها، حيث سنوفر شرحًا للصيغة العامة المستخدمة في بنية WHERE. ونوضح كيفية دمج عدة شروط بحث في بنية واحدة لتصفية البيانات بدقة أكبر، كما سنوضح كيفية استخدام العامل NOT لاستثناء السجلات التي تلبي شرط بحث معين بدلًا من تضمينها. وبالرغم من أننا سنستخدم في أمثلتنا بهذا المقال تعليمات SELECT على وجه التحديد، إلّا أنّه من الممكن استخدام المفاهيم الموضحة فيه في العديد من عمليات SQL، إذ يمكن استخدام بنية WHERE كذلك في عمليات تحديث البيانات UPDATE أو حذفها DELETE. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز كمبيوتر يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية التي تستخدم لغة SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، كما هو موضح في مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة الثالثة من هذا المقال. ستحتاج أيضًا إلى قاعدة بيانات بجداول مُحمّلة ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على كتابة استعلامات تتضمّن بنى WHERE. لذا ننصحك بقراءة الفقرة التالية التي تشرح طريقة الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول تنفيذ الأمثلة المُستخدمة خلال هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL، فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات الطفيفة في الصيغة أو الخرج عند تنفيذها على أنظمة مختلفة عن MySQL. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو التالي: $ ssh ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p الآن ومن نافذة سطر الأوامر، أنشئ قاعدة بيانات باسم where_db كما يلي: mysql> CREATE DATABASE where_db; بمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات where_db، نفّذ تعليمة USE التالية: mysql> USE where_db; الخرج Database changed بعد اختيار قاعدة البيانات where_db، أنشئ جدولًا ضمنها. ولمتابعة الأمثلة المستخدمة في هذا المقال، سنفترض أننا نرغب بإدارة دوري للغولف في ملعب غولف محلي. وقررنا تتبع المعلومات حول أداء كل لاعب في الدوري خلال الجولات التي سيشارك بها، لذا قررنا تخزين المعلومات في قاعدة بيانات تتضمن جدولًا باسم golfers. وارتأينا أنّ هذا الجدول يحتاج إلى ستة أعمدة وهي: name: أسماء لاعبي الغولف، مُعبر عنها باستخدام نمط البيانات varchar بحد أقصى 20 محرفًا. rounds_played: إجمالي عدد الجولات التي لعبها كل لاعب غولف كاملةً، مُعبر عنها بنمط بيانات الأعداد الصحيحة int. best: أفضل أو أدنى نتيجة لكل لاعب جولف لجولة فردية، مُعبرًا عنها أيضًا بنمط الأعداد الصحيحة int. worst: أسوأ أو أعلى نتيجة لكل لاعب جولف لجولة فردية، مُعبرًا عنها كذلك بنمط الأعداد الصحيحة int. average: متوسط تقريبي لنتائج كل لاعب غولف عبر الجولات التي لعبوها، سيحتوي هذا العمود على قيم من نوع decimal، محددة بحد أقصى 4 أرقام، واحد منها على يمين الفاصلة العشرية. wins: عدد الجولات التي حقق فيها كل لاعب غولف أقل نتيجة بين جميع المشاركين في المجموعة، مُعبر عنها باستخدام نمط int. ملاحظة: قد تستغرب لماذا تكون النتيجة الأفضل best لكل لاعب أدنى من نتيجته الأسوأ worst، وهذا يعود لطبيعة قواعد لعبة الغولف التي تقتضي أن يكون الفائز هو من ينجز اللعبة بأقل عدد من الضربات. بالتالي، وبخلاف الرياضات الأخرى، تُعد النتيجة الأدنى هي الأفضل للاعب الغولف. لإنشاء جدول باسم golfers يحتوي على هذه الأعمدة الستة، نفّذ التعليمة CREATE TABLE التالية: mysql> CREATE TABLE golfers ( mysql> name varchar(20), mysql> rounds_played int, mysql> best int, mysql> worst int, mysql> average decimal (4,1), mysql> wins int mysql> ); الآن سنملأ جدول golfers ببعض البيانات التجريبية. نفّذ العملية INSERT INTO التالية لإضافة سبع سجلات من البيانات تمثل سبعة من لاعبي الدوري للغولف: mysql> INSERT INTO golfers mysql> VALUES mysql> ('George', 22, 68, 103, 84.6, 3), mysql> ('Pat', 25, 65, 74, 68.7, 9), mysql> ('Grady', 11, 78, 118, 97.6, 0), mysql> ('Diane', 23, 70, 92, 78.8, 1), mysql> ('Calvin', NULL, 63, 76, 68.5, 7), mysql> ('Rose', NULL, 69, 84, 76.7, 4), mysql> ('Raymond', 18, 67, 92, 81.3, 1); نلاحظ أن قيم rounds_played لبعض سجلات اللاعبين فارغة NULL. فلنفترض جدلًا أنّ هؤلاء اللاعبين لم يُبلغوا بعد عن عدد الجولات التي شاركوا فيها، ولهذا السبب سُجلت هذه القيم على أنّها فارغة NULL. وبذلك غدوتَ جاهزًا للمتابعة بباقي أقسام المقال وبدء تعلم كيفية استخدام بنى WHERE في SQL. تصفية البيانات باستخدام بنى WHERE تُعرّف التعليمة البرمجية في SQL بأنّها أي عملية تُرسَل إلى نظام قاعدة البيانات لتنفيذ مهمّة محددة، من قبيل إنشاء جدول أو إدخال أو حذف بيانات أو تغيير هيكلية عمود أو جدول. وتتألف تعليمات SQL من بنى مختلفة تتكون بدورها من كلمات مفتاحية معينة مع المعلومات التي تتطلبها هذه الكلمات. وكما ذكرنا في المقدمة، تتيح بنى WHERE إمكانية تصفية بعض السجلات كي لا تتأثر بعملية SQL محددة. وتأتي بنية WHERE في الاستعلامات، بعد بنية FROM، كما في المثال التالي: mysql> SELECT columns_to_query mysql> FROM table_to_query mysql> WHERE search_condition; يأتي شرط البحث بعد كلمة WHERE المفتاحية. وما شرط البحث سوى مجموعة من التوابع الشرطية أو التعبيرات القادرة على تقييم تعبير قيمة واحد أو أكثر لتعيد نتيجة تكون إمّا "صحيحة True" أو "خاطئة False" أو "غير محددة Unknown"، ومن الجدير بالملاحظة أنّه في الحالات التي يحتوي فيها شرط البحث على تابع شرطي واحد فقط، يكون المصطلحان "شرط البحث" و"التابع الشرطي" مترادفين. قد تأخذ التوابع الشرطية في شرط البحث الخاص ببنية WHERE أشكالًا عديدة، لكنها عادةً ما تتبع الصيغة التالية: WHERE column_name OPERATOR value_expression يُعرّف تعبير القيمة في لغة SQL - والذي يُشار إليه أحيانًا باسم التعبير ذو القيمة المفردة - بأنّه أي تعبير يُعيد قيمة واحدة. يمكن أن يكون تعبير القيمة عبارة عن قيمة مُصنفة النوع من قبيل سلسلة نصية أو قيمة عددية، أو تعبير رياضي. ولكن غالبًا ما يكون على الأقل أحد تعبيرات القيمة في شرط بحث بنية WHERE هو اسم عمود. فلدى تشغيل استعلامات SQL التي تحتوي على بنية WHERE، سيطبّق نظام إدارة قاعدة البيانات شرط البحث تتابعيًا على كل سجل في الجدول المحدد في بنية FROM. ولن يعيد سوى السجلات التي يُقيّم فيها كل شرط بحث على أنه صحيح True. لتوضيح هذه الفكرة، شغّل الاستعلام التالي. والذي سيعيد كل قيمة من العمود name في الجدول golfers: mysql> SELECT name mysql> FROM golfers mysql> WHERE (2 + 2) = 4; يتضمن هذا الاستعلام بنية WHERE، لكن بدلًا من تحديد اسم عمود فإنها تستخدم (2 + 2) كتعبير قيمة أول وتختبر ما إذا كان مساويًا لتعبير القيمة الثاني 4. ونظرًا لأنّ التعبير (2 + 2) يساوي دائمًا 4، فإن شرط البحث هذا يُقيّم على أنه صحيح لكل سجل في الجدول. ونتيجةً لذلك، تُرجع قبم كافّة السجلات في مجموعة النتائج، على النحو التالي: الخرج +---------+ | name | +---------+ | George | | Pat | | Grady | | Diane | | Calvin | | Rose | | Raymond | +---------+ 7 rows in set (0.01 sec) لعلّ بنية WHERE هذه ليست مفيدة بدرجة كبيرة، إذ إنها تُقيم دائمًا على أنها "صحيحة True" وبالتالي تُرجع دائمًا كافة سجلات الجدول. وكما ذكرنا سابقًا، عادةً ما نستخدم اسم عمود واحد على الأقل كأحد تعبيري القيمة في شرط البحث ضمن بنية WHERE. فلدى تشغيل الاستعلامات، سيطبق نظام قاعدة البيانات شرط البحث على كل سجل على حدة تباعًا. ومن خلال توفير اسم عمود كتعبير قيمة في شرط بحث، فإنك تُخبر نظام إدارة قاعدة البيانات باستخدام قيمة كل سجل من العمود المحدد كجزء من تعبير القيمة للتكرار الخاص بكل سجل في شرط البحث. تُطبّق بنية WHERE في الاستعلام التالي شرط بحث أكثر تحديدًا على كل سجل. إذ ستُرجع قيم كل من عمودي name وwins من أي سجل تساوي فيه قيمة wins الرقم 1: mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins = 1; يُرجع هذا الاستعلام سجليّن للاعبي جولف، نظرًا لوجود لاعبين قد فازا بجولة واحدة فقط، فيكون الخرج على هذا النحو: الخرج +---------+------+ | name | wins | +---------+------+ | Diane | 1 | | Raymond | 1 | +---------+------+ 2 rows in set (0.01 sec) من الجدير بالملاحظة أنّنا استخدمنا في الأمثلة السابقة علامة المساواة = لاختبار ما إذا كان تعبيرا القيمة متكافئين، إلا أنّ العامل المُستخدم يعتمد على نوع التابع الشرطي الذي ترغب باستخدامه لتصفية مجموعات النتائج الخاصة بك. يُحدّد معيار SQL ثمانية عشر نمطًا مختلفًا من التوابع الشرطية، على الرغم من أنّها لا تتوفر كاملةً في كافّة تقديمات SQL. إليك خمسة من أكثر أنماط التوابع الشرطية استخدامًا، بالإضافة إلى شرح موجز لكل منها والعوامل المستخدمة فيها: المقارنة تقارن التوابع الشرطية المقارنِة بين تعبيري قيمة باستخدام عامل مقارنة، وفي معظم الاستعلامات يكون أحد هذين التعبيرين هو اسم عمود. وعوامل المقارنة الستة هي: العامل =: يختبر ما إذا كانت القيمتان متساويتين mysql> SELECT name mysql> FROM golfers mysql> WHERE name = 'George'; الخرج +--------+ | name | +--------+ | George | +--------+ 1 row in set (0.00 sec) العامل <>: يختبر ما إذا كانت القيمتان غير متساويتين mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins <> 1; الخرج +--------+------+ | name | wins | +--------+------+ | George | 3 | | Pat | 9 | | Grady | 0 | | Calvin | 7 | | Rose | 4 | +--------+------+ 5 rows in set (0.00 sec) العامل <: يختبر ما إذا كانت القيمة الأولى أقل من الثانية تمامًا mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins < 1; الخرج +-------+------+ | name | wins | +-------+------+ | Grady | 0 | +-------+------+ 1 row in set (0.00 sec) العامل >: يختبر ما إذا كانت القيمة الأولى أكبر من الثانية تمامًا mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins > 1; الخرج +--------+------+ | name | wins | +--------+------+ | George | 3 | | Pat | 9 | | Calvin | 7 | | Rose | 4 | +--------+------+ 4 rows in set (0.00 sec) العامل <=: يختبر ما إذا كانت القيمة الأولى أقل من أو تساوي الثانية mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins <= 1; الخرج +---------+------+ | name | wins | +---------+------+ | Grady | 0 | | Diane | 1 | | Raymond | 1 | +---------+------+ 3 rows in set (0.00 sec) العامل >=: يختبر ما إذا كانت القيمة الأولى أكبر من أو تساوي القيمة الثانية mysql> SELECT name, wins mysql> FROM golfers mysql> WHERE wins >= 1; الخرج +---------+------+ | name | wins | +---------+------+ | George | 3 | | Pat | 9 | | Diane | 1 | | Calvin | 7 | | Rose | 4 | | Raymond | 1 | +---------+------+ 6 rows in set (0.00 sec) القيم الفارغة تختبر التوابع الشرطية التي تستخدم عامل IS NULL ما إذا كانت القيم في عمود معين فارغة، فإذا كان الأمر كذلك فعلًا، سيقيّم التابع الشرطي على أنه "صحيح"، وبالتالي سيُضمّن السجل في مجموعة النتائج: mysql> SELECT name, rounds_played mysql> FROM golfers mysql> WHERE rounds_played IS NULL; الخرج +--------+---------------+ | name | rounds_played | +--------+---------------+ | Calvin | NULL | | Rose | NULL | +--------+---------------+ 2 rows in set (0.00 sec) النطاق تستخدم التوابع الشرطية النطاقية عامل BETWEEN لاختبار ما إذا كانت قيم العمود محصورة بين تعبيري قيمة آخرين. mysql> SELECT name, best mysql> FROM golfers mysql> WHERE best BETWEEN 67 AND 73; الخرج +---------+------+ | name | best | +---------+------+ | George | 68 | | Diane | 70 | | Rose | 69 | | Raymond | 67 | +---------+------+ 4 rows in set (0.00 sec) الانتماء أو العضوية يستخدم هذا النوع من التوابع الشرطية عامل IN لاختبار ما إذا كانت قيمة ما تنتمي لمجموعة معينة. mysql> SELECT name, best mysql> FROM golfers mysql> WHERE best IN (65, 67, 69, 71); الخرج +---------+------+ | name | best | +---------+------+ | Pat | 65 | | Rose | 69 | | Raymond | 67 | +---------+------+ 3 rows in set (0.00 sec) تطابق الأنماط تستخدم توابع مطابقة الأنماط الشرطية عامل LIKE لاختبار ما إذا كانت قيمة ما تطابق نمطًا نصيًا يحتوي على محرف بدل واحد أو أكثر. وتُعرّف SQL محرفي بدل هما % و _: محرف _: شرطة سفلية تُمثّل محرفًا واحدًا مجهولًا mysql> SELECT name, rounds_played mysql> FROM golfers mysql> WHERE rounds_played LIKE '2_'; الخرج +--------+---------------+ | name | rounds_played | +--------+---------------+ | George | 22 | | Pat | 25 | | Diane | 23 | +--------+---------------+ 3 rows in set (0.00 sec) محرف %: علامة النسبة المئوية تُمثّل صفر أو أكثر من المحارف المجهولة mysql> SELECT name, rounds_played mysql> FROM golfers mysql> WHERE name LIKE 'G%'; الخرج +--------+---------------+ | name | rounds_played | +--------+---------------+ | George | 22 | | Grady | 11 | +--------+---------------+ 2 rows in set (0.00 sec) لن نفصّل بشرح كل نمط من التوابع الشرطية فهو خارج مجال هذا المقال، ولمعرفة المزيد حول هذه الأنماط، ننصحك بالاطلاع على المقالات التالية: كيفية استخدام عوامل المقارنة وIS NULL في لغة الاستعلام البنيوية SQL كيفية استخدام عوامل BETWEEN وIN في لغة الاستعلام البنيوية SQL كيفية استخدام محارف البدل في SQL دمج التوابع الشرطية المتعددة باستخدام عوامل AND وOR قد نضطر في الكثير من الأحيان إلى تصفية النتائج على نحوٍ أدق مما توفره بنية WHERE ذات تابع شرطي وحيد. ومن ناحيةٍ أخرى، قد تكون السجلات التي تحقق واحدًا من شروط بحث متعددة مقبولة ضمن مجموعة النتائج في بعض الأحيان. وفي هذه الحالات، يمكنك كتابة بنى WHERE تتضمن توابع شرطية متعددة باستخدام عوامل AND أو OR على التوالي. للبدء باستخدام هذه العوامل، لنشغّل الاستعلام التالي الذي يعيد قيم من أعمدة name وbest وworst وaverage في جدول golfers. إذ تتضمن بنية WHERE الخاصة بهذا الاستعلام تابعين شرطيين مفصولين بعامل AND: mysql> SELECT name, best, worst, average mysql> FROM golfers mysql> WHERE best < 70 AND worst < 96; يختبر التابع الشرطي الأول ما إذا كانت أفضل قيمة (قيمة العمود best) لكل سجل تقل عن 70، في حين يختبر التابع الشرطي الثاني ما إذا كانت أسوأ قيمة (قيمة العمود worst) لكل سجل تقل عن 96. الآن وفي حال تقييم أي من الشرطين على أنه "خاطئ False" لسجل ما، فإنّ هذا السجل لن يُعاد ضمن مجموعة النتائج: الخرج +---------+------+-------+---------+ | name | best | worst | average | +---------+------+-------+---------+ | Pat | 65 | 74 | 68.7 | | Calvin | 63 | 76 | 68.5 | | Rose | 69 | 84 | 76.7 | | Raymond | 67 | 92 | 81.3 | +---------+------+-------+---------+ 4 rows in set (0.00 sec) الآن، لنشغّل الاستعلام التالي، وهو كما تلاحظ مطابق للمثال السابق، باستثناء فصل التابعين الشرطيين بعامل OR بدلًا من AND: mysql> SELECT name, best, worst, average mysql> FROM golfers mysql> WHERE best < 70 OR worst < 96; نلاحظ أنّ مجموعة النتائج في هذا المثال تتضمّن سجلين أكثر من المثال السابق، وذلك نظرًا لأنّه مع استخدام عامل OR يكفي تقييم تابع شرطي واحد على أنّه "صحيح True" للسجل لكي يُعاد ضمن مجموعة النتائج: الخرج +---------+------+-------+---------+ | name | best | worst | average | +---------+------+-------+---------+ | George | 68 | 103 | 84.6 | | Pat | 65 | 74 | 68.7 | | Diane | 70 | 92 | 78.8 | | Calvin | 63 | 76 | 68.5 | | Rose | 69 | 84 | 76.7 | | Raymond | 67 | 92 | 81.3 | +---------+------+-------+---------+ 6 rows in set (0.00 sec) يمكنك إدراج العديد من التوابع الشرطية في بنية WHERE واحدة بشرط دمجها باستخدام الصياغة المناسبة. ولكن قد يصعب تنبؤ بالبيانات التي ستُصفى مع زيادة تعقيد شروط البحث. من الجدير بالذكر أن أنظمة قواعد البيانات تميل لإعطاء الأولوية لعوامل AND. هذا يعني أن التوابع الشرطية التي تفصل بينها عوامل AND تعدّ كشرط بحث موحد مستقل يُختبر قبل أي توابع شرطية أخرى في بنية WHERE. لتوضيح ذلك، شغّل الاستعلام التالي الذي يسترجع قيمًا من أعمدة name وaverage وworst وrounds_played لكل سجل يستوفي شروط البحث المحددة في بنية WHERE: mysql> SELECT name, average, worst, rounds_played mysql> FROM golfers mysql> WHERE average < 85 OR worst < 95 AND rounds_played BETWEEN 19 AND 23; يبدأ هذا الاستعلام باختبار ما إذا كان كلا التابعين الشرطيين (worst < 95 و rounds_played BETWEEN 19 AND 23) المفصولين بعامل AND يقيمان على أنهما محققان بالنسبة للسجل قيد الاختبار الحالي. فإذا كان الأمر كذلك، سيظهر هذا السجل ضمن مجموعة النتائج. أمّا إذا قُيّم أحدهما أو كلاهما على أنه غير محقق "false"، فسينتقل الاستعلام لفحص ما إذا كانت قيمة average للصف الحالي أقل من 85. وفي حال كانت كذلك، سيظهر الصف ضمن مجموعة النتائج. الخرج +---------+---------+-------+---------------+ | name | average | worst | rounds_played | +---------+---------+-------+---------------+ | George | 84.6 | 103 | 22 | | Pat | 68.7 | 74 | 25 | | Diane | 78.8 | 92 | 23 | | Calvin | 68.5 | 76 | NULL | | Rose | 76.7 | 84 | NULL | | Raymond | 81.3 | 92 | 18 | +---------+---------+-------+---------------+ 6 rows in set (0.00 sec) يمكنك منح الأولوية لمجموعة من تابعين شرطيين فأكثر بوضعهم داخل أقواس. المثال التالي يطابق المثال السابق، لكنه يضع التابعين الشرطيين average < 85 وworst < 95، المفصولين بعامل OR، ضمن أقواس. mysql> SELECT name, average, worst, rounds_played mysql> FROM golfers mysql> WHERE (average < 85 OR worst < 95) AND rounds_played BETWEEN 19 AND 23; نظرًا لأن التابعين الشرطيين في البداية مُحاطين بأقواس، فيعاملهما عامل AND الذي يليهما كشرط بحث مستقل، والذي يجب أن يُقيّم على أنه محقق “True”. فإذا قُيّم كلا التابعين الشرطيين (average < 85 وworst < 95) على أنهما غير محققين “false”، فسيُعتبر شرط البحث بأكمله غير محقق “False” وبالتالي سيستبعد الاستعلام هذا السجل من مجموعة النتائج على الفور قبل أن ينتقل لتقييم السجل التالي. أمّا إذا قُيّم أي من التابعين الشرطيين بين القوسين على أنه محقق “True”، فيبدأ الاستعلام حينها في اختبار ما إذا كانت قيمة rounds_played للاعب الجولف تقع ضمن النطاق 19 و 23. وفي حال تحقق ذلك، يُضم السجل إلى مجموعة النتائج المُعادة. الخرج +--------+---------+-------+---------------+ | name | average | worst | rounds_played | +--------+---------+-------+---------------+ | George | 84.6 | 103 | 22 | | Diane | 78.8 | 92 | 23 | +--------+---------+-------+---------------+ 2 rows in set (0.00 sec) كما تُظهر هذه النتائج، بإعطاء الأولوية لمجموعات التوابع الشرطية وضمها ضمن أقواس، يمكن أن تُنتج الاستعلامات المتشابهة ظاهريًا مجموعات نتائج متباينة بدرجة كبيرة. مع أنه لا يُشترط دومًا اللجوء إلى هذا الأسلوب، إلا أنه يُوصى باستخدام الأقواس عند دمج أكثر من تابعين شرطيين ضمن شرط بحث واحد ليُعزز من مقروئية الاستعلامات ويسهّل فهمها. استثناء النتائج باستخدام عامل NOT ركّزت جميع الأمثلة في هذا المقال حتى الآن على كيفية كتابة استعلامات باستخدام بنية WHERE، والتي تُضمّن فقط السجلات التي تُحقّق شروط البحث المُحددة في مجموعة النتائج. ولكن يُمكنك كتابة استعلامات تستثني سجلات مُحددة عبر إدراج عامل NOT ضمن بنية WHERE. وعادةً ما تتبع بنى التوابع الشرطية للنطاق والعضوية وتطابق الأنماط التي تشمل عامل NOT الصياغة العامة التالية: mysql> . . . mysql> WHERE column_name NOT OPERATOR value_expression mysql> . . . للتوضيح، شغّل الاستعلام التالي الذي سيعيد قيمًا من عمود name في جدول golfers، ولكن وجود عامل NOT في بنية WHERE سيُلزم نظام إدارة قاعدة البيانات باستثناء أي سجلات تُطابق نمط محرف البدل: mysql> SELECT name mysql> FROM golfers mysql> WHERE name NOT LIKE 'R%'; الخرج +--------+ | name | +--------+ | George | | Pat | | Grady | | Diane | | Calvin | +--------+ 5 rows in set (0.00 sec) تتغير الأمور قليلًا عند إضافة عامل NOT إلى توابع IS NULL الشرطية. في هذه الحالات، يُدرج العامل NOT بين IS وNULL كما في المثال التالي. يُعيد هذا الاستعلام قيم name وrounds_played لجميع لاعبي الغولف الذين لا تكون قيمة rounds_played الخاصة بهم فارغة، على النحو: mysql> SELECT name, rounds_played mysql> FROM golfers mysql> WHERE rounds_played IS NOT NULL; الخرج +---------+---------------+ | name | rounds_played | +---------+---------------+ | George | 22 | | Pat | 25 | | Grady | 11 | | Diane | 23 | | Raymond | 18 | +---------+---------------+ 5 rows in set (0.00 sec) كما يُمكنك وضع عامل NOT مباشرةً بعد الكلمة المفتاحية WHERE. الأمر الذي يعدّ مفيدًا لا سيما في حال رغبتك باستثناء سجلات بناءً على ما إذا كانت تحقق عدة شروط بحث، كما في الاستعلام التالي الذي يعيد قيم كل من أعمدة name و average و best و wins للاعبي الغولف. mysql> SELECT name, average, best, wins mysql> FROM golfers mysql> WHERE NOT (average < 80 AND best < 70) OR wins = 9; الخرج +---------+---------+------+------+ | name | average | best | wins | +---------+---------+------+------+ | George | 84.6 | 68 | 3 | | Pat | 68.7 | 65 | 9 | | Grady | 97.6 | 78 | 0 | | Diane | 78.8 | 70 | 1 | | Raymond | 81.3 | 67 | 1 | +---------+---------+------+------+ 5 rows in set (0.00 sec) بالنظر إلى السجل الثاني من مجموعة النتائج أعلاه، نلاحظ أنّ متوسط نتيجة اللاعبة Pat في العمود average أقل من 80 وأفضل نتيجة لها في العمود best أقل من 70. ومع ذلك سجلها مُضمّن في مجموعة النتائج، وذلك نظرًا لأن عامل NOT يُلغي فقط شروط البحث المُحاطة بالأقواس. تذكر أنه عند إحاطة توابع شرطية متعددة مفصولة بعوامل AND أو OR بأقواس، تُعطى الأولوية لهذه التوابع في SQL وتُعامل كشرط بحث مستقل. بالتالي، يستثني عامل NOT السجلات بناءً على أول تابعي شرط فقط (average<80 و best<70). في حين تُضمّن السجلات بناءً على التابع الشرطي الثالث (wins=9). يمكنك إعادة كتابة الاستعلام لاستبعاد السجلات بناءً على التابع الشرطي الثالث أيضًا بالإضافة إلى التابعين الأول والثاني وذلك بإحاطة التوابع الثلاثة ضمن أقواس، كما في المثال التالي: mysql> SELECT name, average, best, wins mysql> FROM golfers mysql> WHERE NOT ((average < 80 AND best < 70) OR wins = 9); الخرج +---------+---------+------+------+ | name | average | best | wins | +---------+---------+------+------+ | George | 84.6 | 68 | 3 | | Grady | 97.6 | 78 | 0 | | Diane | 78.8 | 70 | 1 | | Raymond | 81.3 | 67 | 1 | +---------+---------+------+------+ 4 rows in set (0.00 sec) قد يعدّ نظام قاعدة البيانات لديك صيغة الاستعلام غير صالحة في حال تضمين العامل NOT قبل عامل مقارنة وذلك تبعًا لتقديم SQL المُستخدم. كمثال، لنجرب تشغيل الاستعلام التالي: mysql> SELECT name mysql> FROM golfers mysql> WHERE name NOT = 'Grady'; سيؤدي استخدام هذا الأمر في MySQL أو أي من الأنظمة المستندة إليها إلى حدوث خطأ. الخرج ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '= 'Grady'' at line 1 السبب وراء هذا الخطأ هو أنّ عامل NOT لا يُستخدم عادةً مع عوامل المقارنة (= و<> و< و<= و> و>=)، وذلك نظرًا لإمكانية تحقيق الأثر المعاكس لعامل مقارنة معيّن باستبداله بآخر يعيد السجلات التي كان الأول سيستثنيها. على سبيل المثال، يمكنك استبدال عامل المساواة (=) بعامل عدم المساواة (<>). الخلاصة باطلاعك على هذا المقال،تكون قد اكتسبت المعرفة حول كيفية كتابة بنى WHERE بطريقة تجعل الاستعلام يُعيد فقط السجلات التي تستوفي شرطًا معينًا. كما تعلمت كيفية دمج عدّة توابع شرطية وشروط بحث في استعلام واحد، ناهيك عن كيفية استخدام العامل NOT لاستثناء معلومات من مجموعات النتائج. ومن المفترض أن تعمل الأوامر المشروحة في هذا المقال مع أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن تذكر أن لكل قاعدة بيانات SQL تقديمها الخاص للغة، لذا ينبغي مراجعة التوثيق الرسمي لنظام إدارة قواعد البيانات الخاص بك للحصول على وصف أكثر تفصيلاً لكل أمر فيها ومجموعة خياراته الكاملة. وللمزيد حول SQL، نشجعك على متابعة المقالات المنشورة تحت وسم سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Use WHERE Clauses in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية الاستعلام عن السجلات من الجداول في SQL ما هي محركات قواعد البيانات؟ أنواع قواعد البيانات وأهم مميزاتها واستخداماتها التعامل مع قواعد البيانات
  3. ينطوي التعامل مع قواعد البيانات بشكلٍ أساسيّ على استخراج المعلومات حول البيانات المُخزّنة ضمنها. ويُطلق مصطلح الاستعلام query على أي عملية لاسترجاع المعلومات من جدول في أنظمة إدارة قواعد البيانات العلاقية. سنبحث في هذا المقال في بنية الاستعلامات بلغة الاستعلام البنيوية SQL وبعض الوظائف والعوامل الأكثر استخدامًا فيها. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز كمبيوتر يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، وللقيام بذلك يمكنك الاطلاع على المقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية RDBMS لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات وجدول مُحمّل ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على كتابة الاستعلامات. لذا ننصحك بقراءة القسم القادم الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية إعداد قاعدة بيانات وجدول لاستخدامهما في الأمثلة خلال هذا المقال. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو: $ ssh ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p الآن ومن نافذة سطر الأوامر، أنشئ قاعدة بيانات باسم queries_DB: mysql> CREATE DATABASE queries_DB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات queries_DB، نفّذ تعليمة USE التالية: mysql> USE queries_DB; الخرج Database changed بعد تحديد قاعدة البيانات queries_db، سننشئ عدة جداول داخلها. للمتابعة مع الأمثلة المستخدمة في هذا المقال، تخيل أنك تدير مبادرة لتنظيف المنتزهات العامة في مدينة ما. إذ تضم المبادرة عددًا من المتطوعين الملتزمين بتنظيف منتزه المدينة الأقرب لمنازل كل منهم من خلال جمع القمامة بانتظام. ولدى الانضمام إلى المبادرة، يضع كل متطوع هدفًا لعدد أكياس القمامة التي يود جمعها كل أسبوع. وبفرض أننا قررنا تخزين المعلومات حول أهداف المتطوعين في قاعدة بيانات SQL باستخدام جدول يحتوي على خمسة أعمدة، على النحو: vol_id: مُعرّف كل متطوع، مُعبرًا عنه بنمط بيانات الأعداد الصحيحة int. سيكون هذا العمود هو المفتاح الأساسي للجدول، مما يعني أن كل قيمة منه ستلعب دور المعرّف الفريد لسجلها المقابل. ونظرًا لأن كل قيمة في المفتاح الأساسي يجب أن تكون فريدة، فسيتم تطبيق قيد UNIQUE على هذا العمود أيضًا. name: اسم كل متطوع، مُعبرًا عنه بنمط البيانات varchar بحد أقصى 20 محرفًا. park: اسم المنتزه التي سيجمع فيها كل متطوع القمامة، مُعبرًا عنه بنمط البيانات varchar بحد أقصى 20 محرفًا. لاحظ أنه يمكن لعدة متطوعين تنظيف نفس المنتزه. weekly_goal: هدف كل متطوع لعدد أكياس القمامة التي يرغب في جمعها في الأسبوع، مُعبرًا عنه بنمط البيانات int. max_bags: الرقم القياسي الشخصي لكل متطوع لأكبر عدد من أكياس القمامة التي جمعها في أسبوع واحد، مُعبرًا عنه بنمط البيانات عدد صحيح int. أنشئ جدولًا باسم volunteers يحتوي على هذه الأعمدة الخمسة بتنفيذ تعليمة CREATE TABLE على النحو: mysql> CREATE TABLE volunteers ( mysql> vol_id int UNIQUE, mysql> name varchar(20), mysql> park varchar(30), mysql> weekly_goal int, mysql> max_bags int, mysql> PRIMARY KEY (vol_id) mysql> ); بعد إنشاء جدول volunteers، املأه ببعض البيانات النموذجية. نفّذ تعليمة INSERT INTO التالية لإضافة سبع سجلات تمثل سبعة من متطوعي البرنامج: mysql> INSERT INTO volunteers mysql> VALUES mysql> (1, 'Gladys', 'Prospect Park', 3, 5), mysql> (2, 'Catherine', 'Central Park', 2, 2), mysql> (3, 'Georgeanna', 'Central Park', 2, 1), mysql> (4, 'Wanda', 'Van Cortland Park', 1, 1), mysql> (5, 'Ann', 'Prospect Park', 2, 7), mysql> (6, 'Juanita', 'Riverside Park', 1, 4), mysql> (7, 'Georgia', 'Prospect Park', 1, 3); وبذلك غدوتَ جاهزًا لمتابعة باقي المقال والبدء في تعلم كيفية إنشاء الاستعلامات في لغة الاستعلام البنيوية SQL. مكونات الاستعلام الأساسية: بنيتي SELECT و FROM تُعرّف التعليمة البرمجية في SQL بأنّها أي عملية تُرسَل إلى نظام قاعدة البيانات لتنفيذ مهمّة محددة، من قبيل إنشاء جدول أو إدخال أو حذف بيانات أو تغيير هيكلية عمود أو جدول. وما الاستعلام سوى تعليمة برمجية في SQL تسترجع معلومات حول البيانات المحفوظة في قاعدة البيانات. لن يُغير الاستعلام أي بيانات موجودة في جدول من تلقاء نفسه، إذ سيقتصر الأمر فقط على استرجاع المعلومات حول البيانات التي يطلبها مُنشئ الاستعلام بشكلٍ صريح. ويُشار إلى المعلومات التي يُعيدها استعلام معين بمجموعة نتائجه. والتي عادةً ما تتكون من عمود واحد أو أكثر من جدول محدد، وكل عمود يُعاد في مجموعة النتائج يمكن أن يحتوي على سجل واحد أو أكثر من المعلومات. فيما يلي الصيغة العامة لاستعلام SQL: mysql> SELECT columns_to_return mysql> FROM table_to_query; تتألف تعليمات SQL من بنى مختلفة، والتي تتكون بدورها من كلمات مفتاحية معينة مع المعلومات التي تتطلبها هذه الكلمات. وفي هذا السياق تتطلب الاستعلامات في SQL منك تضمين بنيتين على الأقل، وهما: SELECT و FROM. ملاحظة: كُتبت كل بنية في هذه صيغة هذا المثال في سطرها الخاص. ولكن يمكن كتابة أي تعليمة برمجية في SQL على سطرٍ واحد على النحو التالي: mysql> SELECT columns_to_return FROM table_to_query; يتبع هذا المقال القاعدة الشائعة في أسلوب SQL بتقسيم التعليمات البرمجية على سطور متعددة بحيث يحتوي كل سطر على بنية واحدة فقط. والهدف من ذلك تحسين قابلية القراءة والفهم لكل مثال، لكن ينبغي الإشارة إلى أنه بإمكانك كتابة استعلام على سطر واحد أو توزيعه على عدة سطور، طالما أنه لا يحتوي على أخطاء في الصياغة. تبدأ كل استعلامات SQL عادةً ببنية SELECT، ولذلك يُشار إليها عمومًا بتعليمات SELECT. وتأتي بعد كلمة SELECT المفتاحية قائمة بأسماء الأعمدة التي ترغب في استرجاعها في مجموعة النتائج، والتي يتم اختيارها من الجدول المُحدد في بنية FROM. يبدأ تنفيذ العملية في استعلامات SQL من بنية FROM. الأمر الذي قد يبدو محيرًا نظرًا لأن بنية SELECT تُكتب قبل FROM، ولكن من الضروري أن يحدد نظام إدارة قواعد البيانات أولًا مجموعة البيانات الكاملة التي سيتم الاستعلام عنها قبل البدء في استرجاع المعلومات منها. يُفيد التفكير في الاستعلامات على أنها عملية اختيار SELECT لأعمدة محددة من FROM جدول مُعين. ومن المهم التذكير بأن كل تعليمة SQL يجب أن تختتم بفاصلة منقوطة (;). كمثال، نفذ الاستعلام التالي الذي يسترجع عمود name من جدول volunteers: mysql> SELECT name mysql> FROM volunteers; إليك مجموعة نتائج هذا الاستعلام: الخرج +------------+ | name | +------------+ | Gladys | | Catherine | | Georgeanna | | Wanda | | Ann | | Juanita | | Georgia | +------------+ 7 rows in set (0.00 sec) على الرغم من أن هذه العملية استعرضت جدول volunteers بأكمله، إلا أنها استرجعت فقط العمود المُحدد، ألا وهو name. يمكنك استرجاع المعلومات من عدة أعمدة عن طريق فصل اسماء الأعمدة بعلامات فاصلة، كما في الاستعلام التالي. إذ سيعيد هذا الاستعلام أعمدة vol_id, name, و park من جدول volunteers: mysql> SELECT park, name, vol_id mysql> FROM volunteers; الخرج +-------------------+------------+--------+ | park | name | vol_id | +-------------------+------------+--------+ | Prospect Park | Gladys | 1 | | Central Park | Catherine | 2 | | Central Park | Georgeanna | 3 | | Van Cortland Park | Wanda | 4 | | Prospect Park | Ann | 5 | | Riverside Park | Juanita | 6 | | Prospect Park | Georgia | 7 | +-------------------+------------+--------+ 7 rows in set (0.00 sec) لاحظ أنّ هذه النتيجة تُعيد العمود park أولًا، يليه عمود name ثم vol_id. تُعيد قواعد البيانات SQL الأعمدة عمومًا بالترتيب الذي تم سرده في بنية SELECT. قد تحتاج في بعض الأحيان إلى استرجاع كل الأعمدة من جدول ما. فبدلًا من كتابة أسماء كافّة الأعمدة في استعلامك، يمكنك ببساطة إدخال علامة النجمة (*). وهي الطريقة المختصرة في SQL، للدلالة على "كل الأعمدة". الاستعلام التالي سيُعيد كل الأعمدة من جدول volunteers: mysql> SELECT * mysql> FROM volunteers; الخرج +--------+------------+-------------------+-------------+----------+ | vol_id | name | park | weekly_goal | max_bags | +--------+------------+-------------------+-------------+----------+ | 1 | Gladys | Prospect Park | 3 | 5 | | 2 | Catherine | Central Park | 2 | 2 | | 3 | Georgeanna | Central Park | 2 | 1 | | 4 | Wanda | Van Cortland Park | 1 | 1 | | 5 | Ann | Prospect Park | 2 | 7 | | 6 | Juanita | Riverside Park | 1 | 4 | | 7 | Georgia | Prospect Park | 1 | 3 | +--------+------------+-------------------+-------------+----------+ 7 rows in set (0.00 sec) لاحظ كيف تُعرَض الأعمدة في هذه النتيجة بنفس الترتيب المُحدّد في تعليمة CREATE TABLE من فقرة الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية السابقة. وهي الطريقة التي ستُرتب بها معظم أنظمة قواعد البيانات العلاقية الأعمدة في مجموعة النتائج عند تنفيذ استعلام يستخدم علامة النجمة (*) بدلًا من أسماء الأعمدة الفردية. ومن الجدير بالملاحظة أنّه من الممكن استرجاع المعلومات من عدة جداول في نفس الاستعلام باستخدام الكلمة المفتاحية JOIN. ونشجعك في هذا الصدد على قراءة مقال استخدام عمليات الدمج في SQL. استبعاد القيم المكررة باستخدام DISTINCT تُعيد أنظمة إدارة قواعد البيانات العلاقية افتراضيًا جميع القيم من أعمدة الجدول المُستعلم عنه، بما في ذلك القيم المكررة. كمثال، نفّذ الاستعلام التالي. إذ سيُرجع القيم من عمود park في جدول volunteers: mysql> SELECT park mysql> FROM volunteers; الخرج +-------------------+ | park | +-------------------+ | Prospect Park | | Central Park | | Central Park | | Van Cortland Park | | Prospect Park | | Riverside Park | | Prospect Park | +-------------------+ 7 rows in set (0.00 sec) لاحظ أن مجموعة النتائج تتضمّن قيمتين مكررتين هما Prospect Park وCentral Park. وهو أمر منطقي، إذ يمكن لعدد من المتطوعين التعاون في تنظيف نفس المتنزه. ومع ذلك، قد ترغب في بعض الأحيان بمعرفة القيم الفريدة المخزنة في عمود ما ويمكنك تحقيق ذلك وإزالة القيم المكررة من نتائج استعلامك باستخدام الكلمة المفتاحية DISTINCT بعد SELECT. سيُرجع الاستعلام التالي كافة القيم الفريدة من عمود park، مُستبعدًا أية قيم مكررة. وهو مُتشابه للاستعلام السابق ولكن مع إضافة كلمة DISTINCT، كما يلي: mysql> SELECT DISTINCT park mysql> FROM volunteers; الخرج +-------------------+ | park | +-------------------+ | Prospect Park | | Central Park | | Van Cortland Park | | Riverside Park | +-------------------+ 4 rows in set (0.00 sec) تحتوي مجموعة نتائج هذا الاستعلام على ثلاث سجلات أقل من الاستعلام السابق، بسبب إزالة إحدى قيم Central Park واثنتين من قيم Prospect Park. تجدر الإشارة إلى أن SQL تُعامل كل سجل في مجموعة النتائج كسجل فردي، وتُزيل DISTINCT القيم المكررة فقط في حال تشاركت عدة سجلات بنفس القيم في كل الأعمدة. لتوضيح ذلك، لنُصدر الاستعلام التالي المُتضمّن للكلمة المفتاحية DISTINCT والذي يُرجع كلا العمودين name وpark: mysql> SELECT DISTINCT name, park mysql> FROM volunteers; الخرج +------------+-------------------+ | name | park | +------------+-------------------+ | Gladys | Prospect Park | | Catherine | Central Park | | Georgeanna | Central Park | | Wanda | Van Cortland Park | | Ann | Prospect Park | | Juanita | Riverside Park | | Georgia | Prospect Park | +------------+-------------------+ 7 rows in set (0.00 sec) تشتمل مجموعة النتائج هذه على قيم مكررة في عمود park، بواقع ثلاث تكرارات لقيم Prospect Park وتكرارين لقيم Central Park، وذلك على الرغم من إدراج الكلمة المفتاحية DISTINCT في الاستعلام. فعلى الرغم من احتواء الأعمدة الفردية في مجموعة النتائج على قيم مكررة، لكن يجب أن تكون السجلات متطابقة بالكامل لتُستبعد من قبل DISTINCT. وفي حالتنا، ونظرًا لأن القيم في عمود name فريدة لكل سجل، فإن DISTINCT لن تزيل أي من السجلات لدى تحديد هذا العمود ضمن بنية SELECT. تصفية البيانات باستخدام بنى WHERE قد ترغب في بعض الحالات باسترجاع معلومات أكثر تحديدًا من جداول قاعدة البيانات. إذ يمكنك تصفية سجلات معينة بإدراج بنية WHERE في استعلامك بعد بنية FROM، كما في المثال التالي: mysql> SELECT columns_to_return mysql> FROM table_to_query mysql> WHERE search_condition; يأتي شرط البحث بعد كلمة WHERE في الصيغة المذكورة بالمثال، والذي يُحدّد على وجه الخصوص أي السجلات مُراد تصفيتها من مجموعة النتائج. وما شرط البحث سوى مجموعة من التوابع الشرطية أو التعبيرات القادرة على تقييم تعبير قيمة واحد أو أكثر. إذ يُعرّف تعبير القيمة في لغة SQL - والذي يُشار إليه أحيانًا باسم التعبير ذو القيمة المفردة - بأنّه أي تعبير يُعيد قيمة واحدة. ويمكن أن يكون تعبير القيمة عبارة عن قيمة محددة النوع (سلسلة نصية أو قيمة عددية)، أو تعبير رياضي، أو اسم عمود. يمكن أن تأخذ التوابع الشرطية في شرط البحث الخاص ببنية WHERE أشكالاً مختلفة، ولكنها عادةً ما تتبع الصيغة التالية: WHERE value expression OPERATOR value_expression فقد وضعنا بعد الكلمة المفتاحية WHERE في هذه الصيغة تعبير قيمة، يليه أحد معاملات SQL الخاصة والمُستخدمة لتقييم قيم الأعمدة بالنسبة لتعبير القيمة (أو تعابير القيم) الآتي بعد العامل. وهناك العديد من هذه العوامل المتاحة في SQL، وسنقدّم في هذا القسم لمحة موجزة عن بعضها، ولكن لغرض التوضيح سنركّز فقط على أحد أكثر العوامل استخدامًا، ألا وهو: علامة المساواة (=). يختبر هذا العامل ما إذا كان تعبيرين يحتويان على قيم متطابقة. دائمًا ما تُعطي التوابع الشرطية الناتج "صحيح True" أو "خاطئ False" أو "غير محدد Unknown". فلدى تشغيل استعلامات SQL التي تحتوي على بنية WHERE، سيطبّق نظام إدارة قاعدة البيانات شرط البحث تتابعيًا على كل سجل في الجدول المحدد في بنية FROM. ولن يعيد سوى السجلات التي يُقيّم فيها كل شرط بحث على أنه "صحيح". لتوضيح هذه الفكرة، نفّذ تعليمة SELECT التالية. يُرجع هذا الاستعلام قيمًا من عمود name في جدول volunteers. لكن بدلًا من تقييم قيم أحد أعمدة الجدول، تختبر بنية WHERE في هذا الاستعلام ما إذا كان التعبير (2 + 2) و 4 متساويين. mysql> SELECT name mysql> FROM volunteers mysql> WHERE (2+2) = 4; ونظرًا لأنّ التعبير (2+2) يساوي 4 دائمًا، فإن شرط البحث هذا يُقيّم بأنه صحيح لكل سجل في الجدول. ونتيجةً لذلك، تُرجع قيمة الاسم لكل سجل في مجموعة النتائج، على النحو: الخرج +------------+ | name | +------------+ | Gladys | | Catherine | | Georgeanna | | Wanda | | Ann | | Juanita | | Georgia | +------------+ 7 rows in set (0.00 sec) ولكن ونظرًا لأن شرط البحث هذا يعيد دائمًا نتيجة "صحيحة"، فهو ليس مفيدًا بدرجة كبيرة. وبالتالي من الممكن في هذه الحالة عدم تضمين بنية WHERE أصلًا، لأن تعليمة SELECT name FROM volunteers; ستعطي نفس مجموعة النتائج كما في حالة استخدام WHERE مع شرط بحث مُحقق دومًا. عادةً ما نستخدم اسم عمود كأحد تعبيري القيمة في شرط البحث ضمن بنية WHERE وذلك بدلاً من مقارنة قيمتين مُحددتي النوع كما في الأسلوب أعلاه. وبذلك نُعلم نظام إدارة قاعدة البيانات باستخدام قيمة كل سجل من العمود المحدد كجزء من تعبير القيمة للتكرار الخاص بكل سجل في شرط البحث. تُطبّق بنية WHERE في الاستعلام التالي شرط بحث أكثر تحديدًا على كل سجل. إذ ستُرجع قيم كل من عمودي name و max_bags من أي سجل تساوي فيه قيمة max_bags الرقم 4: mysql> SELECT name, max_bags mysql> FROM volunteers mysql> WHERE max_bags = 4; يُرجع هذا الاستعلام سجل متطوع واحد فقط، نظرًا لأنّ قيمة max_bags لهذا المتطوع وحده تساوي 4 تمامًا، فيكون الخرج على النحو: الخرج +---------+----------+ | name | max_bags | +---------+----------+ | Juanita | 4 | +---------+----------+ 1 row in set (0.00 sec) يمكنك أيضًا تقييم قيم السلاسل النصية المحرفية في التوابع الشرطية الخاصة بشروط البحث. فمثلًا يُرجع الاستعلام التالي قيم عمودي vol_id و name لكل سجل تكون قيمة العمود name فيه مساوية لـ 'Wanda': mysql> SELECT vol_id, name mysql> FROM volunteers mysql> WHERE name = 'Wanda'; ونظرًا لوجود متطوعة واحدة فقط تُدعى Wanda، فإن الاستعلام يُرجع معلومات سجلها فقط: الخرج +--------+-------+ | vol_id | name | +--------+-------+ | 4 | Wanda | +--------+-------+ 1 row in set (0.00 sec) من الجدير بالملاحظة أنّنا استخدمنا نفس العامل لشرط البحث في جميع أمثلة هذا القسم وهو علامة المساواة وذلك لتوضيح الفكرة. ولكن يوجد العديد من أنواع المعاملات Operators الأخرى التي تتيح لنا إمكانية كتابة مجموعة متنوعة من التوابع الشرطية، مما يوفر مستوى عالٍ من التحكم في المعلومات التي تُرجعها الاستعلامات. يُحدّد معيار SQL ثمانية عشر نمطًا مختلفًا من التوابع الشرطية، وعلى الرغم من أنّها لا تتوفر كاملةً في كافّة أنظمة إدارة قواعد البيانات العلاقية RDBMS. إليك خمسة من أكثر أنواع توابع الشرط شيوعًا في شروط البحث والعوامل المستخدمة في كل منها: المقارنة: تقارن التوابع الشرطية المقارنِة بين تعبيري قيمة، وفي معظم الاستعلامات يكون أحد هذين التعبيرين هو اسم عمود. وعوامل المقارنة الستة هي: = يختبر ما إذا كانت القيمتان متساويتين. <> يختبر ما إذا كانت القيمتان غير متساويتين. < يختبر ما إذا كانت القيمة الأولى أقل من الثانية. > يختبر ما إذا كانت القيمة الأولى أكبر من الثانية. <= يختبر ما إذا كانت القيمة الأولى أقل من أو تساوي الثانية. >= يختبر ما إذا كانت القيمة الأولى أكبر من أو تساوي الثانية. القيم الفارغة: تختبر التوابع الشرطية التي تستخدم عامل IS NULL ما إذا كانت القيم في عمود معين فارغة. النطاق: تستخدم التوابع الشرطية النطاقية عامل BETWEEN لاختبار ما إذا كان تعبير قيمة ما يقع بين تعبيري قيمة آخرين. العضوية: يستخدم هذا النوع من التوابع الشرطية عامل IN لاختبار ما إذا كانت قيمة ما تُمثّل عضوًا في مجموعة معينة. تطابق الأنماط: تستخدم توابع مطابقة الأنماط الشرطية عامل LIKE لاختبار ما إذا كانت قيمة ما تطابق نمطًا نصيًا يحتوي على محارف بدل. لمعرفة المزيد حول هذه الأنواع من التوابع الشرطية، ننصحك بالاطلاع على المقالات التالية: كيفية استخدام عوامل المقارنة و IS NULL في لغة الاستعلام البنيوية SQL كيفية استخدام عوامل BETWEEN و IN في لغة الاستعلام البنيوية SQL كيفية استخدام محارف البدل في SQL وللاطلاع على المزيد حول بنى WHERE عمومًا، ننصحك بقراءة مقالنا حول كيفية استخدام بنى WHERE في لغة الاستعلام البنيوية SQL. فرز نتائج الاستعلام باستخدام بنية ORDER BY قد تُعيد الاستعلامات في بعض الأحيان المعلومات بطرق غير واضحة أو غير متوافقة تمامًا مع احتياجاتك. لذا يمكنك فرز أو ترتيب نتائج الاستعلام بتضمين بنية ORDER BY في نهاية تعليمة الاستعلام. فيما يلي الصيغة العامّة لاستعلام يتضمن بنية ORDER BY: mysql> SELECT columns_to_return mysql> FROM table_to_query mysql> ORDER BY column_name; لتوضيح الأمر، بفرض أننا نرغب في معرفة أي من المتطوعين يحقق أعلى قيمة في عمود max_bags. لنُنفّذ الاستعلام التالي الذي يُعيد قيم عمودي name وmax_bags من جدول volunteers: $ SELECT name, max_bags $ FROM volunteers; ولكن يفرز هذا الاستعلام مجموعة النتائج حسب الترتيب الذي أُضيف فيه كل سجل. الخرج +------------+----------+ | name | max_bags | +------------+----------+ | Gladys | 5 | | Catherine | 2 | | Georgeanna | 1 | | Wanda | 1 | | Ann | 7 | | Juanita | 4 | | Georgia | 3 | +------------+----------+ 7 rows in set (0.00 sec) ولعلّ فرز مجموعة بيانات صغيرة نسبيًا كهذه ليس بتلك الأهمية، إذ يمكننا ببساطة مراجعة قيم max_bags في مجموعة النتائج لإيجاد القيمة الأعلى لكن هذا الأمر قد يصبح متعبًا عند العمل مع كميات أكبر من البيانات. يمكننا تنفيذ الاستعلام ذاته ولكن مع إضافة بنية ORDER BY التي تفرز مجموعة النتائج تبعًا لقيم max_bags للسجلات: $ SELECT name, max_bags $ FROM volunteers $ ORDER BY max_bags; الخرج +------------+----------+ | name | max_bags | +------------+----------+ | Georgeanna | 1 | | Wanda | 1 | | Catherine | 2 | | Georgia | 3 | | Juanita | 4 | | Gladys | 5 | | Ann | 7 | +------------+----------+ 7 rows in set (0.00 sec) كما يُظهر هذا الخرج، فالسلوك الافتراضي لاستعلامات SQL التي تتضمن بنية ORDER BY هو فرز قيم العمود المحدد تصاعديًا (من الأصغر إلى الأكبر). ويمكننا تغيير هذا السلوك وفرزها بترتيب تنازلي عن طريق إضافة الكلمة المفتاحية DESC إلى بنية ORDER BY. $ SELECT name, max_bags $ FROM volunteers $ ORDER BY max_bags DESC; الخرج +------------+----------+ | name | max_bags | +------------+----------+ | Ann | 7 | | Gladys | 5 | | Juanita | 4 | | Georgia | 3 | | Catherine | 2 | | Georgeanna | 1 | | Wanda | 1 | +------------+----------+ 7 rows in set (0.00 sec) الخلاصة باطلاعك على هذا المقال، اكتسبت المعرفة حول كيفية كتابة استعلامات أساسية، وكيفية تصفية وفرز مجموعات نتائج الاستعلام، ومن المفترض أن تعمل الأوامر المشروحة في هذا المقال مع أي نظام لإدارة قواعد البيانات يستخدم SQL، لكن تذكر أن لكل قاعدة بيانات SQL تقديمها الخاص للغة، لذا ينبغي مراجعة التوثيق الرسمي لنظام إدارة قواعد البيانات الخاص بك للحصول على وصف أكثر تفصيلاً لكل أمر فيها ومجموعة خياراته الكاملة. وللمزيد حول SQL، نشجعك على متابعة المقالات المنشورة تحت وسم سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To SELECT Rows FROM Tables in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية حذف البيانات في لغة الاستعلام البنيوية SQL أنواع قواعد البيانات وأهم مميزاتها واستخداماتها تعرف على مكونات قاعدة البيانات ما هي محركات قواعد البيانات؟ فهم قواعد البيانات العلاقية
  4. سنتعرف في مقال اليوم على تعليمة DELETE في لغة الاستعلام البنيوية SQL واحدة من أقوى العمليات المتاحة للمستخدمين. وهي كما يوحي اسمها، تحذف سجلًا أو أكثر من جدول قاعدة البيانات على نحوٍ لا يمكن التراجع عنه. ومن المهم لمستخدمي SQL فهم كيف تعمل تعليمة DELETE باعتبارها جانبًا أساسيًا من إدارة البيانات. سيغطي المقال كيفية استخدام صيغة DELETE في SQL لحذف البيانات من جدول واحد أو أكثر. كما سيشرح كيف تتعامل SQL مع عمليات الحذف التي قد تتعارض مع قيود المفتاح الخارجي Foreign key. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز حاسوب يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، ويمكنك إعداد الخادم بالاستعانة بمقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات وجدول مُحمّل ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على حذف البيانات. لذا ننصحك بقراءة الفقرة التالية الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية إعداد قاعدة بيانات وجدول لاستخدامهما في الأمثلة خلال هذا المقال. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو: $ ssh ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p أنشئ قاعدة بيانات باسمdeleteDB: mysql> CREATE DATABASE deleteDB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات deleteDB، نفّذ تعليمة USE التالية: mysql> USE deleteDB; الخرج Database changed بعد اختيار قاعدة البيانات deleteDB، أنشئ جدولين داخلها. كمثال، تخيل أنك وبعض أصدقائك تملكون ناديًا حيث يمكن للأعضاء مشاركة المعدات الموسيقية مع بعضهم البعض. فقررت إنشاء بعض الجداول لتساعدك في تتبع أعضاء النادي ومعداتهم. سيتضمّن الجدول الأول الأعمدة الأربعة التالية: memberID: مُعرّف كل عضو في النادي، مُعبّر عنه بنمط بيانات الأعداد الصحيحة int. سيكون هذا العمود هو المفتاح الأساسي للجدول. name: اسم كل عضو، مُعبّر عنه بنمط بيانات المحارف varchar مع حد أقصى يصل إلى 30 محرفًا. homeBorough: هذا العمود سيخزن المنطقة التي يعيش فيها كل عضو، مُعبر عنه بنمط البيانات varchar ولكن بحد أقصى يصل إلى 15 محرفًا فقط. email: عنوان البريد الإلكتروني الذي يمكن من خلاله الاتصال بكل عضو، مُعبر عنه بنمط البيانات varchar مع حد أقصى يصل إلى 30 محرفًا. لننشئ إذًا جدولًا باسم clubMembers يحتوي على هذه الأعمدة الأربعة. mysql> CREATE TABLE clubMembers ( mysql> memberID int PRIMARY KEY, mysql> name varchar(30), mysql> homeBorough varchar(15), mysql> email varchar(30) mysql> ); أمّا الجدول الثاني فسيتضمّن الأعمدة التالية: equipmentID: معرّف فريد لكل قطعة من المعدات. إذ ستكون القيم في هذا العمود من نمط بيانات الأعداد الصحيحة int. وسيكون هذا العمود هو المفتاح الأساسي للجدول على نحوٍ مشابه لعمود memberID في جدول clubMembers، equipmentType: نوع الآلة أو الأداة التي يُمثّلها كل سجل (على سبيل المثال الغيتار guitar ومازج الأصوات mixer ومضخّم الصوتamplifier وما إلى ذلك). سنعبّر عن هذه القيم باستخدام نمط البيانات varchar مع حد أقصى يصل إلى 30 محرفًا. brand: العلامة التجارية التي أنتجت كل قطعة من المعدات، معبّر عنها أيضًا بنمط البيانات varchar مع حد أقصى يصل إلى 30 محرفًا. ownerID: هذا العمود سيحتوي على معرّف العضو المالك للقطعة نت المعدات، مُعبر عنه برقم صحيح. ولضمان أنّ عمود ownerID لن يتضمّن سوى قيم تُمثّل مُعرّفات أعضاء صالحة، يمكنك إنشاء قيد مفتاح خارجي عليه بحيث يُشير إلى عمود memberID في جدول clubMembers. يُعد قيد المفتاح الخارجي طريقة لتحديد علاقة بين جدولين، إذ يفرض أن تكون القيم في العمود المُطبّق عليه موجودة بالفعل في العمود المُشار إليه. في المثال التالي، يشترط قيد المفتاح الخارجي أن تكون كل قيمة تُضاف إلى عمود ownerID موجودة مسبقًا في عمود memberID. أنشئ جدولًا بهذه الأعمدة وهذا القيد باسم clubEquipment: mysql> CREATE TABLE clubEquipment ( mysql> equipmentID int PRIMARY KEY, mysql> equipmentType varchar(30), mysql> brand varchar(15), mysql> ownerID int, mysql> CONSTRAINT fk_ownerID mysql> FOREIGN KEY (ownerID) REFERENCES clubMembers(memberID) mysql> ); ومن الجدير بالملاحظة أنّ هذا المثال يوفّر اسمًا لقيد المفتاح الخارجي، ألا وهو: fk_ownerID. إذ تُنشئ MySQL تلقائيًا اسمًا لأي قيد تضيفه، إلّا أنّ تحديد اسم من قبلنا في هذه الحالة سيكون مفيدًا عندما نحتاج للإشارة إلى هذا القيد لاحقًا. بعد ذلك، نفّذ تعليمة INSERT INTO التالية لملء جدول clubMembers بستة سجلات من البيانات النموذجية: mysql> INSERT INTO clubMembers mysql> VALUES mysql> (1, 'Rosetta', 'Manhattan', 'hightower@example.com'), mysql> (2, 'Linda', 'Staten Island', 'lyndell@example.com'), mysql> (3, 'Labi', 'Brooklyn', 'siffre@example.com'), mysql> (4, 'Bettye', 'Queens', 'lavette@example.com'), mysql> (5, 'Phoebe', 'Bronx', 'snow@example.com'), mysql> (6, 'Mariya', 'Brooklyn', 'takeuchi@example.com'); ثم نفّذ تعليمة INSERT INTO أخرى لملء جدول clubEquipment بعشرين سجلًا من البيانات النموذجية: mysql> INSERT INTO clubEquipment mysql> VALUES mysql> (1, 'electric guitar', 'Gilled', 6), mysql> (2, 'trumpet', 'Yemehe', 5), mysql> (3, 'drum kit', 'Purl', 3), mysql> (4, 'mixer', 'Bearinger', 3), mysql> (5, 'microphone', 'Sure', 1), mysql> (6, 'bass guitar', 'Fandar', 4), mysql> (7, 'acoustic guitar', 'Marten', 6), mysql> (8, 'synthesizer', 'Korgi', 4), mysql> (9, 'guitar amplifier', 'Vax', 4), mysql> (10, 'keytar', 'Poland', 3), mysql> (11, 'acoustic/electric bass', 'Pepiphone', 2), mysql> (12, 'trombone', 'Cann', 2), mysql> (13, 'mandolin', 'Rouge', 1), mysql> (14, 'electric guitar', 'Vax', 6), mysql> (15, 'accordion', 'Nonher', 5), mysql> (16, 'electric organ', 'Spammond', 1), mysql> (17, 'bass guitar', 'Peabey', 1), mysql> (18, 'guitar amplifier', 'Fandar', 3), mysql> (19, 'cello', 'Yemehe', 2), mysql> (20, 'PA system', 'Mockville', 5); وبذلك، غدوتَ جاهزًا لمتابعة باقي المقال وبدء التعلم حول كيفية حذف البيانات باستخدام لغة الاستعلام البنيوية SQL. حذف البيانات من جدول واحد إنّ الصيغة العامة لحذف البيانات في SQL على النحو: mysql> DELETE FROM table_name mysql> WHERE conditions_apply; تحذير: الجزء المهم من هذه الصيغة هو البنية WHERE فمن خلالها يمكنك تحديد السجلات التي يجب حذفها بدقة. وبدونها، سيُنفَّذ أمر مثل DELETE FROM table_name; على نحوٍ صحيح، ولكنه سيحذف كل سجلات البيانات من الجدول! وبالعودة إلى موضوعنا، تذكّر أنّ أي عملية حذف ناجحة لا يمكن التراجع عنها. فإذا نفذّت عملية حذف دون معرفة دقيقة بالبيانات التي ستُحذف، فقد تحذف سجلات عن طريق الخطأ. ومن الطرق التي تفيدك في التأكد من عدم حذف بيانات عن طريق الخطأ هي إجراء استعلام عن البيانات المحددة للحذف باستخدام SELECT لرؤية البيانات التي ستعيدها بنية WHERE ضمن عملية الحذف DELETE من البداية قبل تنفيذ عملية الحذف. ولتوضيح الأمر، لنفترض أنّك تريد إزالة أي سجلات مُتعلقة بمعدات الموسيقى المصنعة من قبل العلامة التجارية Korgi. ولكنك قررت البدء بكتابة استعلام لرؤية كافة سجلات الآلات المُتضمنة لعلامة korgi تحديدًا في عمود brand. لمعرفة الآلات الموسيقية في جدولك المُصنّعة من قبل Korgi، يمكنك تنفيذ الاستعلام المبيّن أدناه. ومن الجدير بالملاحظة أنّه وعلى العكس من الاستعلام باستخدام SELECT أو عملية INSERT INTO، فلا تسمح عمليات الحذف بتحديد أعمدة فردية، لأنها مُخصصّة لحذف سجلات البيانات بالكامل. ولمحاكاة هذا السلوك، أتبعنا الكلمة المفتاحية SELECT بعلامة النجمة (*) في الاستعلام التالي والتي تعدّ اختصارًا في SQL يمثل "كل الأعمدة": mysql> SELECT * FROM clubEquipment mysql> WHERE brand = 'Korgi'; الخرج +-------------+---------------+-------+---------+ | equipmentID | equipmentType | brand | ownerID | +-------------+---------------+-------+---------+ | 8 | synthesizer | Korgi | 4 | +-------------+---------------+-------+---------+ 1 row in set (0.00 sec) ولحذف هذا السجل، عليك تنفيذ عملية حذف DELETE تحتوي على بنيتي FROM وWHERE مطابقتين لاستعلام SELECT السابق، على النحو: mysql> DELETE FROM clubEquipment mysql> WHERE brand = 'Korgi'; الخرج Query OK, 1 row affected (0.01 sec) يُظهر هذا الخرج أن عملية الحذف DELETE قد نُفِّذت على سجل واحد فقط. ولكن بإمكانك حذف عدة سجلات باستخدام بنية WHERE تُعيد أكثر من سجل واحد. أمّا استعلام SELECT التالي فيعيد كافّة السجلات في جدول clubEquipment التي يتضمن عمود equipmentType فيها كلمة electric: mysql> SELECT * FROM clubEquipment mysql> WHERE equipmentType LIKE '%electric%'; الخرج +-------------+------------------------+-----------+---------+ | equipmentID | equipmentType | brand | ownerID | +-------------+------------------------+-----------+---------+ | 1 | electric guitar | Gilled | 6 | | 11 | acoustic/electric bass | Pepiphone | 2 | | 14 | electric guitar | Vax | 6 | | 16 | electric organ | Spammond | 1 | +-------------+------------------------+-----------+---------+ 4 rows in set (0.00 sec) ولحذف هذه السجلات الأربعة، لنعد كتابة الاستعلام السابق مستبدلين SELECT * بتعليمة DELETE: mysql> DELETE FROM clubEquipment mysql> WHERE equipmentType LIKE '%electric%'; الخرج Query OK, 4 rows affected (0.00 sec) كما من الممكن استخدام الاستعلامات الفرعية Subqueries لإعادة وحذف مجموعات نتائج أكثر تفصيلاً. ويُعرّف الاستعلام الفرعي بأنّه عملية استعلام كاملة - تعليمة SQL تبدأ بـ SELECT وتتضمن بنية FROM- مُضمنة ضمن عملية أخرى، تأتي عقب بنية FROM الخاصة بالعملية المحيطة (الاستعلام الرئيسي). على سبيل المثال، لنفترض أنك ترغب في حذف أي معدات مُدرجة في جدول clubEquipment تخص أي عضو يبدأ اسمه بالحرف "L". يمكنك أولاً الاستعلام عن هذه البيانات باستخدام تعليمة SELECT كالتالي: mysql> SELECT * mysql> FROM clubEquipment mysql> WHERE ownerID IN mysql> (SELECT memberID FROM clubMembers mysql> WHERE name LIKE 'L%'); تُعيد هذه العملية كل سجل من جدول clubEquipment تظهر قيمة عمود ownerID الخاصة به ضمن القيم المُعادة من الاستعلام الفرعي الذي يبدأ في السطر الرابع. إذ يُعيد هذا الاستعلام الفرعي مُعرّف العضو memberID لأي سجل تبدأ قيمة العمود name الموافقة له بالحرف "L": الخرج +-------------+------------------+-----------+---------+ | equipmentID | equipmentType | brand | ownerID | +-------------+------------------+-----------+---------+ | 12 | trombone | Cann | 2 | | 19 | cello | Yemehe | 2 | | 3 | drum kit | Purl | 3 | | 4 | mixer | Bearinger | 3 | | 10 | keytar | Poland | 3 | | 18 | guitar amplifier | Fandar | 3 | +-------------+------------------+-----------+---------+ 6 rows in set (0.00 sec) يمكنك بعد ذلك حذف هذه البيانات باستخدام تعليمة DELETE التالية: mysql> DELETE FROM clubEquipment mysql> WHERE ownerID IN mysql> (SELECT memberID FROM clubMembers mysql> WHERE name LIKE 'L%'); الخرج Query OK, 6 rows affected (0.01 sec) حذف البيانات من عدة جداول يمكنك حذف البيانات من أكثر من جدول في عملية واحدة عن طريق تضمين بنية JOIN. تُستخدم بنى JOIN لدمج السجلات من جدولين أو أكثر في نتيجة استعلام واحد. يتم ذلك عن طريق إيجاد عمود مشترك بين الجداول وفرز النتائج على نحوٍ مناسب في الخرج. تبدو صيغة عملية الحذف التي تتضمن بنية JOIN على النحو التالي: mysql> DELETE table_1, table_2 mysql> FROM table_1 JOIN table_2 mysql> ON table_2.related_column = table_1.related_column mysql> WHERE conditions_apply; لاحظ أنه نظرًا لقدرة صيغ الدمج JOIN على مقارنة البيانات من عدة جداول، فإن صيغة هذا المثال تُوضّح الجدول المُستهدف لكل عمود بوضع اسم الجدول متبوعًا بنقطة قبل اسم العمود، وهذا ما يُعرف بالإشارة الكاملة والمؤهلة للعمود. ويُمكنك تحديد الجدول المصدر لكل عمود بهذه الطريقة في أي عملية، على الرغم من عدم ضرورتها عند الاختيار من جدول واحد فقط كما فعلنا في الأمثلة السابقة. لتوضيح مفهوم حذف البيانات باستخدام بنية JOIN، لنفترض أن ناديك قرر تحديد العلامات التجارية للمعدات الموسيقية التي يمكن للأعضاء مشاركتها. نفّذ الأمر التالي لإنشاء جدول باسم prohibitedBrands حيث ستسرد العلامات التجارية التي لم تعد مقبولة في النادي. يحتوي هذا الجدول على عمودين فقط، كلاهما يستخدم نمط بيانات varchar، لتخزين اسم كل علامة تجارية والبلد الذي تعمل فيه: mysql> CREATE TABLE prohibitedBrands ( mysql> brandName varchar(30), mysql> homeCountry varchar(30) mysql> ); ثم املأ هذا الجدول الجديد ببعض البيانات النموذجية التجريبية: mysql> INSERT INTO prohibitedBrands mysql> VALUES mysql> ('Fandar', 'USA'), mysql> ('Givson', 'USA'), mysql> ('Muug', 'USA'), mysql> ('Peabey', 'USA'), mysql> ('Yemehe', 'Japan'); بعد ذلك، يقرر النادي حذف أي سجلات للمعدات من جدول clubEquipment التي تظهر علاماتها التجارية في جدول prohibitedBrands ومقرها في الولايات المتحدة. يمكنك الاستعلام عن هذه البيانات بتنفيذ عملية استعلام مثل التالية باستخدام SELECT. إذ تدمج هذه العملية جدولي clubEquipment وprohibitedBrands معًا، وتُرجع فقط السجلات التي تشترك فيها أعمدة brand وbrandName في نفس القيمة. وتعمل بنية WHERE على إتمام تحديد نتائج الاستعلام بإقصاء أي علامة تجارية لا تتضمن القيمة "USA" في عمود homeCountry: mysql> SELECT * mysql> FROM clubEquipment JOIN prohibitedBrands mysql> ON clubEquipment.brand = prohibitedBrands.brandName mysql> WHERE homeCountry = 'USA'; الخرج +-------------+---------------+--------+---------+-----------+-------------+ | equipmentID | equipmentType | brand | ownerID | brandName | homeCountry | +-------------+---------------+--------+---------+-----------+-------------+ | 6 | bass guitar | Fandar | 4 | Fandar | USA | | 17 | bass guitar | Peabey | 1 | Peabey | USA | +-------------+---------------+--------+---------+-----------+-------------+ 2 rows in set (0.00 sec) هذه هي كل المعلومات التي نبحث عنها؛ وهي كل علامة تجارية مقرها الولايات المتحدة والموجودة في جدول prohibitedBrands والتي تظهر أيضًا في جدول clubEquipment. لحذف هذه العلامات التجارية من جدول prohibitedBrands والمعدات المرتبطة بها من جدول clubEquipment، أعد كتابة استعلام SELECT السابق ولكن استبدل تعليمة SELECT * بتعليمة DELETE متبوعةً بأسماء كلا الجدولين: mysql> DELETE clubEquipment, prohibitedBrands mysql> FROM clubEquipment JOIN prohibitedBrands mysql> ON clubEquipment.brand = prohibitedBrands.brandName mysql> WHERE homeCountry = 'USA'; الخرج Query OK, 4 rows affected (0.01 sec) يشير هذا الخرج إلى أن العملية حذفت أربع سجلات من قاعدة البيانات: سجلين من جدول clubEquipment وسجلين من جدول prohibitedBrands. إذا كنت تريد حذف السجلات من جدول clubEquipment فقط والاحتفاظ بجميع السجلات في جدول prohibitedBrands، فعليك إدراج clubEquipment فقط بعد كلمة DELETE، والعكس صحيح. تغيير سلوك تعليمة DELETE للمفاتيح الخارجية ستفشل أي تعليمة DELETE قد تسبب تعارضًا مع قيد FOREIGN KEY افتراضيًا. بالعودة إلى فقرة الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية في مستلزمات العمل وبتذكّر أنّ العمود ownerID في جدول المعدات clubEquipment هو مفتاح خارجي يشير إلى عمود memberID في جدول الأعضاء clubMembers. فهذا يعني أنّ أي قيمة مُدخلة في عمود ownerID يجب أن تكون موجودة بالفعل في جدول memberID. إذا حاولت إزالة سجل من جدول clubMembers تُستخدم قيمة memberID المُخصصة له في مكان ما ضمن عمود ownerID من جدول clubEquipment، سيؤدي ذلك إلى ظهور خطأ. mysql> DELETE FROM clubMembers mysql> WHERE memberID = 6; الخرج ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails يمكنك تجنب هذا الخطأ بإزالة أي سجلات في الجدول الابن (clubEquipment في هذا المثال) حيث توجد قيمة المفتاح الخارجي في الجدول الأب (clubMembers). كبديل، يمكنك تغيير هذا السلوك بتعديل قيد المفتاح الخارجي القائم بآخر يعالج عمليات الحذف على نحوٍ مختلف. ملاحظة: لا تسمح كافة أنظمة إدارة قواعد البيانات العلاقية أو محركاتها بإضافة أو إزالة قيود من جدول قائم كما هو موضح في الفقرات اللاحقة. فإذا كنت تستخدم نظام RDBMS غير MySQL، يجب عليك مراجعة الوثائق الرسمية الخاصة به لفهم القيود المتعلقة بإدارة القيود. وبالعودة إلى موضوعنا، بذلك ستكون قادرًا على تحديث قيمة clientID لأي سجل في الجدول الأب clubMembers، وستنتقل هذه التغييرات بشكل تلقائي إلى أي سجلات في الجدول الابن clubEquipment المرتبطة به. لاستبدال القيد الحالي، يجب أولًا إزالته باستخدام تعليمة ALTER TABLE. تذكر أننا في تعليمة CREATE TABLE لجدول clubEquipment، قمنا بتحديد fk_ownerID كاسم لقيد المفتاح الخارجي للجدول. mysql> ALTER TABLE clubEquipment mysql> DROP FOREIGN KEY fk_ownerID; الخرج Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 بعد ذلك، أنشئ قيد مفتاح خارجي جديد مُعدّ ليتعامل مع عمليات الحذف DELETE بطريقة تتناسب مع حالة الاستخدام المعطاة. بصرف النظر عن الإعداد الافتراضي الذي يمنع تعليمات DELETE التي تخالف المفتاح الخارجي، هناك خياران آخران متاحان في معظم أنظمة إدارة قواعد البيانات العلاقية: ON DELETE SET NULL: يسمح لك هذا الخيار بحذف السجلات من الجدول الأب، وسيعيد تعيين أي قيم مرتبطة بها في الجدول الابن على أنها قيم فارغة NULL. ON DELETE CASCADE: عند حذف سجل في الجدول الأب، سيدفع هذا الخيار SQL لحذف أي سجلات في الجدول الابن مرتبطة بذلك السجل من الجدول الأب. في سياق هذا المثال، لا يُعد استخدام خيار ON DELETE SET NULL منطقيًا. فإذا غادر أحد الأعضاء النادي وحُذِف سجله من جدول clubMembers، فلن تكون معداته متاحة للأعضاء المتبقين بعد الآن وبالتالي يجب إزالتها من جدول clubEquipment. وفي هذا الصدد يُعدّ خيار ON DELETE CASCADE هو الأنسب لهذا السياق. لإضافة قيد FOREIGN KEY يعمل وفق آلية ON DELETE CASCADE، نفّذ أمر ALTER TABLE التالي لتعديل الجدول. ستنشئ هذه التعليمة قيدًا جديدًا باسم newfk_ownerID يعكس تعريف القيد السابق ولكن مع إضافة خيار ON DELETE CASCADE. mysql> ALTER TABLE clubEquipment mysql> ADD CONSTRAINT newfk_ownerID mysql> FOREIGN KEY (ownerID) mysql> REFERENCES clubMembers(memberID) mysql> ON DELETE CASCADE; الخرج Query OK, 7 rows affected (0.07 sec) Records: 7 Duplicates: 0 Warnings: 0 تشير هذه النتائج إلى أن العملية قد أثرت على جميع السجلات السبعة المتبقية في جدول clubEquipment. ملاحظة: بدلًا من تغيير تعريف جدول مُعرّف مسبقًا لتعديل كيفية تفاعل قيد المفتاح الخارجي مع عمليات DELETE، يُمكنك من البداية تحديد هذا السلوك عند إنشاء الجدول بواسطة تعليمة إنشاء الجدول CREATE TABLE ، وبذلك تُعيّن السلوك المطلوب مُسبقًا، على النحو التالي: mysql> CREATE TABLE clubEquipment ( mysql> equipmentID int PRIMARY KEY, mysql> equipmentType varchar(30), mysql> brand varchar(15), mysql> ownerID int, mysql> CONSTRAINT fk_ownerID mysql> FOREIGN KEY (ownerID) REFERENCES clubMembers(memberID) mysql> ON DELETE CASCADE mysql> ); عقب ذلك، ستكون قادرًا على حذف أي سجل من جدول clubMembers، وستُحذف جميع السجلات المرتبطة به في جدول clubEquipment تلقائيًا: mysql> DELETE FROM clubMembers mysql> WHERE memberID = 6; الخرج Query OK, 1 row affected (0.00 sec) رغم أن هذا الخرج يشير إلى تأثر سجل واحد فقط، إلا أنّ العملية قد حذفت أيضًا كافة سجلات المعدات في جدول clubEquipment ذات القيمة 6 في عمود ownerID. الخلاصة باطلاعك على هذا المقال، اكتسبت المعرفة حول كيفية حذف البيانات الموجودة في جدول واحد أو أكثر باستخدام تعليمة DELETE في SQL. كما تعرفت على كيفية تعامل SQL مع عمليات الحذف التي تتعارض مع قيود المفتاح الخارجي وطرق تغيير هذا السلوك الافتراضي. ومن المفترض أن تعمل الأوامر المشروحة في هذا المقال مع أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن تذكر أن لكل قاعدة بيانات SQL تقديمها الخاص للغة، لذا ينبغي مراجعة التوثيق الرسمي لنظام إدارة قواعد البيانات الخاص بك للحصول على وصف أكثر تفصيلاً لكيفية التعامل مع عمليات الحذف والخيارات المتاحة لها. وللمزيد حول SQL، نشجعك على متابعة المقالات المنشورة تحت وسم سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Delete Data in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية تحديث البيانات في لغة الاستعلام البنيوية SQL ما هي تقنية SQL تنظيم شيفرات SQL وتأمينها تصميم الجداول ومعلومات المخطط وترتيب تنفيذ الاستعلامات في SQL
  5. لدى التعامل مع قاعدة بيانات، قد تضطر أحيانًا لتعديل بيانات كانت مدرجة من قبل في جدول أو أكثر. كأن تُضطر مثلًا لتصحيح خطأ إملائي في إدخال معين أو إضافة معلومات جديدة إلى سجل غير مكتمل. وتوفّر لغة الاستعلام البنيوية المعروفة بـ SQL الكلمة المفتاحية UPDATE، التي تُمكّن المستخدمين من تعديل البيانات الموجودة في جدول ما. يشرح هذا المقال كيفية استعمال الصيغة UPDATE في SQL لتعديل البيانات في جدول واحد أو عدة جداول مرتبطة ببعضها. كما يتناول الطريقة التي تتعامل بها SQL مع عمليات UPDATE التي قد تتعارض مع قيود المفتاح الخارجي. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز حاسوب يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، ويمكنك إعداد الخادم بالاستعانة بمقالنا كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، ومُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات مع بعض الجداول المُحمّلة ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على تحديث بيانات SQL. وإذا لم تكن متوفرة لديك، يمكنك مراجعة مقال الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية الاتصال بخادم MySQL وإنشاء قاعدة البيانات التجريبية المُستخدمة في أمثلة هذا المقال. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو: $ ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p أنشئ قاعدة بيانات باسم updateDB: mysql> CREATE DATABASE updateDB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات updateDB، نفّذ تعليمة USE التالية: mysql> USE updateDB; الخرج Database changed وبعد اختيارك لقاعدة البيانات updateDB، أنشئ بعض الجداول ضمنها. ولتوضيح الأمثلة في هذا المقال، تخيّل أنّك تدير وكالة مواهب، وقد قررت تتبّع عملائك وأدائهم عبر قاعدة بيانات SQL، وبأنّك تعتزم البدء بجدولين: الجدول الأوّل لتخزين معلومات عن عملائك. وقد حددت أنّ هذا الجدول يحتاج إلى أربعة أعمدة: clientID: مُعرّف كل عميل، مُعبرًا عنه بنمط بيانات الأعداد الصحيحة int، كما سيُمثّل هذا العمود المفتاح الرئيسي للجدول، بحيث تمثل كل قيمة منه دور المُعرف الفريد للسجل المُرتبط بها. name: اسم كل عميل، مُعبرًا عنه بنمط بيانات varchar بحد أقصى 20 محرفًا. routine: وصف مُختصر لنوع الأداء الرئيسي لكل عميل، مُعبرًا عنه بنمط بيانات varchar بحد أقصى 30 محرفًا. performanceFee: عمود لتسجيل رسوم الأداء القياسية لكل عميل، يستخدم نمط البيانات decimal وتُحدد القيم في هذا العمود بحد أقصى قدره خمسة أرقام، بواقع رقمين على يمين الفاصلة العشرية. وبالتالي، تتراوح القيم المسموح بها من -999.99 إلى 999.99. أنشئ جدولًا باسم clients يشمل هذه الأعمدة الأربعة: mysql> CREATE TABLE clients mysql> (clientID int PRIMARY KEY, mysql> name varchar(20), mysql> routine varchar(30), mysql> standardFee decimal (5,2) mysql> ); أمّا الجدول الثاني فسيكون مخصصًا لتخزين بيانات حول أداء عملائك في مكان عرض محدد محليًا. وبفرض أنك ارتأيت بأنّ هذا الجدول يتطلّب خمسة أعمدة: showID: بمثابة عمود clientID، إذ سيحتفظ هذا العمود بمُعرّف فريد لكل عرض، مُعبرًا عنه بنمط بيانات الأعداد الصحيحة int. كما سيمُثّل هذا العمود المفتاح الرئيسي لجدول العروض shows. showDate: تاريخ كل عرض. يُعبر عن قيم هذا العمود باستخدام نمط بيانات التواريخ date الذي يستخدم الصيغة YYYY-MM-DD (خانتين لليوم وخانتين للشهر وأربع خانات للسنة). clientID: مُعرّف العميل الذي يؤدي في العرض، مُعبرًا عنه كعدد صحيح. attendance: عدد الحضور في كل عرض، مُعبرًا عنه كعدد صحيح. ticketPrice:سعر تذكرة الدخول لكل عرض. يستخدم هذا العمود نمط البيانات decimal وتُحدد القيم في هذا العمود بحد أقصى قدره خمسة أرقام، بواقع رقمين على يمين الفاصلة العشرية. وبالتالي، تتراوح القيم المسموح بها من- 999.99 إلى 999.99. ولضمان أنّ عمود clientID لن يتضمّن سوى قيم تُمثّل مُعرّفات عملاء صالحة، قررتَ تطبيق قيد مفتاح خارجي عليه بحيث يُشير إلى عمود clientID في جدول clients. يُعد قيد المفتاح الخارجي طريقة لتحديد علاقة بين جدولين، إذ يفرض أن تكون القيم في العمود المُطبّق عليه موجودة بالفعل في العمود المُشار إليه. في المثال القادم، يشترط قيد FOREIGN KEY أن تكون كل قيمة تُضاف إلى عمود clientID في جدول shows مُسجلة مسبقًا في عمود clientID بجدول clients. أنشئ جدولًا باسم clients يتضمن هذه الأعمدة الخمسة: mysql> CREATE TABLE shows mysql> (showID int PRIMARY KEY, mysql> showDate date, mysql> clientID int, mysql> attendance int, mysql> ticketPrice decimal (4,2), mysql> CONSTRAINT client_fk mysql> FOREIGN KEY (clientID) mysql> REFERENCES clients(clientID) mysql> ); ومن الجدير بالملاحظة أنّ هذا المثال يوفّر اسمًا لقيد المفتاح الخارجي، ألا وهو: client_fk. إذ تُنشئ MySQL تلقائيًا اسمًا لأي قيد تضيفه، إلّا أنّ تحديد اسم من قبلنا في هذه الحالة سيكون مفيدًا عندما نحتاج للإشارة إلى هذا القيد لاحقًا. بعد ذلك، نفّذ تعليمة INSERT INTO التالية لملء جدول العملاء clients بخمسة سجلات من البيانات النموذجية: mysql> INSERT INTO clients mysql> VALUES mysql> (1, 'Fares', 'song and dance', 180), mysql> (2, 'Camal', 'standup', 99.99), mysql> (3, 'Karam', 'standup', 45), mysql> (4, 'Wael', 'song and dance', 200), mysql> (5, 'Ahmad', 'trained squirrel', 79.99); ثم نفّذ تعليمة INSERT INTO أخرى لملء جدول shows بعشرة سجلات من البيانات النموذجية: mysql> INSERT INTO shows mysql> VALUES mysql> (1, '2019-12-25', 4, 124, 15), mysql> (2, '2020-01-11', 5, 84, 29.50), mysql> (3, '2020-01-17', 3, 170, 12.99), mysql> (4, '2020-01-31', 5, 234, 14.99), mysql> (5, '2020-02-08', 1, 86, 25), mysql> (6, '2020-02-14', 3, 102, 39.5), mysql> (7, '2020-02-15', 2, 101, 26.50), mysql> (8, '2020-02-27', 2, 186, 19.99), mysql> (9, '2020-03-06', 4, 202, 30), mysql> (10, '2020-03-07', 5, 250, 8.99); وبذلك، غدوتَ جاهزًا لمتابعة باقي المقال وبدء تعلم كيفية تحديث البيانات باستخدام لغة الاستعلام البنيوية SQL. تحديث البيانات في جدول واحد تبدو الصيغة العامّة لتعليمة UPDATE على النحو: mysql> UPDATE table_name mysql> SET column_name = value_expression mysql> WHERE conditions_apply; تُتبع الكلمة المفتاحية UPDATE باسم الجدول الذي يحتوي على البيانات المُراد تحديثها. ثم تأتي بنية SET، والتي تُحدّد بيانات العمود المُراد تحديثها وكيفية التحديث. تُعدّ بنية SET وكأنها تعيين لقيم العمود المُحدد لتُصبح مطابقة لأي تعبير قيمة تُقدّمه. يُعرّف تعبير القيمة — الذي يُعرف أحيانًا بالتعبير ذو القيمة المفردة — بأنّه أي تعبير يُعيد قيمة واحدة لكل سجل يُراد تحديثه. يمكن أن تكون القيمة المُعادة عبارة عن سلسلة نصية مجردة، أو عملية رياضية تُجرى على قيم رقمية موجودة في العمود. ولا بُدّ من تضمين عملية إسناد لقيمة واحدة على الأقل في كل تعليمة UPDATE، كما يُمكنك تضمين أكثر من تعليمة واحدة بغية تحديث البيانات في عدة أعمدة. تُتبع بنية SET ببنية WHERE. فإضافة بنية WHERE إلى تعليمة UPDATE كما في صيغة المثال هذه يُمكنّك من تصفية أي سجلات لا ترغب في تحديثها. إنّ بنية WHERE اختيارية تمامًا في تعليمات UPDATE، ولكن إذا لم تُضمنها، ستُحدّث العملية كل سجل في الجدول. لتوضيح كيفية تعامل SQL مع عمليات التحديث UPDATE، ابدأ بالاطلاع على كافة البيانات في جدول العملاء clients. يشتمل الاستعلام التالي على علامة النجمة (*)، وهي اختصار في SQL يُمثّل كل عمود في الجدول، لذا سيُعيد هذا الاستعلام جميع البيانات من كل عمود في جدول clients. $ SELECT * FROM clients; الخرج +----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Fares | song and dance | 180.00 | | 2 | Camal | standup | 99.99 | | 3 | Karam | standup | 45.00 | | 4 | Wael | song and dance | 200.00 | | 5 | Ahmad | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec) لنفترض على سبيل المثال أنّك لاحظت وجود خطأ في تهجئة الاسم Kamal، إذ يجب أن يبدأ بحرف K ولكنه في الجدول يبدأ بحرف C، ولذا قررت تغيير هذه القيمة عبر تنفيذ تعليمة UPDATE التالية. هذه العملية تُحدّث القيم في عمود الاسم name عن طريق تغيير قيمة عمود الاسم name في أي سجل يحتوي على الاسم Camal لتصبح Kamal: mysql> UPDATE clients mysql> SET name = 'Kamal' mysql> WHERE name = 'Camal'; الخرج Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 يُظهر هذا الخرج أن سجلًا واحدًا فقط قد حُدّث. يمكنك التأكد من ذلك بتشغيل استعلام SELECT السابق مجددًا، على النحو: $ SELECT * FROM clients; الخرج +----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Fares | song and dance | 180.00 | | 2 | Kamal | standup | 99.99 | | 3 | Karam | standup | 45.00 | | 4 | Wael | song and dance | 200.00 | | 5 | Ahmad | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec) تُظهر هذه النتائج أن القيمة المُدخلة سابقًا على أنّها Camal قد عُدلت الآن إلى Kamal. لقد حُدثّت قيمة واحدة فقط في عمود الاسم name في هذا المثال. ولكن، يمكنك تحديث عدة قيم باستخدام بنية WHERE أشمل. لإيضاح هذه الفكرة، بفرض أنّك تفاوضت على أجور أداء موحدة لجميع عملائك الذين يؤدون فقرات محددة. ستُحدّث التعليمة التالية القيم في عمود standardFee وتعينها لتكون 140. يرجى ملاحظة أن بنية WHERE في هذا المثال تتضمن المعامل LIKE، لذا فهي تُحدّث قيمة performanceFee لكل عميل تُطابق قيمة routine له النمط المحدد بالمحرف البديل 's%'. بمعنى آخر، سيُحدّث أجر الأداء لأي مؤدي يبدأ نوع عرضه بالحرف "s": mysql> UPDATE clients mysql> SET standardFee = 140 mysql> WHERE routine LIKE 's%'; الخرج Query OK, 4 rows affected (0.00 sec) Rows matched: 4 Changed: 4 Warnings: 0 والآن إذا استعلمت مجددًا عن محتويات جدول العملاء clients، فستؤكد مجموعة النتائج أن أربعة من عملائك غدا لديهم الآن رسوم أداء متطابقة: $ SELECT * FROM clients; الخرج +----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Fares | song and dance | 140.00 | | 2 | Kamal | standup | 140.00 | | 3 | Karam | standup | 140.00 | | 4 | Wael | song and dance | 140.00 | | 5 | Ahmad | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec) في حالة وجود أعمدة بالجدول تحمل قيمًا رقمية، فيُمكن تحديثها بتنفيذ عملية حسابية ضمن بنية SET. لتوضيح الأمر، بفرض أنّك توصلّت لاتفاق على زيادة رسوم الأداء لكل عميل بنسبة أربعين بالمئة، ولتطبيق هذا التغيير على جدول العملاء clients، يمكن تنفيذ عملية UPDATE كالآتي: mysql> UPDATE clients mysql> SET standardFee = standardFee * 1.4; الخرج Query OK, 5 rows affected, 1 warning (0.00 sec) Rows matched: 5 Changed: 5 Warnings: 1 ملاحظة: لاحظ أن الخرج يشير إلى أنّ التحديث قد نتج عنه تحذير. ففي كثير من الأحيان، تُصدر MySQL تحذيرًا عندما تُجبر على إجراء تغيير على بياناتك يتعارض والخصائص أو المحددات القياسية لعمود أو جدول معين. وتوفّر MySQL الاختصار SHOW WARNINGS الذي قد يساعد في شرح أي تحذيرات تتلقاها: mysql> SHOW WARNINGS; الخرج +-------+------+--------------------------------------------------+ | Level | Code | Message | +-------+------+--------------------------------------------------+ | Note | 1265 | Data truncated for column 'standardFee' at row 5 | +-------+------+--------------------------------------------------+ 1 row in set (0.00 sec) يُخبرنا هذا الخرج بأن نظام قاعدة البيانات أصدر التحذير لأنه اضطر إلى اقتطاع إحدى قيم العمود standardFee الجديدة حتى تتوافق مع تنسيق الرقم العشري - خمسة أرقام مع وجود رقمين على يمين الفاصلة العشرية - المُعرّف مسبقًا. لنستعلم عن جدول العملاء clients مجددًا للتأكد من أن رسوم الأداء لكل من العملاء قد ارتفعت بنسبة أربعين بالمئة بالفعل. $ SELECT * FROM clients; الخرج +----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Fares | song and dance | 196.00 | | 2 | Kamal | standup | 196.00 | | 3 | Karam | standup | 196.00 | | 4 | Wael | song and dance | 196.00 | | 5 | Ahmad | trained squirrel | 111.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec) كما ذكرنا سابقًا، يمكنك أيضًا تحديث البيانات في عدة أعمدة دفعة واحدة باستخدام تعليمة UPDATE واحدة. للقيام بذلك، يجب تحديد كل عمود ترغب في تحديثه، متبوعًا بالتعبير الخاص بالقيمة المراد تعيينها، ثم تفصل بين كل زوج من اسم عمود وتعبير قيمة بعلامة فاصلة. على سبيل المثال، بفرض أنّك اكتشفت بأنّ القاعة التي يقدم فيها عملاؤك عروضهم قد أخطأت في الإبلاغ عن عدد الحضور لجميع عروض Karam و Wand. وبالصدفة، تبين أيضًا أنك قمت بإدخال أسعار تذاكر خاطئة لكل من عروضهما. قبل الشروع في تحديث البيانات في جدول العروض shows، نفّذ الاستعلام التالي لاسترجاع كافة البيانات الحالية المُخزنة به حاليًا: $ SELECT * FROM shows; الخرج +--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 124 | 15.00 | | 2 | 2020-01-11 | 5 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 170 | 12.99 | | 4 | 2020-01-31 | 5 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 25.00 | | 6 | 2020-02-14 | 3 | 102 | 39.50 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 202 | 30.00 | | 10 | 2020-03-07 | 5 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.01 sec) ولتصحيح أعداد الحضور والأسعار لتعبّر عن تلك الفعلية، سنحدّث الجدول لإضافة عشرين حاضرًا إلى كل عرض لهما وزيادة قيم سعر التذكرة ticketPrice لكل عرض بنسبة خمسين في المئة. يمكنك القيام بذلك من خلال عملية على النحو: mysql> UPDATE shows mysql> SET attendance = attendance + 20, mysql> ticketPrice = ticketPrice * 1.5 mysql> WHERE clientID IN mysql> (SELECT clientID mysql> FROM clients mysql> WHERE name = 'Karam' OR name = 'Wael'); الخرج Query OK, 4 rows affected, 1 warning (0.00 sec) Rows matched: 4 Changed: 4 Warnings: 1 لاحظ أن هذا المثال يستخدم استعلامًا فرعيًا في بنية WHERE لإرجاع قيم clientID لكل من Karam و Wael من جدول العملاء clients. وغالبًا ما يكون من الصعب تذكر القيم المجردة من قبيل أرقام التعريف، إلّا أنّ هذه الطريقة التي تستخدم فيها استعلامًا فرعيًا للعثور على قيمة يمكن أن تكون مفيدة في حال معرفتك لبعض السمات فقط حول السجلات المعنية. بعد تحديث جدول العروض shows، لنستعلم عنه مجددًا للتأكد من أن التغييرات قد تمّت كما هو متوقع: $ SELECT * FROM shows; الخرج +--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 144 | 22.50 | | 2 | 2020-01-11 | 5 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 190 | 19.49 | | 4 | 2020-01-31 | 5 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 25.00 | | 6 | 2020-02-14 | 3 | 122 | 59.25 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 222 | 45.00 | | 10 | 2020-03-07 | 5 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.00 sec) يشير هذا الخرج إلى أن تعليمة UPDATE قد اكتملت بنجاح. استخدام بنية JOIN لتحديث البيانات في جداول متعددة ركّز هذا المقال حتى الآن على عرض طرق تحديث البيانات في جدول واحد فقط في كل مرة. ولكن، تُتيح بعض الإصدارات من SQL إمكانية تحديث أعمدة متعددة في جداول متعددة من خلال دمج الجداول مؤقتًا باستخدام بنية JOIN. فيما يلي الصيغة العامة التي بإمكانك استخدامها لتحديث عدة جداول دفعة واحدة مستخدمًا بنية JOIN: mysql> UPDATE table_1 JOIN table_2 mysql> ON table_1.related_column = table_2.related_column mysql> SET table_1.column_name = value_expression, mysql> table_2.column_name = value_expression mysql> WHERE conditions_apply; تبدأ صيغة هذا المثال بالكلمة المفتاحية UPDATE متبوعة بأسماء جدولين، يفصل بينهما صيغة JOIN. يلي ذلك صيغة ON، التي توضّح كيف ينبغي للاستعلام أن يدمج الجدولين معًا. في معظم تقديمات SQL، يمكنك دمج الجداول عن طريق إيجاد تطابقات ما بين أي مجموعة من الأعمدة تحتوي على ما يُعرف في معيار SQL باسم "أنواع البيانات المؤهلة للدمج" (JOIN eligible). بمعنى آخر، يُمكن بشكل عام دمج أي عمود يحتوي على بيانات عددية مع أي عمود آخر يحتوي على بيانات عددية، بغض النظر عن أنماط البيانات المحددة لكل منهما. وبالمثل، يمكن دمج أي أعمدة تحتوي على قيم محرفية مع أي عمود آخر يحتوي على بيانات محرفية. لاحظ أنه نظرًا لقدرة بنى JOIN على مقارنة البيانات من عدة جداول، فإن صيغة هذا المثال تُوضّح الجدول المُستهدف لكل عمود بوضع اسم الجدول متبوعًا بنقطة قبل اسم العمود، وهذا ما يُعرف بالإشارة الكاملة والمؤهلة للعمود. يُمكنك تحديد الجدول المصدر لكل عمود بهذه الطريقة في أي عملية، وهي غالبًا ما تُستخدم لزيادة الوضوح عند العمل مع أكثر من جدول. لتوضيح كيفية تنفيذ ذلك باستخدام جداول clients وshows المُنشأة مسبقًا، نفذ تعليمة UPDATE التالية. ما سيدمج جدولي clients وshows بناءً على أعمدة clientID المتطابقة في كلا الجدولين، ومن ثم تحديث قيم routine وticketPrice لسجل Fares في جدول clients وكل عروضها المدرجة في جدول shows. mysql> UPDATE clients JOIN shows mysql> USING (clientID) mysql> SET clients.routine = 'mime', mysql> shows.ticketPrice = 30 mysql> WHERE name = 'Fares'; الخرج Query OK, 2 rows affected (0.01 sec) Rows matched: 2 Changed: 2 Warnings: 0 لاحظ أنّ هذا المثال يدمج الجداول باستخدام الكلمة المفتاحية USING بدلاً من ON المُستخدمة في صيغة المثال السابق. وهذا ممكن لأنّ كل من الجدولين لديهما عمود clientID يتشاركان فيه نفس نوع البيانات. لمزيد من التفاصيل حول عمليات الدمج باستخدام JOIN، ننصحك بقراءة المقال التالي كيفية استخدام عمليات الدمج في SQL. تغيير سلوك تعليمة UPDATE للمفاتيح الخارجية ستفشل أي تعليمة UPDATE قد تسبب تعارضًا مع قيد FOREIGN KEY افتراضيًا. بالعودة إلى فقرة الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية في مستلزمات العمل وبتذكّر أنّ العمود clientID في جدول العروض shows هو مفتاح خارجي يشير إلى عمود clientID في جدول العملاء clients. فهذا يعني أنّ أي قيمة مُدخلة في عمود clientID الخاص بجدول العروض يجب أن تكون موجودة بالفعل في جدول العملاء. فإذا حاولت تحديث قيمة clientID لسجل ما في جدول العملاء والتي تظهر أيضًا في عمود clientID لجدول العروض، فسيؤدي ذلك إلى حدوث خطأ: mysql> UPDATE clients mysql> SET clientID = 9 mysql> WHERE name = 'Ahmad'; الخرج ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails يمكنك تجنب هذا الخطأ بتغيير قيد المفتاح الخارجي الحالي بآخر يتعامل مع عمليات التحديث على نحوٍ مختلف. ملاحظة: لا تسمح كافة أنظمة إدارة قواعد البيانات العلاقية أو محركات قواعد البيانات بإضافة أو إزالة قيد من جدول موجود بالفعل كما هو موضح في الفقرات التالية. فإذا كنت تستخدم نظام RDBMS غير MySQL، يجب عليك الرجوع إلى الوثائق الرسمية الخاصة به لفهم القيود الموجودة بخصوص إدارة القيود. بالعودة إلى موضوعنا، ولاستبدال القيد الحالي، عليك بدايةً إزالته باستخدام تعليمة ALTER TABLE. تذكّر أننا في تعليمة CREATE TABLE الخاصة بجدول العروض shows، حددنا client_fk كاسم لقيد المفتاح الخارجي FOREIGN KEY للجدول: mysql> ALTER TABLE shows mysql> DROP FOREIGN KEY client_fk; الخرج Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 بعد ذلك، أنشئ قيد مفتاح خارجي جديد مُعدّ ليتعامل مع عمليات التحديث UPDATE بطريقة تتناسب مع الحالة الاستخدامية المعطاة. بصرف النظر عن الإعداد الافتراضي الذي يمنع تعليمات UPDATE التي تخالف المفتاح الخارجي، هناك خياران آخران متاحان في معظم أنظمة إدارة قواعد البيانات العلاقية: ON UPDATE SET NULL: يسمح لك هذا الخيار بتحديث السجلات من الجدول الأب، وسيعيد تعيين أي قيم مرتبطة بها في الجدول الابن على أنها قيم فارغة NULL. ON UPDATE CASCADE: عند تحديث سجل في الجدول الأب، سيدفع هذا الخيار SQL لتحديث أي سجلات في الجدول الابن مرتبطة بذلك السجل من الجدول الأب لتتماشى مع القيمة الجديدة المُحدّثة. في سياق هذا المثال، لا يُعد استخدام خيار ON UPDATE SET NULL منطقيًا، فلو غيّرت مُعرّف لأحد العملاء دون حذفه من جدول clients، ينبغي أن يبقى مرتبطًا بعروضه في الجدول shows. ويجب أن يظهر المُعرّف الجديد ضمن سجلات عروضه، وبالتالي يكون استخدام الخيار ON UPDATE CASCADE هو الأنسب لهذا السياق. لإضافة قيد FOREIGN KEY يعمل وفق آلية ON UPDATE CASCADE، نفّذ أمر ALTER TABLE التالي. ستنشئ هذه التعليمة قيد جديد باسم new_client_fk يعكس تعريف القيد السابق ولكن مع إضافة خيار ON UPDATE CASCADE. mysql> ALTER TABLE shows mysql> ADD CONSTRAINT new_client_fk mysql> FOREIGN KEY (clientID) mysql> REFERENCES clients (clientID) mysql> ON UPDATE CASCADE; الخرج Query OK, 10 rows affected (0.02 sec) Records: 10 Duplicates: 0 Warnings: 0 تشير هذه النتائج إلى أن العملية قد أثرت على جميع السجلات العشرة وقامت بتعديلها في جدول العروض shows. ملاحظة: بدلًا من تغيير تعريف جدول مُعرّف مسبقًا لتعديل كيفية تفاعل قيد المفتاح الخارجي مع عمليات UPDATE، يُمكنك من البداية تحديد هذا السلوك عند إنشاء الجدول بواسطة تعليمة CREATE TABLE، وبذلك تُعيّن السلوك المطلوب مُسبقًا. mysql> CREATE TABLE shows mysql> (showID int PRIMARY KEY, mysql> showDate date, mysql> clientID int, mysql> attendance int, mysql> ticketPrice decimal (4,2), mysql> CONSTRAINT client_fk mysql> FOREIGN KEY (clientID) mysql> REFERENCES clients(clientID) mysql> ON UPDATE CASCADE mysql> ); عقب ذلك، ستكون قادرًا على تحديث قيمة clientID لأي سجل في جدول clients، وستنتقل هذه التغييرات بشكل تلقائي إلى جميع السجلات المرتبطة بها في جدول shows. mysql> UPDATE clients mysql> SET clientID = 9 mysql> WHERE name = 'Ahmad'; الخرج Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 رغم أن هذا الخرج يشير إلى تأثر سجل واحد فقط، إلا أنّ العملية قد حدّثت في الواقع قيمة clientID لكل سجلات جدول العروض المرتبطة بـ Ahmad في جدول shows. وللتحقق من ذلك، نفّذ الاستعلام التالي لاسترجاع كافة البيانات من الجدول shows: $ SELECT * FROM shows; الخرج +--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 144 | 22.50 | | 2 | 2020-01-11 | 9 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 190 | 19.49 | | 4 | 2020-01-31 | 9 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 30.00 | | 6 | 2020-02-14 | 3 | 122 | 59.25 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 222 | 45.00 | | 10 | 2020-03-07 | 9 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.00 sec) كما هو متوقع، تسبب التحديث الذي أُجري على عمود clientID في جدول clients في تحديث السجلات المرتبطة في جدول shows. الخلاصة بوصولك إلى نهاية هذا المقال، ستكون قد اكتسبت المعرفة حول كيفية تعديل السجلات الموجودة في جدول واحد أو أكثر باستخدام تعليمة UPDATE في SQL. كما تعرفت على كيفية تعامل SQL مع عمليات التحديث التي تتعارض مع قيود المفتاح الخارجي وطرق تغيير هذا السلوك الافتراضي. ومن المفترض أن تعمل الأوامر المشروحة في هذا المقال مع أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن تذكر أن لكل قاعدة بيانات SQL تقديمها الخاص للغة، لذا ينبغي مراجعة التوثيق الرسمي لنظام إدارة قواعد البيانات الخاص بك للحصول على وصف أكثر تفصيلاً لكيفية التعامل مع عمليات التحديث والخيارات المتاحة لها. وللمزيد حول SQL، نشجعك على متابعة المقالات المنشورة تحت وسم سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Update Data in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية إدراج البيانات في SQL المرجع المتقدم إلى لغة SQL تصميم الجداول ومعلومات المخطط وترتيب تنفيذ الاستعلامات في SQL حذف الجداول وقواعد البيانات في SQL أهمية قواعد البيانات
  6. تُقدّم لغة الاستعلامات البنيوية SQL، مرونةً هائلةً من حيث الطرق الممكنة لإدراج البيانات في الجداول. فعلى سبيل المثال، يمكنك تحديد سجلات بيانات فردية باستخدام الكلمة المفتاحية VALUES، أو نسخ مجموعات كاملة من البيانات من الجداول الحالية باستخدام الاستعلامات SELECT. كما يمكن تعريف الأعمدة بأساليب تسمح للغة SQL بإدراج البيانات فيها تلقائيًا. في هذا المقال، سنستعرض كيفية استخدام الصيغة INSERT INTO في SQL لإضافة البيانات إلى الجداول وفق كل من هذه الأساليب. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز حاسوب يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقيَّة RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، كما هو موضح في مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. نظام إدارة قواعد البيانات MySQL مثبت على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في سياق المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقيَّة تستخدم تقديمات فريدة خاصة بها للغة SQL. فعلى الرغم من أن الأوامر المُوضحة في هذا المقال ستعمل على نحوٍ سليم في معظم هذه الأنظمة، ولكن قد تختلف الصياغة الدقيقة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات يمكنك استخدامها للتدرّب على إدراج البيانات. إذا لم تكن لديك قاعدة بيانات للتجربة، اطلع على فقرة الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية** التالي للحصول على تفاصيل حول كيفية إنشائها. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم بعيد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو التالي: $ mysql -u user -p ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p أنشئ قاعدة بيانات باسم insertDB: mysql> CREATE DATABASE insertDB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات insertDB، نفّذ تعليمة USE التالية: mysql> USE insertDB; الخرج Database changed بعد اختيار قاعدة البيانات insertDB، أنشئ جدولًا داخلها. فعلى سبيل المثال، بفرض لديك مصنع وترغب في إنشاء جدول لتخزين بعض المعلومات عن موظفيك. سيحتوي هذا الجدول على الأعمدة الخمسة التالية: name: اسم كل موظف، ويُعبّر عنه باستخدام نمط البيانات varchar مع حد أقصى للطول قدره 30 محرفًا. position: يخزن هذا العمود الموقع الوظيفي لكل موظف، ويُعبّر عنه أيضًا باستخدام نمط البيانات varchar مع حد أقصى للطول قدره 30 محرفًا. department: يمثل القسم الذي يعمل فيه كل موظف، ويُعبّر عنه باستخدام نمط البيانات varchar ولكن بحد أقصى للطول قدره 20 محرفًا فقط. hourlyWage: عمود لتسجيل أجر كل موظف بالساعة، ويستخدم نمط البيانات decimal، إذ تقتصر أي قيم في هذا العمود على حد أقصى قدره أربعة أرقام، مع وجود رقمين من هذه الأرقام على يمين الفاصلة العشرية. وبالتالي، تتراوح القيم المسموح بها في هذا العمود من ‎-99.99 إلى 99.99. startDate: تاريخ تعيين كل موظف، ويُعبّر عنه باستخدام نمط البيانات date. ويجب أن تتوافق القيم من هذا النوع مع التنسيق YYYY-MM-DD. أنشئ جدولًا باسم factoryEmployees يحتوي على هذه الأعمدة الخمسة، على النحو: mysql> CREATE TABLE factoryEmployees ( mysql> name varchar(30), mysql> position varchar(30), mysql> department varchar(20), mysql> hourlyWage decimal(4,2), mysql> startDate date mysql> ); وبهذا، أصبحت جاهزًا لمتابعة الخطوات في المقال وبدء التعلم حول كيفية إدراج البيانات باستخدام SQL. إدراج البيانات يدويًا تبدو الصيغة العامة لإدراج البيانات في SQL كالتالي: mysql> INSERT INTO table_name mysql> (column1, column2, . . . columnN) mysql> VALUES mysql> (value1, value2, . . . valueN); للتوضيح، نفّذ الأمر INSERT INTO التالي لتحميل جدول factoryEmployees مع سجل واحد من البيانات: mysql> INSERT INTO factoryEmployees mysql> (name, position, department, hourlyWage, startDate) mysql> VALUES mysql> ('Agnes', 'thingamajig foreman', 'management', 26.50, '2017-05-01'); الخرج Query OK, 1 row affected (0.00 sec) يبدأ هذا الأمر بالكلمات المفتاحية INSERT INTO، يليها اسم الجدول الذي ترغب في إدراج البيانات فيه. وبعد اسم الجدول، تأتي قائمة بأسماء الأعمدة التي ستضيف البيانات إليها والتي تكون محصورة ضمن أقواس هلالية. وبعد قائمة الأعمدة، تأتي الكلمة المفتاحية VALUES، ومن ثم مجموعة من القيم محاطة بأقواس هلالية ومفصولة برموز فاصلة. الترتيب الذي تُدرج فيه الأعمدة ليس بالأمر المُلزم، ولكن من الأساسي ضمان تطابق ترتيب القيم مع ترتيب الأعمدة المُدرجة. إذ ستُدرج SQL القيمة الأولى في العمود الأول المُحدد، والقيمة الثانية في العمود الثاني، وهكذا. وللتوضيح لاحظ أن الأمر INSERT في المثال التالي سيضيف سجلًا جديدًا من البيانات، ولكن بترتيب مختلف للأعمدة: mysql> INSERT INTO factoryEmployees mysql> (department, hourlyWage, startDate, name, position) mysql> VALUES mysql> ('production', 15.59, '2018-04-28', 'Jim', 'widget tightener'); الخرج Query OK, 1 row affected (0.00 sec) إذا لم تتطابق القيم على نحوٍ صحيح مع ترتيب الأعمدة، قد تُدرج SQL البيانات في الأعمدة الخاطئة. ناهيك عن إمكانية حدوث خطأ في حال تعارضت أي من القيم مع نوع البيانات المحدد للعمود، كما في المثال التالي: mysql> INSERT INTO factoryEmployees mysql> (name, hourlyWage, position, startDate, department) mysql> VALUES mysql> ('Louise', 'doodad tester', 16.50, '2017-05-01', 'quality assurance'); الخرج ERROR 1366 (HY000): Incorrect decimal value: 'doodad tester' for column 'hourlyWage' at row 1 وعلى الرغم من ضرورة توفير قيمة لكل عمود تحدده، ولكن بالمقابل ليس من الضروري تحديد كل عمود في الجدول عند إضافة سجل جديد من البيانات. ففي حال عدم وجود قيود على الأعمدة التي تتجاهلها (كالقيد NOT NULL)، ستضع MySQL القيمة الفارغة NULL في الأعمدة غير المُحددة. mysql> INSERT INTO factoryEmployees mysql> (name, position, hourlyWage) mysql> VALUES mysql> ('Harry', 'whatzit engineer', 26.50); الخرج Query OK, 1 row affected (0.01 sec) فإذا كنت تخطط لإدخال سجل يتضمّن قيمًا لكل عمود في الجدول، فليس من الضروري تضمين أسماء الأعمدة على الإطلاق. ومع ذلك، عليك التأكد من أن القيم المُدخلة تتوافق مع الترتيب الذي عُرّفت الأعمدة وفقًا له لدى تعريف الجدول. في هذا المثال، تتوافق القيم المدرجة مع الترتيب الذي عُرّفت الأعمدة وفقًا له في تعليمة CREATE TABLE الخاصة بالجدول factoryEmployee: mysql> INSERT INTO factoryEmployees mysql> VALUES mysql> ('Marie', 'doodad welder', 'production', 27.88, '2018-03-29'); الخرج Query OK, 1 row affected (0.00 sec) كما يمكنك إضافة سجلات متعددة في وقت واحد عبر فصل كل سجل بعلامة فاصلة، كما في المثال التالي: mysql> INSERT INTO factoryEmployees mysql> VALUES mysql> ('Giles', 'gizmo inspector', 'quality assurance', 26.50, '2019-08-06'), mysql> ('Daphne', 'gizmo presser', 'production', 32.45, '2017-11-12'), mysql> ('Joan', 'whatzit analyst', 'quality assurance', 29.00, '2017-04-29'); الخرج Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 نسخ البيانات باستخدام تعليمات SELECT يمكنك نسخ سجلات البيانات المتعددة من جدول ما وإدراجها في جدول آخر باستخدام استعلام SELECT بدلًا من تحديد البيانات سجلًا تلو الآخر. تبدو صيغة هذه العملية كالتالي: mysql> INSERT INTO table_A (col_A1, col_A2, col_A3) mysql> SELECT col_B1, col_B2, col_B3 mysql> FROM table_B; فبدلًا من إلحاق قائمة الأعمدة بالكلمة المفتاحية VALUES، ألحقنا الصيغة ضمن هذا المثال بتعليمة SELECT. إذ تشمل تعليمة SELECT في هذه الصيغة بنية FROM فقط، ولكن يمكن لأي استعلام صالح أن يعمل هنا على نحوٍ صحيح. لتوضيح ذلك، نفّذ العملية CREATE TABLE التالية لإنشاء جدول جديد باسم showroomEmployees. لاحظ أن أعمدة هذا الجدول لها نفس الأسماء وأنماط البيانات كما في ثلاثة أعمدة من الجدول factoryEmployees المُستخدم في القسم السابق: mysql> CREATE TABLE showroomEmployees ( mysql> name varchar(30), mysql> hourlyWage decimal(4,2), mysql> startDate date mysql> ); الخرج Query OK, 0 rows affected (0.02 sec) الآن يمكنك ملء هذا الجدول الجديد ببعض البيانات من الجدول factoryEmployees المُنشأ سابقًا عن طريق إضافة استعلام SELECT ضمن تعليمة INSERT INTO. إذا أعاد استعلام SELECT نفس عدد الأعمدة وبنفس الترتيب كما في أعمدة الجدول الهدف، وكان لها أيضًا نفس أنماط البيانات، فيمكنك حينها تجاهل قائمة الأعمدة في تعليمة INSERT INTO، على النحو: mysql> INSERT INTO showroomEmployees mysql> SELECT mysql> factoryEmployees.name, mysql> factoryEmployees.hourlyWage, mysql> factoryEmployees.startDate mysql> FROM factoryEmployees mysql> WHERE name = 'Agnes'; الخرج Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 ملاحظة: كل من الأعمدة المدرجة في الاستعلام SELECT الخاص بالعملية أعلاه مسبوقة باسم الجدول factoryEmployees متبوعًا برمز النقطة. وعندما نُحدد اسم جدول بهذه الطريقة عند الإشارة إلى عمود، فيُطلق عليها مصطلح الإشارة الكاملة للعمود fully qualified column reference. الأمر غير الضروري في هذه الحالة الخاصة في المثال أعلاه. ففي الواقع، ستعطي التعليمة INSERT INTO في الأمثلة التالية نفس النتيجة كالتعليمة السابقة: mysql> INSERT INTO showroomEmployees mysql> SELECT mysql> name, mysql> hourlyWage, mysql> startDate mysql> FROM factoryEmployees mysql> WHERE name = 'Agnes'; وقد استخدمنا في الأمثلة ضمن هذا القسم طريقة الإشارة الكاملة للعمود من باب التوضيح، ولكن من المستحسن استخدامها دائمًا. فهي لا تساعد في جعل لغة الاستعلام SQL أكثر وضوحًا فحسب، ولكنها تغدو كضرورة في العمليات التي تتضمن الإشارة إلى أكثر من جدول، كالاستعلامات التي تحتوي على بنية الدمج JOIN. تشمل تعليمة الاستعلام SELECT في هذه العملية البنية WHERE، وبوجودها سيُعيد الاستعلام من الجدول factoryEmployees السجلات التي تحتوي على القيمة Agnes في العمود name فقط. وبما أن هناك سجلًا واحدًا فقط في الجدول المصدر موافق لهذه القيمة، فينسخ هذا السجل فقط إلى الجدول showroomEmployees. لتأكيد ذلك، نفّذ الاستعلام التالي لاسترجاع جميع السجلات في جدول showroomEmployees: mysql> SELECT * FROM showroomEmployees; الخرج +-------+------------+------------+ | name | hourlyWage | startDate | +-------+------------+------------+ | Agnes | 26.50 | 2017-05-01 | +-------+------------+------------+ 1 row in set (0.00 sec) يمكنك إدراج عدة سجلات من البيانات باستخدام أي استعلام يُعيد أكثر من سجل من الجدول المصدر. فعلى سبيل المثال، سيُعيد الاستعلام في التعليمة التالية جميع سجلات قاعدة البيانات factoryEmployees التي لا تبدأ قيمها ضمن العمود name بالحرف J: mysql> INSERT INTO showroomEmployees mysql> SELECT mysql> factoryEmployees.name, mysql> factoryEmployees.hourlyWage, mysql> factoryEmployees.startDate mysql> FROM factoryEmployees mysql> WHERE name NOT LIKE 'J%'; الخرج Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 نفّذ هذا الاستعلام مجددًا لاسترجاع جميع السجلات في الجدول showroomEmployees: mysql> SELECT * FROM showroomEmployees; +--------+------------+------------+ | name | hourlyWage | startDate | +--------+------------+------------+ | Agnes | 26.50 | 2017-05-01 | | Agnes | 26.50 | 2017-05-01 | | Harry | 26.50 | NULL | | Marie | 27.88 | 2018-03-29 | | Giles | 26.50 | 2019-08-06 | | Daphne | 32.45 | 2017-11-12 | +--------+------------+------------+ 6 rows in set (0.00 sec) نلاحظ وجود سجلين متطابقين يحملان القيمة Agnes في العمود name. فعند تنفيذ تعليمة INSERT INTO التي تستخدم الاستعلام SELECT, تُعامل SQL نتيجة الاستعلام هذا كمجموعة جديدة من البيانات. فبدون فرض قيود محددة على الجدول أو الاعتماد على استعلامات أدق وأكثر تحديدًا، لن يكون هناك ما يمنع وجود تكرار في السجلات عند إضافة البيانات بهذه الطريقة. إدراج البيانات تلقائيًا يمكن تطبيق بعض السمات على الأعمدة لدى إنشاء جدول، والتي تجعل نظام إدارة قواعد البيانات العلاقيّ يملؤها بالبيانات تلقائيًا. للتوضيح، نفّذ التعليمة التالية لتعريف جدول باسم interns. إذ ستُنشئ هذه العملية جدولًا باسم interns يحتوي على ثلاثة أعمدة. العمود الأول في هذا المثال، وهو internID، يحتوي على بيانات من النمط int. ولكن لاحظ أنه يشمل أيضًا سمة AUTO_INCREMENT. هذه السمة ستجعل SQL تُنشئ قيمة رقمية فريدة تلقائيًا لكل سجل جديد، تبدأ افتراضيًا بالرقم 1 وتزداد تلقائيًا بخطوة مقدارها واحد مع كل سجل تالي. وبالمثل، يشمل تعريف العمود الثاني الذي يُدعى department الكلمة المفتاحية DEFAULT. ما سيجعل نظام إدارة قواعد البيانات العلاقيّ يدرج القيمة الافتراضية – وهي الكلمة 'production' في مثالنا - تلقائيًا وذلك في حال حذف العمود department من قائمة الأعمدة ضمن تعليمة INSERT INTO، على النحو التالي: mysql> CREATE TABLE interns ( mysql> internID int AUTO_INCREMENT PRIMARY KEY, mysql> department varchar(20) DEFAULT 'production', mysql> name varchar(30) mysql> ); ملاحظة: تعدّ السمة AUTO_INCREMENT ميزة خاصة بنظام إدارة قواعد البيانات MySQL، ولكن العديد من أنظمة إدارة قواعد البيانات العلاقيّة لديها طريقتها الخاصة لتحقيق التزايد في الأرقام الصحيحة. وللحصول على فهم أفضل حول كيفية تعامل نظام إدارة قواعد البيانات العلاقي مع مسألة الزيادة التلقائية، يُفضل الرجوع إلى التوثيق الرسمي الخاص بهذا النظام. وإليك التوثيق الرسمي بخصوص هذا الموضوع لبعض قواعد البيانات المفتوحة المصدر الشهيرة: توثيق سمة AUTO_INCREMENT لـ MySQL توثيق نمط البيانات serial لـ PostgreSQL توثيق الكلمة المفتاحية Autoincrement لـ SQLite. ولتوضيح هذه الميزات، لنحمّل الجدول interns ببعض البيانات، وذلك بتنفيذ تعليمة INSERT INTO التالية. إذ تُحدّد هذه العملية القيم للعمود name فقط: mysql> INSERT INTO interns (name) VALUES ('Pierre'), ('Sheila'), ('Francois'); الخرج Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 ومن ثمّ شغّل هذا الاستعلام ليعيد كافّة السجلات من الجدول: mysql> SELECT * FROM interns; الخرج +----------+------------+----------+ | internID | department | name | +----------+------------+----------+ | 1 | production | Pierre | | 2 | production | Sheila | | 3 | production | Francois | +----------+------------+----------+ 3 rows in set (0.00 sec) يُظهر هذا الخرج أنّه وبسبب تعريفات الأعمدة فإنّ التعليمة INSERT INTO السابقة أضافت قيمًا إلى العمودين internID وdepartment، على الرغم من عدم تحديدهما. لإضافة قيمة مختلفة عن تلك الافتراضية لعمود department، يجب تحديد ذلك العمود ضمن تعليمة INSERT INTO، كالتالي: mysql> INSERT INTO interns (name, department) mysql> VALUES mysql> ('Jacques', 'management'), mysql> ('Max', 'quality assurance'), mysql> ('Edith', 'management'), mysql> ('Daniel', DEFAULT); الخرج Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 لاحظ أن السجل الأخير من القيم المُقدمة في هذا المثال يشتمل على الكلمة المفتاحية DEFAULT بدلًا من قيمة نصية. سيؤدي ذلك إلى جعل قاعدة البيانات تدرج القيمة الافتراضية ('production'). mysql> SELECT * FROM interns; الخرج +----------+-------------------+----------+ | internID | department | name | +----------+-------------------+----------+ | 1 | production | Pierre | | 2 | production | Sheila | | 3 | production | Francois | | 4 | management | Jacques | | 5 | quality assurance | Max | | 6 | management | Edith | | 7 | production | Daniel | +----------+-------------------+----------+ 7 rows in set (0.00 sec) الخلاصة تعرفت في هذا المقال على العديد من طرق إدراج البيانات في الجداول، بما في ذلك تحديد سجلات البيانات على نحوٍ فرديّ باستخدام الكلمة المفتاحية VALUES، ونسخ مجموعات كاملة من البيانات باستخدام استعلامات SELECT، وتعريف الأعمدة التي ستُدرج فيها SQL البيانات تلقائيًا. ومن الجدير بالذكر أن الأوامر التي شرحناها هنا يجب أن تعمل على أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن عليك مراعاة أن كل قاعدة بيانات SQL تستخدم تقديمًا فريدًا للّغة، لذلك يُفضّل الرجوع إلى التوثيقات الرسمية لنظام إدارة قواعد البيانات الخاص بك للحصول على توصيف أدق لكيفية التعامل مع تعليمة INSERT INTO والخيارات المتاحة لها. للمزيد حول كيفية التعامل مع SQL، ننصحك بالاطلاع على سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Use Constraints in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية استخدام القيود في SQL جلب الاستعلامات عبر SELECT في SQL التعامل مع البيانات (الإدخال، الحذف والتعديل) في SQL مدخل إلى SQL تحديث الجداول في SQL
  7. عند تصميم قاعدة بيانات باستخدام SQL، قد تُضطر أحيانًا إلى فرض قيود على نمط البيانات التي يمكن إضافتها إلى أعمدة معينة ضمن جدول. إذ توفّر لك SQL هذه الإمكانية من خلال ما يُعرف بالقيود constraints. فبمجرد تطبيق قيد على عمود أو جدول، ستفشل أي محاولة لإضافة بيانات لا تتوافق مع هذا القيد. ولعلّ لكل نظام من أنظمة قواعد البيانات التي تستخدم SQL طريقته الخاصة في التعامل مع القيود. يهدف هذا المقال إلى تقديم نظرة عامة حول الصيغة المُتبعة في العديد من أنظمة إدارة قواعد البيانات للتعامل مع القيود، مع التركيز على MySQL كمثال رئيسي في هذا الإطار. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز حاسوب يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العِلاقيَّة RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، كما هو موضح في مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. MySQL مثبتة ومؤمنة على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقيَّة تستخدم تقديمات فريدة خاصة بها للغة SQL. فعلى الرغم من أن الأوامر المُوضحة في هذا المقال ستعمل على نحوٍ سليم في معظم هذه الأنظمة، ولكن قد تختلف الصياغة الدقيقة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، فمن المفيد أيضًا أن يكون لديك فهم عام حول قيود SQL وكيفية عملها. وللحصول على نظرة عامة حول هذا المفهوم، يمكنك الرجوع إلى مقال فهم قيود SQL. كما ستحتاج إلى قاعدة بيانات يمكنك استخدامها للتدرّب على إنشاء الجداول مع القيود. إذا لم تكن لديك قاعدة بيانات للتجربة، اطلع على القسم إعداد قاعدة بيانات تجريبية نموذجية والاتصال بها التالي للحصول على تفاصيل حول كيفية إنشائها. إعداد قاعدة بيانات تجريبية نموذجية والاتصال بها إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم عن بُعد، اتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو: $ ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p أنشئ قاعدة بيانات باسم constraintsDB: mysql> CREATE DATABASE constraintsDB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات constraintsDB، نفّذ تعليمة USE التالية: mysql> USE constraintsDB; الخرج Database changed وبذلك تغدو جاهزًا للخوض في الخطوات التالية من مقالنا هذا لتنطلق في تعلّم كيفية إنشاء وإدارة الجداول في SQL. إنشاء الجداول مع القيود عادةً ما تُعرّف القيود أثناء إنشاء الجدول. فمثلًا تُنشئ الصيغة التالية لتعليمة CREATE TABLE جدولًا باسم employeeInfo (معلومات الموظفين) يحتوي على ثلاثة أعمدة: empId (لتخزين مُعرّف الموظف) وempName (لتخزين اسم الموظف) و empPhoneNum (لتخزين رقم هاتف الموظف). كما تُطبّق هذه التعليمة أيضًا القيد UNIQUE على العمود empId. ما سيمنع وجود أي قيم متطابقة فيه: mysql> CREATE TABLE employeeInfo ( mysql> empId int UNIQUE, mysql> empName varchar(30), mysql> empPhoneNum int mysql> ); تُعرّف هذه التعليمة القيد UNIQUE مباشرةً بعد العمود empId، ما يعني أن القيد ينطبق فقط على هذا العمود. فإذا حاولت إضافة أي بيانات إلى هذا الجدول، سيراقب نظام إدارة قواعد البيانات المحتوى الحالي للعمود empId للتأكد من أنّ القيم الجديدة التي تضيفها إليه فريدة بالفعل. وهذا ما يُسمّى بالقيد على مستوى العمود. كما من الممكن تطبيق القيد خارج تعريفات العمود. ففي المثال التالي، نُنشئ جدولًا باسم racersInfo (معلومات المتسابقين) يحتوي على ثلاثة أعمدة: racerId (لتخزين مُعرّف المتسابق) وracerName (لتخزين اسم المتسابق) وfinish (لتخزين ترتيب إنهاء المتسابق للسباق). وأسفل تعريفات الأعمدة، نُطبّق القيد CHECK على العمود finish لضمان أن ترتيب كل متسابق أكبر من أو يساوي 1 (إذ لا يمكن أن يكون ترتيب أي متسابق أقل من المركز الأول): mysql> CREATE TABLE racersInfo ( mysql> racerId int, mysql> finish int, mysql> racerName varchar(30), mysql> CHECK (finish > 0) mysql> ); ونظرًا لتطبيق القيد خارج تعريف أي من الأعمدة الفردية، فيتعين عليك تحديد اسم الأعمدة التي ترغب بتطبيق القيد عليها بين قوسين هلاليين. دائمًا في حال تحديد قيد خارج تعريفات الأعمدة الفردية، نُسمّي هذا القيد بقيد على مستوى الجدول. فالقيود على مستوى العمود تنطبق فقط على الأعمدة الفردية، في حين قد تُطبّق قيود الجدول على عدة أعمدة. تسمية القيود عندما تحدد قيدًا، يولد نظام إدارة قواعد البيانات العِلاقيَّة اسمًا له تلقائيًا. يُستخدم هذا الاسم للإشارة إلى القيد في رسائل الخطأ وفي الأوامر المستخدمة لإدارة القيود. قد يكون من المريح لمدراء قواعد البيانات في بعض الأحيان توفير اسماء خاصة للقيود. فعادةً لا تكون أسماء القيود المُنشأة تلقائيًا وصفية، لذلك قد يساعد توفير الاسم بنفسك في تذكر الغرض من القيد. لتسمية قيد، ضع الكلمة المفتاحية CONSTRAINT متبوعة بالاسم الذي تختاره وذلك قبل نوع القيد. فمثلًا تعيد التعليمات التالية إنشاء جدول racersInfo مع تسميته newRacersInfo وإضافة الاسم noNegativeFinish للقيد CHECK: mysql> CREATE TABLE newRacersInfo ( mysql> racerId int, mysql> finish int, mysql> racerName varchar(30), mysql> CONSTRAINT noNegativeFinish mysql> CHECK (finish >= 1) mysql> ); ملاحظة: إذا لم تُحدّد اسمًا للقيد، أو حددته ونسيته لاحقًا، فمن المحتمل أن تعثر عليه بالرجوع إلى تخطيطات معلومات قاعدة البيانات information schemas لنظام إدارة قواعد البيانات الخاص بك. إذ توفّر العديد من أنظمة قواعد البيانات الحديثة وعملاؤها اختصارًا لعرض تعليمات CREATE الداخلية والتي تشير إلى اسم القيد. وفيما يلي روابط التوثيقات الرسمية لهذه الاختصارات لكل من MySQL وPostgreSQL: MySQL: تتضمّن MySQL التعليمة SHOW CREATE TABLE، والتي تعيد كامل تعليمة CREATE TABLE التي أنشأت الجدول المطوب، على النحو: mysql> SHOW CREATE TABLE table_name; PostgreSQL: يتضمن عميل PostgreSQL المُسمّى psql على العديد من الخيارات التي يمكنك استخدامها للكشف عن معلومات حول جدول معين. فالخيار d\ مثلًا يعيد بياناتٍ وصفية حول الجدول المطلوب: Postgres=# \d table_name إدارة القيود يمكنك إضافة القيود إلى الجداول الموجودة أصلًا في MySQL أو حذفها باستخدام أوامر ALTER TABLE. على سبيل المثال، الأمر التالي يضيف قيد UNIQUE إلى العمود empName في الجدول employeeInfo المُنشأ مسبقًا: mysql> ALTER TABLE employeeInfo ADD UNIQUE (empName); عند إضافة قيد إلى جدول موجود، يمكنك أيضًا استخدام الكلمة المفتاحية CONSTRAINT لتوفير اسم لتعريف القيد. فالأمر في المثال التالي يضيف قيد UNIQUE باسم uID إلى العمود racerId من الجدول racersInfo المُنشأ مسبقًا: mysql> ALTER TABLE racersInfo ADD CONSTRAINT uID UNIQUE (racerId); وستفشل التعليمة ALTER TABLE إذا أدخلت أي سجلات قد تنتهك شرط القيد الجديد قبل إضافته وفق هذه الطريقة. لحذف قيد، استخدم الصيغة DROP CONSTRAINT، متبوعة باسم القيد الذي ترغب في حذفه. فمثلًا الأمر التالي سيحذف القيد uID المُنشأ في الأمر السابق: mysql> ALTER TABLE racersInfo DROP CONSTRAINT uID; الخلاصة تعلمت في هذا المقال كيفية إضافة وحذف القيود للأعمدة والجداول باستخدام SQL. ومن الجدير بالذكر أن الأوامر التي شرحناها هنا يجب أن تعمل على أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن عليك مراعاة أن كل قاعدة بيانات SQL تستخدم تقديمًا فريدًا للّغة، لذلك يُفضّل الرجوع إلى التوثيقات الرسمية لنظام إدارة قواعد البيانات الخاص بك للحصول على توصيف أدق لكل أمر والخيارات المتاحة. للمزيد حول كيفية التعامل مع SQL، ننصحك بالاطلاع على سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Use Constraints in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: كيفية إنشاء وإدارة الجداول في SQL نظرة سريعة على لغة الاستعلامات الهيكلية SQL مدخل إلى أهم الاستعلامات (queries) في MySQL مدخل إلى برنامج إدارة قواعد البيانات MySQL
  8. الجداول هي الهياكل التنظيمية الأساسية في قواعد بيانات SQL. وهي تتكون من عدد من الأعمدة التي تعكس السمات الفردية لكل صف أو سجل في الجدول. ولعلّ من المهم لكل من يعمل مع قواعد البيانات العلاقية أن يفهم كيفية إنشاء وتغيير وحذف الجداول حسب الحاجة كونها جزءًا أساسيًا من آلية تنظيم البيانات. سنتناول في هذا المقال كيفية إنشاء الجداول في SQL، بالإضافة إلى كيفية تعديل وحذف الجداول الموجودة أصلًا في قاعدة البيانات. مستلزمات العمل لمتابعة الخطوات في هذا المقال، ستحتاج إلى جهاز كمبيوتر يُشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية RDBMS التي تستخدم SQL. وقد اختبرنا الأوامر البرمجية والأمثلة في هذا المقال مستخدمين البيئة التالية: خادم عامل على توزيعة أوبنتو، مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر، وجدار حماية مكوّن باستخدام UFW، كما هو موضح في مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة. نظام إدارة قواعد البيانات MySQL مثبت على الخادم، كما هو موضح في المقال كيفية تثبيت MySQL على أوبونتو. وقد نفذنا خطوات هذا المقال باستخدام مستخدم MySQL مختلف عن المستخدم الجذر، مُنشأ وفق الطريقة الموضحة في الخطوة 3 من هذا المقال. ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية لها تقديماتها الفريدة من لغة SQL. فبالرغم من كون الأوامر المُقدمة في هذا المقال ستعمل مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات الطفيفة في الصيغة أو الناتج عند تنفيذها على أنظمة مختلفة عن MySQL. وبالعودة إلى مستلزمات العمل، ستحتاج أيضًا إلى قاعدة بيانات وجدول مُحمّل ببعض البيانات التجريبية النموذجية لتتمكن من التدرب على استخدام محارف البدل. وإذا لم تكن متوفرة لديك، يمكنك مراجعة الفقرة التالية الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية للمزيد من التفاصيل حول كيفية إعداد قاعدة بيانات وجدول لاستخدامهما في الأمثلة خلال هذا المقال. الاتصال بـ MySQL وإعداد قاعدة بيانات تجريبية نموذجية إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم بعيد، فاتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي على النحو التالي: $ ssh user@your_server_ip ثم افتح واجهة سطر الأوامر في خادم MySQL، مُستبدلًا user باسم حساب مستخدم MySQL الخاص بك: $ mysql -u user -p الآن أنشئ قاعدة بيانات باسم tablesDB: mysql> CREATE DATABASE tablesDB; وبمجرّد إنشاء قاعدة البيانات بنجاح ستحصل على خرجٍ كالتالي: الخرج Query OK, 1 row affected (0.01 sec) ولاختيار قاعدة البيانات tablesDB، نفّذ تعليمة USE التالية: mysql> USE tablesDB; الخرج Database changed وبذلك تغدو جاهزًا لتجربة الخطوات التالية من مقالنا هذا لتنطلق في تعلّم كيفية إنشاء وإدارة الجداول في SQL. إنشاء الجداول لإنشاء جدول في SQL، استخدم الأمر CREATE TABLE متبوعًا بالاسم الذي ترغب بتسمية الجدول به: mysql> CREATE TABLE table_name; وكما هو الحال مع كل تعليمات SQL، انتبه إلى وجوب انتهاء تعليمات CREATE TABLE برمز الفاصلة المنقوطة ;. تُنشئ الصيغة في المثال السابق جدولًا فارغًا بدون أي أعمدة. أمّا لإنشاء جدول يتضمّن أعمدة محددة، فيجب أن نُتبع اسم الجدول بقائمة تتضمن أسماء الأعمدة وأنماط البيانات الموافقة لكل منها والقيود المتعلقة بها، محصورةً بين أقواس هلالية ومفصولة برمز الفاصلة، على النحو التالي: mysql> CREATE TABLE table_name ( mysql> column1_name column1_data_type, mysql> column2_name column2_data_type, mysql> . . . mysql> columnN_name columnN_data_type mysql> ); كمثال، لنفترض أنك ترغب بإنشاء جدول لتسجيل بعض المعلومات حول المنتزهات التي تفضلها في مدينة نيويورك. فبعد اتخاذ قرار بشأن السمات التي تود تسجيلها حول كل منتزه، ستحدّد أسماء الأعمدة لكل من تلك السمات وكذلك نمط البيانات المناسب لكل منها: parkName: اسم كل منتزه. ونظرًا لوجود تباين واسع في أطوال أسماء المنتزهات، سيكون استخدام نمط البيانات varchar بطول أعظمي يبلغ 30 محرفًا مناسبًا. yearBuilt: السنة التي بُني فيها المنتزه. على الرغم من أنّ MySQL تتضمّن نمط بيانات يُسمّى year (لتخزين السنوات الميلادية)، إلّا أنّه يسمح فقط بقيم تتراوح بين 1901 و 2155. ولأن هناك عدة منتزهات في مدينة نيويورك بُنيت قبل عام 1901، لذلك من الأفضل استخدام نمط بيانات الأعداد الصحيحة int كبديل. firstVisit: تاريخ أول زيارة لك لكل منتزه. تتضمّن MySQL نمط بيانات date لتخزين التواريخ، ومن المناسب استخدامه لهذا العمود، إذ يُخزّن البيانات بالتنسيق YYYY-MM-DD (اليوم بخانتين-الشهر بخانتين-السنة بأربع خانات). lastVisit: تاريخ زيارتك الأخيرة لكل منتزه. ويمكنك هنا استخدام نمط البيانات date مجددًا. ولإنشاء جدول باسم faveParks يحتوي على أعمدة بهذه الأسماء وأنماط البيانات، نفّذ الأمر التالي: mysql> CREATE TABLE faveParks ( mysql> parkName varchar(30), mysql> yearBuilt int, mysql> firstVisit date, mysql> lastVisit date mysql> ); الخرج Query OK, 0 rows affected (0.01 sec) ومن الجدير بالملاحظة أن الأمر أعلاه يُنشئ هيكلية الجدول فقط، إذ أنّك لم تُضف أي بيانات إلى الجدول بعد. كما يمكنك إنشاء جداول جديدة استنادًا إلى جداول موجودة أصلًا باستخدام الصيغة CREATE TABLE AS على النحو التالي: mysql> CREATE TABLE new_table_name AS ( mysql> SELECT column1, column2, . . . columnN mysql> FROM old_table_name mysql> ); فبدلًا من إلحاق اسم الجدول الجديد (new_table_name) بقائمة من أسماء الأعمدة وأنماط البيانات الموافقة، نُتبعه بتعليمه AS ومن ثم تعليمة SELECT بين قوسين هلاليين والتي تُرجع الأعمدة والبيانات التي نرغب في نسخها من الجدول الأصلي (old_table_name) إلى الجدول الجديد. ومن الجدير بالملاحظة أنّه إذا كانت أعمدة الجدول الأصلي تتضمّن أي بيانات، فسيتم نسخ تلك البيانات إلى الجدول الجديد أيضًا. وللتوضيح، تشمل صيغة المثال أعلاه استعلام باستخدام SELECT والذي يحتوي فقط على بنية FROM المطلوبة. ولكن أي تعليمة صحيحة من تعليمات SELECT ستعمل على نحوٍ سليم في هذا المكان. ولمزيد من التوضيح، يُنشئ الأمر التالي جدولًا باسم parkInfo من خلال استخدام عمودين من الجدول faveParks المُنشأ سابقًا: mysql> CREATE TABLE parkInfo AS ( mysql> SELECT parkName, yearBuilt mysql> FROM faveParks mysql> ); الخرج Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 فإذا كان الجدول faveParks يحتوي على أي بيانات، فستنسخ البيانات الموجودة في أعمدة parkName وyearBuilt إلى جدول parkInfo أيضًا. ولكن في حالتنا، كلا الجدولين سيكون فارغًا. أمّا إذا حاولت إنشاء جدول مُستخدمًا اسم جدول موجود مُسبقًا من خلال التعليمات التالية: mysql> CREATE TABLE parkInfo ( mysql> name varchar(30), mysql> squareFootage int, mysql> designer varchar(30) mysql> ); الخرج ERROR 1050 (42S01): Table 'parkInfo' already exists فسيؤدي ذلك إلى وقوع خطأ يشير إلى أنّ الاسم parkinfo موجود أصلًا. ولتجنب هذا الخطأ، يمكنك إضافة الخيار IF NOT EXISTS ضمن أمر CREATE TABLE الخاص بك. إذ سيُخبر هذا الخيار قاعدة البيانات بالتحقق من وجود جدول موجود مسبقًا بنفس الاسم المحدد، ففي حال كان موجودًا، سيظهر تحذير بدلًا من رسالة الخطأ. mysql> CREATE TABLE IF NOT EXISTS parkInfo ( mysql> name varchar(30), mysql> squareFootage int, mysql> designer varchar(30) mysql> ); الخرج Query OK, 0 rows affected, 1 warning (0.00 sec) سيفشل هذا الأمر في إنشاء جدول جديد، إذ أنّ الجدول بالاسم parkInfo ما زال موجودًا أصلًا. ولكن نلاحظ أن الخرج يشير إلى كون تعليمة CREATE TABLE أدت إلى ظهور تحذير. ولعرض رسالة التحذير، نفّذ الأمر التشخيصي SHOW WARNINGS كالتالي: mysql> SHOW WARNINGS; الخرج | Level | Code | Message | +-------+------+---------------------------------+ | Note | 1050 | Table 'parkInfo' already exists | +-------+------+---------------------------------+ 1 row in set (0.00 sec) وكما يشير هذا الخرج، فقد سُجّل نفس الخطأ الذي تلقيته سابقًا على أنه تحذير، ذلك لأنك قد ضمّنت الخيار IF NOT EXISTS. وهذا الأمر قد يكون مفيدًا في بعض الحالات، كما هو الحال عند تنفيذ المعاملات Transactions التي تمثل سلسلة من عمليات SQL تُجرى على قاعدة بيانات وتعامل كما لو كانت عملية واحدة، بحيث إما أن تُنفَّذ جميعها أو لا تنفذ بأكملها، في حين يشير التحذير إلى فشل التعليمة الذي تسببت به فقط. تعديل الجداول قد تضطر في بعض الحالات إلى تغيير تعريف جدول معين وهذا الأمر مختلف عن تحديث البيانات ضمن الجدول فهو يعني تغيير هيكلية الجدول نفسه. وللقيام بذلك، يمكنك استخدام الصيغة ALTER TABLE على النحو التالي: mysql> ALTER TABLE table_name ALTER_OPTION sub_options . . . ; وبعد تضمين تعليمة ALTER TABLE، حدّد اسم الجدول الذي تود تعديله. ومن ثم مرّر الخيارات المتاحة بناءً على نظام إدارة قواعد البيانات الخاص بك لإجراء التعديل المطلوب. على سبيل المثال، قد ترغب في تغيير اسم الجدول أو إضافة عمود جديد أو حذف عمود قديم أو تغيير تعريف أحد الأعمدة. لنطبق بعض الأمثلة على جدول المنتزهات المُفضّلة faveParks الذي أنشأناه سابقًا في قسم إنشاء الجداول لمزيد من التدريب على كتابة تعليمات التعامل مع الجداول. لتغيير اسم الجدول faveParks، يمكنك استخدام صيغة RENAME TO. يغير المثال التالي اسم جدول faveParks إلى faveNYCParks: تحذير: كن حذرًا عند تغيير اسم جدول. فالقيام بذلك قد يسبب مشكلات في حال كان هناك تطبيق يستخدم الجدول أو إذا كانت هناك جداول أخرى في قاعدة البيانات تشير إليه. mysql> ALTER TABLE faveParks RENAME TO faveNYCParks; الخرج Query OK, 0 rows affected (0.01 sec) لإضافة عمود جديد للجدول، استخدم الخيار ADD COLUMN. يضيف المثال التالي عمود بالاسم borough، والذي يُخزّن بيانات من النمط varchar، ولكن بطول أقصى يبلغ 20 محرفًا إلى الجدول faveNYCParks: mysql> ALTER TABLE faveNYCParks ADD COLUMN borough varchar(20); الخرج Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 لحذف عمود من جدول مع أي بيانات يحتوي عليها، يمكنك استخدام الصيغة DROP TABLE. يحذف الأمر في المثال التالي العمود borough: mysql> ALTER TABLE faveNYCParks DROP COLUMN borough; تسمح العديد من تقديمات SQL بتغيير تعريف العمود باستخدام الصيغة ALTER TABLE. ويستخدم المثال التالي بنية MODIFY COLUMN في MySQL، إذ يقوم بتغيير العمود yearBuilt لاستخدام بيانات من النمط smallint بدلًا من النمط int الأصلي: mysql> ALTER TABLE faveNYCParks MODIFY COLUMN yearBuilt smallint; ومما يجب أخذه في الحسبان أنّ كل نظام إدارة قواعد بيانات يتضمّن خيارات مختلفة بخصوص ما يمكنك تغييره باستخدام تعليمة ALTER TABLE. ولتحقيق فهمٍ كامل حول ما يمكنك تنفيذه باستخدام ALTER TABLE, راجع التوثيق الرسمي لنظام إدارة قواعد البيانات الذي تستخدمه لمعرفة الخيارات المتاحة للتعليمة. إليك التوثيق الرسمي حول هذا الموضوع لبعضٍ من أشهر قواعد البيانات مفتوحة المصدر: توثيق ALTER TABLE في MySQL توثيق ALTER TABLE في PostgreSQL توثيق ALTER TABLE في SQLite حذف الجداول لحذف جدول وجميع البيانات الموجودة فيه، استخدم الصيغة DROP TABLE: تحذير: كن حذرًا عند تنفيذ الأمر DROP TABLE، إذ سيقوم بحذف الجدول وجميع بياناته نهائيًا. mysql> DROP TABLE table_name; كما يمكنك حذف عدة جداول باستخدام تعليمة DROP واحدة وذلك بفصل أسماء الجداول برمز فاصلة ومحرف مسافة، كما في المثال التالي: mysql> DROP TABLE table1, table2, table3; للتوضيح، سيحذف الأمر التالي كل من جدولي faveNYCParks و parkInfo المُنشأين سابقًا في هذا المقال: mysql> DROP TABLE IF EXISTS faveNYCParks, parkInfo; لاحظ أن هذا المثال يتضمن الخيار IF EXISTS، والذي يؤدي الوظيفة المعاكسة لخيار IF NOT EXISTS المتاح لأمر إنشاء الجداول CREATE TABLE. إذ سيجعل خيار IF EXISTS تعليمة DROP TABLE تعيد تحذيرًا بدلًا من رسالة خطأ في حال لم يكن أحد الجداول المُحدّدة موجودًا. الخلاصة تعلمت في هذا المقال كيفية إنشاء وتغيير وحذف الجداول في قواعد البيانات المبنية على SQL. ومن الجدير بالذكر أن الأوامر التي شرحناها هنا يجب أن تعمل على أي نظام لإدارة قواعد البيانات يستخدم SQL. لكن عليك مراعاة أن كل قاعدة بيانات SQL تستخدم تقديمًا فريدًا للّغة، لذلك يُفضّل الرجوع إلى التوثيقات الرسمية لنظام إدارة قواعد البيانات الخاص بك للحصول على توصيف أدق لكل أمر والخيارات المتاحة. للمزيد حول كيفية التعامل مع SQL، ننصحك بالاطلاع على سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Create and Manage Tables in SQL لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: فهم قيود SQL المرجع المتقدم إلى لغة SQL تصميم الجداول ومعلومات المخطط وترتيب تنفيذ الاستعلامات في SQL حذف الجداول وقواعد البيانات في SQL أهمية قواعد البيانات
  9. لدى تصميمك لقاعدة بيانات، قد تحتاج أحيانًا إلى وضع قيود على البيانات المسموح إدخالها ضمن أعمدة معينة في هذه القاعدة. على سبيل المثال، إذا كنت تنوي تصميم جدول لتخزين معلومات حول ناطحات سحاب، فلا بدّ من أنك سترغب في منع إدخال قيم سالبة في العمود الخاص بارتفاع كل مبنى. تُمكنّك أنظمة إدارة قواعد البيانات العلاقية RDBMSs من التحكّم بالبيانات التي يُسمح بإضافتها إلى الجدول من خلال ما يُسمّى بالقيود constraints. والقيد عبارة عن قاعدة خاصة تُفرض على عمود واحد أو أكثر، أو حتى على الجدول كاملًا، وتحدد هذه القاعدة التغييرات المتاح إجراؤها على بيانات الجدول، سواء كان هذا التغيير من هو أمر إدراج بيانات جديدة INSERT، أو تحديث بيانات موجوة UPDATE، أو حذف بيانات معينة DELETE. سنعرض في هذا المقال مفهوم القيود وكيفية استخدامها في أنظمة RDBMS بالتفصيل، كما سنستعرض القيود الخمسة المُعرفّة في معايير SQL ونشرح الوظيفة الأساسية لكل منها. ما هي القيود؟ القيد constraint في SQL هو أي قاعدة تُطبق على عمود أو جدول بهدف تحديد طبيعة البيانات التي يمكن إدخالها فيه. فعند كل محاولة لإجراء عملية من شأنها تغيير البيانات الموجودة في جدول – من خلال أمر إدراج INSERT أو تحديث UPDATE أو حذف DELETE للبيانات مثلًا – ستتحقق نظم إدارة قواعد البيانات العلاقية فيما إذا كانت هذه البيانات تخالف أي من القيود الموجودة أم لا، وستعيد خطأ إذا كانت تخالفها بالفعل أو ستنفذها في حال كانت تحقق المعايير المطلوبة. يعتمد مسؤولو قواعد البيانات على القيود لضمان اتباع قاعدة البيانات لمجموعة مُحددة من قواعد وتوجيهات العمل، وفي إطار قواعد البيانات، تُعرّف القاعدة بأنها أي سياسة أو إجراء تتبعه الشركة أو أي منظمة أخرى لتحدد من خلالها كيفية تخزين البيانات في قاعدة البيانات، إذ يجب أن تتوافق بياناتها مع هذه القواعد تمامًا. على سبيل المثال، إذا كنت تعمل على تطوير قاعدة بيانات لرصد مخزون متجر لأحد العملاء وطلب منك هذا العميل التأكد من وجود رقم تعريف فريد لكل سجل (منتج)، فبإمكانك وضع القيد UNIQUE (المُعبّر عن كون كل سجل في العمود المعني فريد) على العمود المُخصص للرقم التعريفي لضمان عدم وجود أي تكرار في القيم المدخلة لأرقام المنتجات المختلفة. تلعب القيود دورًا مهمًا في الحفاظ على دقة وصحة البيانات أو ما يعرف بسلامة البيانات data integrity. إذ يُشير مصطلح سلامة البيانات إلى مدى دقة واتساق ومنطقية البيانات المحفوظة في قاعدة البيانات وفقًا لسياق استخدامها. فغالبًا ما تكون الجداول ضمن قاعدة البيانات مرتبطة ببعضها البعض، فقد تعتمد بعض الأعمدة في جدول معين على القيم الموجودة في جدول آخر. ونظرًا لأن الأخطاء البشرية واردة الحدوث أثناء إدخال البيانات، فإن وضع القيود أمر أساسي في مثل هذه الحالات، إذ أنها تضمن عدم تأثير البيانات المُدخلة على نحوٍ خاطئ على هذه العلاقات بما قد يؤثّر سلبًا بالنتيجة على سلامة البيانات. بفرض أنك تُصمّم قاعدة بيانات تتضمّن جدولين: الأول لإدراج الطلاب الحاليين في مدرسة ما، والثاني لإدراج أعضاء فريق كرة السلة في تلك المدرسة. يمكنك في هذه الحالة تطبيق قيد FOREIGN KEY (قيد المفتاح الخارجي) على أحد أعمدة جدول فريق كرة السلة ليشير إلى أحد أعمدة جدول الطلاب. وهذا ما سينشئ علاقة بين الجدولين، إذ يتطلب أي إدخال جديد في جدول الفريق أن يشير إلى إدخال موجود بالفعل في جدول الطلاب. ولدى تصميم جدول في قاعدة البيانات، يمكن للمستخدمين تحديد القيود أثناء إنشاء هذا الجدول أو إضافتها لاحقًا باستخدام إحدى تعليمات ALTER TABLE، بشرط ألّا تتعارض هذه القيود المُضافة مع البيانات الموجودة أصلًا في الجدول. وعند إنشاء قيد جديد، سيولّد نظام قاعدة البيانات تلقائيًا اسمًا له، ولكن وفي العديد من تطبيقات SQL يمكنك تحديد اسم مُخصّص للقيد. إذ يُستخدم هذا الاسم للإشارة إلى القيد ضمن مجموعة التعليمات ALTER TABLE المُتعلّقة بتعديل القيد أو إزالته. يُعرّف المعيار الرسمي للغة SQL خمس قيود فقط وهي: قيد المفتاح الأساسي PRIMARY KEY قيد المفتاح الخارجي FOREIGN KEY قيد القيم الفريدة UNIQUE قيد التحقق CHECK القيد غير فارغ NOT NULL ملاحظة: تتضمّن العديد من نظم إدارة قواعد البيانات العلاقية الكلمة المفتاحية DEFAULT لتحديد قيمة ابتدائية افتراضية غير فارغة NULL تسند لسجلات العمود في حال عدم تحديد قيمة لحظة إضافة السجل. وتصف توثيقات بعض قواعد البيانات DEFAULT على أنها قيد، نظرًا لأن طريقة استخدامها تشابه لطريقة استخدام القيود الأخرى مثل UNIQUE أو CHECK. ولكن ومن الناحية التقنية، لا تعدّ DEFAULT قيدًا حقيقيًا لأنها لا تُحدّد أو تقيّد القيم التي يمكن إدخالها في العمود. بالعودة إلى موضوعنا، وبعد حصولك على فهمٍ عام حول كيفية استخدام القيود، لنلقِ نظرة أعمق على كل من هذه القيود الخمسة. القيد PRIMARY KEY يتطلب قيد المفتاح الأساسي PRIMARY KEY أن يكون كل مُدخل في العمود المعني غير فارغ وغير مكرر، سامحًا لك باستخدام هذا العمود لتعريف كل سجل في الجدول على نحوٍ فريد. والمفتاح key عمومًا في النموذج العلاقي عبارة عن عمود أو مجموعة من الأعمدة في جدول تضمن أن كل قيمة فيها فريدة وغير فارغة. أمّا المفتاح الأساسي فهو مفتاح خاص يستخدم لتعريف وتمييز سجلات الجدول على نحوٍ فردي، ويمكن استخدام العمود أو الأعمدة التي تكوّن مفتاح أساسي لتعريف الجدول وتحديده في باقي أجزاء قاعدة البيانات. وهذا جانب مهم في قواعد البيانات العلاقية فبوجود المفتاح الأساسي، لا يُضطر المستخدمون لمعرفة مكان تخزين البيانات فيزيائيًا على الجهاز، إذ يمكن لنظام إدارة قاعدة البيانات أن يتتبّع كل سجل ويسترجعه حسب الطلب. ما يعني بدوره عدم وجود ترتيب منطقي محدد للسجلات، وبالتالي يتمكّن المستخدمون من استرجاع بياناتهم بأي ترتيب يفضلونه أو وفق أي مُرشحات (عوامل تصفية) يختارونها. يمكنك إنشاء مفتاح أساسي في SQL باستخدام القيد PRIMARY KEY، والذي يُعدّ بالأصل مزيجًا من القيدين UNIQUE و NOT NULL. وبعد تعريف مفتاح أساسي، يُنشئ نظام إدارة قاعدة البيانات تلقائيًا فهرس index مرتبط به. والفهرس هو هيكلية في قاعدة البيانات تساعد في استرجاع البيانات من جدول ما بسرعة أكبر، وما على الاستعلامات إلّا استعراض الإدخالات الموافقة للعمود المُفهرس للعثور على القيم المترابطة (التابعة لسجل واحد) بآلية مُشابهة لاستخدام الفهرس في الكتب النصيّة العادية. الأمر الذي يسمح للمفتاح الأساسي بلعب دور المُعرّف لكل سجل في الجدول. يمكن لكل جدول أن يتضمّن مفتاح أساسي واحد فقط، والذي قد يشتمل على عدّة أعمدة كما هو الحال بالنسبة للمفاتيح النمطية regular keys، ولكن من مميزات المفاتيح الأساسية هو استعانتها بأقل عدد ممكن من السمات لتمييز كل سجل في الجدول على نحوٍ فريد. ولتبسيط هذه الفكرة، تخيل جدولًا يُخزّن معلومات الطلاب في مدرسة ما من خلال ثلاثة أعمدة كالتالي: studentID: يُستخدم لتخزين رقم التعريف (مُعرّف) الخاص بكل طالب. firstName: يُستخدم لتخزين الاسم الأول لكل طالب. lastName: يُستخدم لتخزين اسم العائلة لكل طالب. ولكن قد تتطابق الأسماء الأولى لبعض الطلاب في المدرسة، ما يجعل من العمود firstName خيارًا غير مناسب للاستخدام كمفتاح أساسي. وينطبق الأمر نفسه على العمود lastName. وبالتالي، قد يكون من المناسب استخدام مفتاح أساسي يتكون من الاسم الأول والأخير معًا، ولكن يبقى احتمال وجود طلاب بنفس الاسم الكامل قائمًا. وبالتالي، يمكن الاعتماد على مفتاح أساسي يتألف من عمود رقم تعريف الطالب studentID بالإضافة إلى عمود الاسم الأول firstName أو عمود الاسم الأخير lastName. ولكن وبما أنّ رقم تعريف كل طالب هو قيمة فريدة، فإنّ إضافة أحد أعمدة الأسماء للمفتاح الأساسي لا يُمثّل أي قيمة مُضافة. ولهذا، يعدّ استخدام عمود رقم تعريف الطالب وحده الخيار الأمثل ليكون المفتاح الأساسي لهذا الجدول. إذا كان المفتاح مكوّنًا من بيانات تطبيقية واقعية (أي بيانات تُمثّل كيانات أو أحداث أو سمات من العالم الواقعي)، فيُطلق عليه اسم مفتاح طبيعي natural key. أمّا إذا أُنشئ المفتاح داخليًا دون أن يُمثّل أي شيء خارج قاعدة البيانات، فيُعرف حينها باسم مفتاح بديل surrogate أو مفتاح مُصنّع synthetic key. تُوصي بعض أنظمة قواعد البيانات بتجنب استخدام المفاتيح الطبيعية، فحتى البيانات التي تبدو ثابتة قد تتغير بطرق غير متوقعة. القيد FOREIGN KEY يفرض القيد FOREIGN KEY أن تكون كل قيمة في العمود المعني موجودة بالفعل في عمود معين من جدول آخر. بفرض لديك جدولين، ووددت ربطهما ببعضهما البعض، فإحدى الطرق التي يمكنك استخدامها لهذا الغرض هي تعريف مفتاح خارجي باستخدام القيد FOREIGN KEY. والمفتاح الخارجي هو عمود في جدول معين (ويطلق عليه الجدول "الابن") تأتي قيمه من مفتاح في جدول آخر (ويطلق عليه "الأب" أو الجدول الرئيسي). وهذا ما يُعبّر عن علاقة بين الجدولين: فالقيد FOREIGN KEY يفرض أن تكون القيم في العمود المعني موجودة بالفعل في العمود المُشار إليه من الجدول الآخر. يُظهر المخطط التالي هذا النوع من العلاقة بين جدولين: إذ يُستخدم الأول لتسجيل معلومات حول الموظفين في شركة، ويُستخدم الثاني لتتبع مبيعات الشركة، وقد استخدمنا في هذا المثال مفتاح خارجي في جدول المبيعات SALES يشير إلى المفتاح الأساسي من جدول الموظفين EMPLOYEES: فإذا حاولت إضافة سجل إلى الجدول الابن مع كون القيمة المُدخلة في عمود المفتاح الخارجي من هذا السجل غير موجودة في عمود المفتاح الأساسي للجدول الأب فستكون تعليمة الإدراج هذه غير صالحة. الأمر الذي يضمن الحفاظ على نزاهة مستوى العلاقة بين الجدولين، بضمان ربط السجلات في الجدولين على النحو الصحيح دائمًا. فغالبًا ما يكون المفتاح الخارجي للجدول الابن هو المفتاح الأساسي للجدول الأب، ولكن الحال ليس على هذا النحو دائمًا. ففي معظم أنظمة إدارة قواعد البيانات العلاقية يمكن للمفتاح الخارجي في الجدول الابن الإشارة إلى أي عمود مُطبّق عليه أحد القيدين PRIMARY KEY أو UNIQUE في الجدول الأب. القيد UNIQUE يمنع القيد UNIQUE إضافة قيم مكررة إلى العمود المعني، وكما يوحي اسمه، يتطلب هذا القيد أن تكون كل قيمة تقوم بإدخالها في العمود المعني فريدةـ وأي محاولة لإضافة قيمة موجودة بالفعل فيه ستؤدي إلى ظهور خطأ. تفيد القيود UNIQUE في فرض علاقات من نوع واحد-إلى-واحد one-to-one بين الجداول. فرغم إمكانية تكوين علاقات بين الجداول باستخدام المفتاح الخارجي كما أشرنا سابقًا، إلّا أنّ هناك عدّة أنواع من العلاقات التي قد تظهر بين الجداول: واحد-إلى-واحد: نقول بأنّ علاقة من نوع واحد-إلى-واحد تربط بين جدولين إذا كان كل سجل في الجدول الأب مرتبط بسجل واحد فقط في الجدول الابن. واحد-إلى-عديد: في علاقة واحد-إلى-عديد، يمكن أن يرتبط كل سجل في الجدول الأب مع عدة سجلات في الجدول الابن، لكن كل سجل في الجدول الابن يمكن أن يرتبط بسجل واحد فقط من الجدول الأب. عديد-إلى-عديد: نقول بأنّ علاقة من نوع عديد-إلى-عديد تربط بين الجدولين إذا كان بإمكان السجلات في الجدول الأب أن ترتبط مع عدّة سجلات من الجدول الابن، والعكس صحيح. بإضافة القيد UNIQUE إلى عمود قد طُبّق عليه القيد FOREIGN KEY أيضًا، يمكنك التأكد من أن كل مُدخل في الجدول الأب يظهر مرة واحدة فقط في الجدول الابن، وبذلك تكون قد أنشأت علاقة من نوع واحد-إلى-واحد بين الجدولين. ومن الجدير بالذكر أنّه يمكن تعريف القيود UNIQUE على مستوى الجدول أو على مستوى العمود. فعند تعريف القيد UNIQUE على مستوى الجدول، يمكن أن يشمل حينها أكثر من عمود. وفي مثل هذه الحالات، يمكن لكل عمود مُدرج ضمن القيد أن يحتوي على قيم مكررة، ولكن يجب أن تكون لكل سجل مجموعة فريدة من القيم في الأعمدة الخاضعة للقيد. القيد CHECK يُعرّف القيد CHECK قاعدة يجب أن تُطبق على عمود معين على هيئة عبارة شرطية predicate ويجب أن تُحقق جميع القيم المُدخلة في ذلك العمود الشرط المسند لهذا العمود. حيث تُكتب شروط القيد CHECK بشكل تعبير شرطي يأخذ القيمة TRUE (صحيح/مُحقق) أو FALSE (خاطئ/غير مُحقق)، أو حتى UNKNOWN (غير معروف وهو ما يحدث في حالة وجود قيم فارغة NULL في العمود). فإذا حاولت إدخال قيمة في عمود خاضع للقيد CHECK وتسببت هذه القيمة في تقييم الشرط إلى TRUE أو UNKNOWN فستنجح العملية وتخزن القيمة في العمود، وإذا تم تقييم التعبير إلى FALSE ستفشل ولن يسمح لك بإدخالها. وتعتمد شروط القيد CHECK في كثير من الأحيان على عامل مقارنة رياضي (من قبيل <، >، <=، أو >=) لتحديد نطاق البيانات المسموح بإدخالها في العمود المُحدّد. فعلى سبيل المثال، من الاستخدامات الشائعة للقيود CHECK هي منع استقبال قيم سالبة في بعض الأعمدة وذلك في الحالات التي لا تكون فيها القيم السالبة مقبولة، كما سنوضح في المثال التالي. سنكتب تعليمة CREATE TABLE لإنشاء جدول يخزن بيانات المنتجات وسنطلق عليه اسم productInfo، يحتوي هذا الجدول على أعمدة لتخزين اسم كل منتج ورقم التعريف الخاص به وسعره. ونظرًا لأن سعر المنتج لا يمكن أن يكون سالبًا من الناحية المنطقية، فنكتب قيد CHECK على عمود السعر price لضمان احتوائه على قيم موجبة فقط بالشكل التالي: mysql> CREATE TABLE productInfo ( mysql> productID int, mysql> name varchar(30), mysql> price decimal(4,2) mysql> CHECK (price > 0) mysql> ); لا يُشترط استخدام عامل مقارنة رياضي في كل شرط من الشروط المنطقية الإسنادية الخاصة بالقيد CHECK. إذ يُمكنك استخدام أي معامل من معاملات SQL التي يمكن تقييمها في عبارة الشرط المنطقي إلى TRUE أو FALSE أو UNKNOWN، مثل LIKE و BETWEEN و IS NOT NULL وغيرها. وتسمح بعض تقديمات SQL -ولكن ليس كلها- بإضافة استعلام فرعي داخل العبارة الشرطية. في حين لا تسمح معظم التقديمات بالإشارة إلى جدول آخر داخل هذه العبارة الشرطية. القيد NOT NULL يحظرك القيد NOT NULL من إضافة أي قيم فارغة NULL إلى العمود المعني، فإذا أضفت سجل من البيانات ولم تُحدد فيه قيمة لعمود معين، فسوف يُمثّل نظام قواعد البيانات في معظم تقديمات SQL البيانات المفقودة افتراضيًا على أنها قيمة فارغة NULL. وفي لغة SQL تعد كلمة NULL مصطلحًا خاصًّا يُستخدم لتمثيل قيمة مجهولة أو مفقودة أو غير مُحددة. ولكن NULL ليست قيمة بحد ذاتها، بل هي حالة تُعبّر عن قيمة مجهولة أو غير متوفرة. ولتوضيح هذا الفارق، تخيل جدولًا يُستخدم لتتبع العملاء في شركة لاستقطاب المواهب ويحتوي هذا الجدول على أعمدة لأسماء العملاء الأولى والأخيرة. فإذا كان العميل معروفًا باسمٍ واحدٍ فقط، فسيُدخل مدير قاعدة البيانات هذا الاسم في عمود الاسم الأول فقط، مما يتسبب في إدخال قيمة فارغة NULL في عمود الاسم الأخير. في مثل هذه الحالة لا تعدّ قاعدة البيانات أن الاسم الأخير للعميل هو حرفيًا "فارغ". بل يعني ذلك فقط أن القيمة الموجودة في عمود الاسم الأخير لذلك السجل مجهولة أو غير متوفرة. وبالتالي، وكما يوحي اسمه، يمنعك القيد NOT NULL من إدخال قيم فارغة NULL أو تجاهل إدخال قيمة في العمود المعني. وبالتالي ستكون مجبورًا على تحديد قيمة لأي عمود طُبِّق عليه قيد NOT NULL عند إضافة سجل جديد، وإلا ستفشل عملية الإدراج. الخلاصة تعرفنا في مقال اليوم على مفهوم القيود التي تعد أحد المفاهيم الأساسية لأي شخص يرغب في تصميم قاعدة بيانات بمستوى عالٍ من نزاهة وأمان البيانات وسلامتها. إذ يمكنك التأكد من الحفاظ على العلاقات بين الجداول على النحو الصحيح من خلال تحديد البيانات التي يُسمح بإدخالها ضمن عمود معين، ما يضمن توافق قاعدة البيانات مع القواعد المطلوبة التي تحدد الغرض من إنشائها. للمزيد حول كيفية إنشاء وإدارة القيود في SQL، يمكنك مراجعة مقالنا كيفية استخدام القيود في SQL. وللمزيد حول SQL عمومًا، نشجعك على متابعة سلسلة تعلم SQL في أكاديمية حسوب. ترجمة -وبتصرف- للمقال Understanding SQL Constraints لصاحبه Mark Drake. اقرأ أيضًا المقال السابق: لماذا يجب عليك تعلم SQL؟ المفاهيم الأساسية في قواعد البيانات وتصميمها دليلك الشامل إلى قواعد البيانات DataBase البيانات في SQL: أنواعها والقيود عليها ما هي محركات قواعد البيانات؟
  10. قد تبدو لغة SQL أو لغة الاستعلام الهيكلية مُعقدة ومربكة للبعض في البداية، لكن مع التعلم والتعمق في اللغة ستصبح الأمور أوضح وأبسط فلغة SQL هي لغة سهلة التعلم بالعموم، وهي تُستخدم بشكل أساسي لتعريف ومعالجة والاستعلام عن البيانات المُخزنّة في قواعد البيانات العلاقية Relational، التي تعد أحد أشهر أنواع قواعد البيانات والتي تُنظّم البيانات فيها بدقة لتُناسب هيكلية أسطر (سجلات) وأعمدة (حقول) مُحدّدة مُسبقًا بشكل محدد وواضح. ملاحظة: يمكنك الاطلاع على تفاصيل أكثر حول قواعد البيانات العلاقية، بما في ذلك تاريخها والمفاهيم الرئيسية المُتعلّقة بها واستخداماتها الشائعة، بالعودة إلى المقال السابق فهم قواعد البيانات العلاقية. وبالعودة إلى موضوعنا، فقد ازدادت شهرة وشعبية لغة SQL منذ ظهورها في السبعينيات، وتوسّعت مجالات استخدامها على نحوٍ كبير منذ ذلك الحين. وتعدّ SQL في أيامنا من أبرز وأنضج اللغات المستخدمة في الاستعلام عن البيانات ومعالجتها في معظم القطاعات ومن أكثر الأدوات شهرةً. وبالتالي، فإن فرصة استخدام لغة SQL في مجال وظيفتك البرمجية كبيرة، فسواء كنت تعمل كمدير لقاعدة بيانات أو مصممًا لها أو مهندس برمجيات أو محلل بيانات، وحتى لو لم تكن تعمل في أي من الوظائف آنفة الذكر فستستفيد بالفعل من فهمك لأساسيات هذه اللغة وإن لم تستخدمها بشكل مباشر. يُبرز هذا المقال أهمية تعلم لغة SQL، ويشرح كيف وأين يمكنك تطبيق معرفتك لهذه اللغة والاستفادة منها. لغة SQL منتشرة بشكل واسع في عالم قواعد البيانات العلاقية إذا تعاملت مع أي قاعدة بيانات علاقية مثل MySQL أو PostgreSQL أو Microsoft SQL أو Oracle SQL أو غيرها الكثير، فستصادف بالتأكيد تعليمات SQL. إذ تُستخدم هذه اللغة على نطاق واسع لتعريف ومعالجة والاستعلام عن البيانات في هذا النوع من قواعد البيانات، فهي الوسيلة الأساسية للتفاعل مع محرك قاعدة البيانات. وبالرغم من أنّ العديد من أنظمة قواعد البيانات تُقدّم واجهات رسومية سهلة الاستخدام للتعامل مع بنية قاعدة البيانات وتعديل البيانات المُخزّنة فيها، إلا أن هذا لا يقلل من أهمية تقنية SQL أو يجعلها غير ضرورية. فبالرغم من إمكانية إنجاز المهام البسيطة بسرعة دون الحاجة إلى كتابة تعليمات SQL، ستتطلّب المهام الأعقد في معالجة البيانات أو الاستعلام عنها استخدام لغة SQL لبناء الاستعلامات وجلب البيانات التي تحتاجها بكفاءة مستفيدًا من قوة محرك قاعدة البيانات. وبالتالي بفهمك للغة SQL، ستتمكن من التعامل بسرعة مع أي نظام قاعدة بيانات علاقية مُستخدم اليوم تقريبًا، ولن تقتصر مهاراتك على برنامج محدد أو جهة عمل معينة. SQL مُستخدمة أيضًا على نحو واسع في مجالات عديدة أخرى استطاعت SQL بفضل شهرتها واستخدامها في أنظمة قواعد البيانات العلاقية المُعتَمَدة على نحوٍ متزايد، أن تجد طريقها إلى أنظمة قواعد بيانات وأدوات تحليل بيانات أخرى. إذ تتمتّع SQL والعديد من اللغات المُشتقّة منها بالدعم في العديد من أنظمة التخزين ومحركات تحليل البيانات وأدوات ذكاء الأعمال وأدوات التنقيب عن البيانات، وحتى في العديد من قواعد البيانات غير العلاقية وقواعد البيانات التحليلية Online analytical processing - OLAP وحلول البيانات الضخمة. وبغض النظر عن البرمجيات التي قد تصادفها لدى تحليل مجموعات البيانات الكبيرة، فهناك احتمالية عالية بأن تستفيد من معرفتك بلغة SQL للتعامل مع البيانات ضمن تلك الأدوات. إذ ستتمكن من اتباع منهجية مشابهة مع قواعد البيانات المتنوعة، الأمر الذي سيسهل عليك العمل ويجعله أشمل عبر مصادر البيانات المختلفة. وبالتالي تعدّ معرفة SQL من الأدوات الأساسية والضرورية التي يعتمد عليها محللو البيانات وعلماء البيانات على الدوام. كما تُعد لغة SQL ضمن أول عشر لغات برمجة وفق مؤشر مجتمع البرمجة TIOBE، وهو مؤشر يُظهر شعبية لغات البرمجة وانتشارها. تساعدك لغة SQL في التواصل مع الآخرين بخصوص البيانات لربما تُمثّل مناقشة البيانات تحديًا في العديد من الأحيان، فقد يفهم الأشخاص اللغة المحكية بطرق مختلفة قليلًا عما هو مطلوب، ما يُنشئ غموضًا قد يؤدي بدوره إلى سوء الفهم وأخطاء في التواصل. ولكن بمعرفتك لأساسيات SQL، كفهم كيفية هيكلة البيانات وكيفية الاستعلام عنها بنفسك، وستكون أدق لدى التواصل مع زملائك وأعضاء فريقك. فحتى إن لم تكن تنوي كتابة تعليمات SQL بنفسك، يمكنك استخدام خبرتك فيها لتوضيح متطلباتك وتوقعاتك بدقة. كما ستكون قادرًا على تحديد المشكلات المتعلقة بالبيانات التي تتلقاها، وتقديم تغذية راجعة واضحة وعملية لمحللي البيانات الذين يساعدونك في إعداد تلك البيانات. وبالتالي، يمكنك النظر إلى SQL على أنها لغة مشتركة يفهمها الجميع في عالم البيانات. فحتى إن لم تستخدمها على نحوٍ مباشر، فإن الاستناد إلى المفاهيم المُستمدّة منها ستجعل تواصلك بخصوص البيانات أدق وأوضح. تساعدك لغة SQL في تصميم قواعد بيانات أفضل من الضروري لدى تكليفك بتصميم قاعدة بيانات، أن تأخذ أنماط البيانات التي ستُخزّن وكيفية الوصول إليها أو التعامل معها مُستقبلًا في الحسبان. فبالرغم أنّه من الممكن بالطبع تصميم قواعد البيانات اعتمادًا على الفهم الجيد لنظرية تصميم قواعد البيانات فقط، إلّا أنّ الانتقال من التصميم النظري إلى قاعدة البيانات الفعلية قد يكون صعبًا، وستعترض المصمم مفاجآت غير متوقعة في الغالب. إذ سيُستخدم نوع من استعلامات SQL مع كل عملية استرجاع بيانات من قاعدة البيانات، وسواءً كتبت هذه الاستعلامات من قبل مُحلل البيانات أو أُنشئت عبر برمجيات مُتخصّصة. فإن فهمك لأنماط الاستخدام المطلوبة ومعرفتك لكيفية ترجمتها إلى استعلامات SQL قابلة للتنفيذ، سيمكنك من فهم كيفية وصول SQL إلى قاعدة البيانات الأساسية لاسترداد البيانات، وما الذي سيتعين على محرّك قاعدة البيانات إنجازه كاستجابةً لهذا الاستعلام. وبالتالي، يمكنك تصميم قواعد بيانات تلبي الغرض المطلوب باستخدام المعرفة التي اكتسبتها. وبمراعاتك لحالات الاستخدام التي يجب أن تدعمها قاعدة البيانات، يمكنك اختيار هيكلية لها تُسهّل إجراء استعلامات أبسط وأكفأ تُناسب سيناريوهات الاستخدام الشائعة. كما يمكنك هيكلة الجداول على نحوٍ مدروس، مُسهلًا الوصول إلى البيانات باستخدام أنماط البيانات والعلاقات المُعتمدة على المفاتيح الخارجية والفهارس. بمعنى أنّك ستتعلم كيفية تصميم قواعد بيانات تُناسب أهدافك على نحوٍ أفضل. تساعدك لغة SQL في كتابة تطبيقات أفضل تستفيد العديد من أطُر التطوير الحديثة مثل أطُر تطوير الويب المشهورة لارافيل Laravel أو Symfony أو جانغو Django أو Ruby on Rails من طبقات تجريد البيانات، لاسيما أدوات التخطيط بين الكائنات وقواعد البيانات العلاقيَّة object-relational mappers إذ تهدف هذه الأدوات إلى تبسيط عملية الوصول إلى البيانات وتقديمها بشكل مبسّط للمبرمج. فبينما توفر هذه الأطُر طرقًا بديلة للتفاعل مع البيانات اعتمادًا على التعليمات البرمجية البسيطة الخاصّة بها موفرّةً البيانات التي تطلبها بسلاسة، إلا أن فهمك للغة SQL سيمكّنك من التعامل مع البيانات بشكل أكثر فعالية ودقة، حتى وإن لم تستخدم SQL مباشرة في عملية التطوير. فبغض النظر عن العديد من الاختصارات والسهولة الكبيرة التي تقدمها أطر العمل، فإنها تُبنى استعلامات في محرك قاعدة البيانات الأساسي باستخدام جمل SQL خلف الكواليس من المدخلات الخاصة بك. وبالتالي فإن فهم كيفية عمل SQL يمكن أن يساعدك في استخدام ميزات الإطار البرمجي الذي اخترته لجعل الاستعلامات أسرع وأكثر فعالية، وبهذا يمكنك الاعتماد على معرفتك بكيفية بناء الإطار للاستعلامات في توجيه بنائها وتنفيذها على نحوٍ أمثل وصولًا إلى البيانات المطلوبة. ناهيك عن إمكانية تصحيح أي مشكلات في الاستعلام عن البيانات ومعالجتها على نحوٍ أسهل. فغالبًا ما تُعيد محركات قواعد البيانات أخطاء تُشير إلى الجزء الذي فشل من الاستعلام المُنفّذ فعليًا باستخدام SQL. وبالرغم من دقة هذه الأخطاء، يبقى تحديد مصدر المشكلة ضمن الصياغة الخاصة بالإطار المستخدم أمرًا صعبًا، ولكن فهمك لأخطاء قواعد البيانات سيمكنك من تحديد المشكلة بدقة. وأخيرًا وليس آخرًا، ستكون أكثر وعيًا بالمخاطر الأمنية الناتجة عن استخدام استعلامات SQL على نحوٍ غير صحيح وخطير، مثل هجمات حقن SQL، كما ستكون قادرًا على مواجهتها والتصدي لها. فبفضل معرفتك بلغة SQL، ستمتلك السيطرة الكاملة على كيفية الوصول إلى البيانات، سواء قررت استخدام SQL مباشرةً أو اخترت العمل مع طبقات التجريد وأدوات التخطيط بين الكائنات وقواعد البيانات العلاقية ضمن الأطُر البرمجية. لغة SQL سهلة التعلم للمبتدئين هناك العديد من الفوائد المرتبطة بفهم وتطبيق لغة الاستعلام الهيكلية في الواقع العملي. ولعلّ أحد أبرز ما يميزها هو سهولة تعلمها للمبتدئين. إذ تمتاز هذه اللغة بوضوحها ودقتها واستخدامها لكلمات إنجليزية شائعة كأسماء للعمليات والمُرشحات (عوامل التصفية) وغيرها من الواصفات (العناصر التي تغير أو تحدد سلوك الاستعلام). فيمكنك قراءة استعلامات SQL في كثير من الأحيان على هيئة جمل مكتوبة باللغة الإنجليزية، ما يجعلها مفهومة حتى دون وجود خلفية برمجية. ربما تجد بعض الجوانب الصعبة والمعقدة في اللغة والتي تحتاج إلى جهد لفهمها والتمرن عليها. ولكن بالمقابل يمكنك فهم وتعلم أساسيات لغة SQL بشكل ميسر. ومع استخدامك المتواصل لها في عملك اليومي، ستصبح عملية تعلم الأمور الأصعب أكثر فعالية لأنها تتم وفقًا لاحتياجاتك الفعلية للبيانات. وبالتالي يمكنك البدء مع أساسيات SQL، ومن ثم تطوير فهمك للغة تدريجيًا كلما احتجت لاستخدام طرق استعلام جديدة. والجيد في الأمر أنّ إجراء التجارب والتعامل مع SQL أثناء الاستعلام عن البيانات أمر سهل وخالٍ من المخاطر من ناحية فقدان البيانات، ما يوفّر لك الشعور بالأمان والراحة أثناء رحلة التعلّم. ستحصل بتعلمك للغة SQL على فوائد تتجاوز بكثير الوقت المستغرق في ذلك، وتكتسب طرقًا جديدة لاسترجاع البيانات من عدة المصادر وتحليلها وتحقق الاكتفاء الذاتي في حاجتك لتحليل البيانات، ما يفتح آفاق وظيفية جديدة في مجالات متعددة. الخلاصة غدت لغة SQL أكثر لغات الاستعلام عن البيانات ومعالجتها شيوعًا وشهرة بفضل مرونتها وسهولة استخدامها وتطبيقها في مجالات متعددة ذات صلة بالبيانات. وبالتالي، سيوفر لك تعلمها العديد من الفوائد الجليّة، حتى وإن لم تكن وظيفتك الرئيسية مرتبطة مباشرةً بقواعد البيانات أو بتطوير البرمجيات. ترجمة -وبتصرف- للمقال Why You Should Learn SQL لصاحبه Mateusz Papiernik. اقرأ أيضًا المقال السابق: فهم قواعد البيانات العلاقية ما هي تقنية SQL؟ أهمية قواعد البيانات أنواع قواعد البيانات وأهم مميزاتها واستخداماتها تعرف على مكونات قاعدة البيانات ما هي محركات قواعد البيانات؟
  11. تعدّ أنظمة إدارة قواعد البيانات Relational database management system أو اختصارًا DMBS برامج حاسوبية تسمح للمستخدمين بالتفاعل مع قاعدة البيانات وتتيح لهم إمكانية التحكّم بالوصول إلى قاعدة البيانات وكتابة البيانات فيها وتنفيذ الاستعلامات Queries التي تستخلص البيانات أو تعدلها وإنجاز أي مهمّة أخرى ذات صلة بإدارة قواعد البيانات. وبالتالي كي تتمكن من إنجاز أي من هذه المهام، يجب أن تمتلك أنظمة DMBS نموذجًا أساسيًا يُعرّف كيفية تنظيم البيانات. وإحدى منهجيات تنظيم البيانات التي لاقت استخدامًا واسعًا في برمجيات قواعد البيانات منذ ابتكارها في أواخر ستينيات القرن الماضي هي النموذج العلاقيّ أو العلائقي Relational، لدرجة أنّه وحتى وقت كتابة هذا المقال فإنّ أربعة من بين أكثر خمسة أنظمة لإدارة قواعد البيانات شيوعًا هي من النمط العلاقيّ. يوضّح هذا المقال المفاهيمي النظري تاريخ النموذج العلاقيّ وكيفية تنظيم البيانات في قواعد البيانات العلاقيَّة وكيفية استخدامها في تطبيقاتنا المختلفة. تاريخ النموذج العلاقي قواعد البيانات عبارة عن مجموعات من المعلومات أو البيانات المُنظّمة منطقيًا. إذ تُعدّ أي مجموعة من البيانات كقاعدة بيانات، بغض النظر عن كيفية أو مكان تخزينها. فحتى درج الملفات المُتضمّنة لمعلومات الرواتب يُعدّ قاعدة بيانات، كذلك الأمر بالنسبة لأي مجموعة مُكدّسة من البيانات مثل نماذج المرضى في مستشفى، أو معلومات مجموعة من عملاء شركة موزعة عبر عدّة مواقع. فقبل أن تغدو عملية تخزين وإدارة البيانات باستخدام الحواسيب شائعة، كانت قواعد البيانات المادية كهذه في الأمثلة السابقة هي الوحيدة المتاحة للحكومات والمنظمات التجارية التي كانت بحاجة لتخزين المعلومات. وفي منتصف القرن العشرين تقريبًا، شهدت علوم الحاسوب تطورات كبيرة أفضت إلى ظهور أجهزة ذات قدرة معالجة أعلى وسعات تخزين محلية وخارجية أكبر. جعلت هذه التطورات علماء الحاسوب يُدركون القدرات الهائلة لهذه الأجهزة في تخزين وإدارة كميات أكبر من البيانات. ولكن لم تكن هناك حينها نظريات مُحدّدة حول كيفية تنظيم البيانات في الحواسيب بطرق منطقية ذات معنى فقد كان من السهل تخزين البيانات عشوائيًا على جهاز ما، لكن تصميم أنظمة قواعد البيانات سيتيح إمكانية إضافة واسترجاع وترتيب وإدارة هذه البيانات بطرق عملية وثابتة هو تحدٍ أكبر. فقد أسفرت الحاجة إلى وجود نظام منطقي لتخزين وتنظيم البيانات إلى ظهور العديد من الاقتراحات حول كيفية استخدام الحواسيب في إدارة البيانات. ولعلّ أحد النماذج الأولية لقواعد البيانات كان النموذج الهرمي، حيث تنظم البيانات وفق هذا النموذج ضمن هيكلية أو بنية شبيهة بالشجرة بأسلوب مماثل لأنظمة الملفات. ويوضّح المثال التالي الشكل الذي قد يبدو عليه جزء من مخطط قاعدة بيانات هرمية تستخدم لتصنيف الحيوانات: لقد طُبِّق النموذج الهرمي على نحوٍ واسع في أنظمة إدارة قواعد البيانات الأولية، لكنه أظهر بالمقابل بعض الصعوبات من حيث المرونة. ففي هذا النموذج يمكن للسجل الواحد امتلاك عدّة أبناء Children، لكن لا يمكنه أن يتبع سوى لأب Parent واحد ضمن الهيكلية الهرمية، الأمر الذي يجعل قواعد البيانات الهرمية قادرة على التعبير فقط عن علاقات من نوع "واحد-إلى-واحد (one-to-one)" و"واحد-إلى-عديد (one-to-many)" ولا يسمح بالتعبير عن العلاقات من نوع "عديد-إلى-عديد (many-to-many)"، وهذا القصور قد يفضي إلى حدوث مشاكل لدى التعامل مع نقاط بيانات تتبع لأكثر من أب. إلى أن ابتكر عالم الحاسوب إدجار فرانك كود Edgar F. Codd والذي كان يعمل في شركة IBM النموذج العلاقيّ لإدارة قواعد البيانات وذلك في أواخر ستينيات القرن الماضي. إذ سمح نموذج Codd العلاقيّ هذا بربط السجل الواحد بأكثر من جدول، ما سمح بإمكانية التعبير عن العلاقات من نوع "عديد-إلى-عديد" بين نقاط البيانات ممكنة، بالإضافة إلى إمكانية التعبير عن العلاقات من نوع "واحد-إلى-عديد". الأمر الذي أتاح المزيد من المرونة مقارنةً بالنماذج الموجودة حينها لتصميم هياكل قواعد البيانات وأثبت قدرة أنظمة إدارة قواعد البيانات العِلاقيَّة (RDBMSs) على تلبية مجموعة أوسع بكثير من احتياجات الأعمال. كما اقترح العالم كود Codd لغة لإدارة البيانات العلاقيَّة عُرِفت باسم ألفا (Alpha)، والتي أثّرت في تطوير لغات قواعد البيانات اللاحقة. فقد أنشأ اثنان من زملائه في IBM وهما دونالد تشامبرلين Donald Chamberlin وريمون بويس Raymond Boyce لغة مستوحاة من لغة ألفا، أطلقا عليها اسم SEQUEL اختصارًا لعبارة Structured English Query Language (لغة الاستعلام الهيكلية بالإنجليزية)، ولكن بسبب وجود علامة تجارية موجودة مسبقًا بنفس الاسم، اختصروا اسم لغتهم إلى SQL والتي يُشار إليها على نحوٍ أكثر رسمية باسم لغة الاستعلام الهيكلية Structured Query Language. كانت قواعد البيانات العلاقيَّة الأولية بطيئة للغاية وغير عملية بسبب قيود العتاد، واحتاجت بعض الوقت حتى تنتشر، ولكن ومع حلول منتصف الثمانينات، طُبّق نموذج Codd العِلاقيّ في العديد من المنتجات التجارية لإدارة قواعد البيانات، سواء من قبل شركة IBM أو منافسيها. إذ قام هؤلاء المُصنعّون أيضًا باتباع خطى IBM من خلال تطوير وتنفيذ لهجاتهم الخاصة من لغة SQL. وبحلول عام 1987، صادق كل من المعهد الوطني الأمريكي للمعايير American National Standards Institute والمنظمة الدولية للمعايير International Organization for Standardization على معايير لغة SQL ونشروها، ما جعل منها اللغة المعترف بها لإدارة أنظمة قواعد البيانات العلاقيَّة. ولعلّ انتشار استخدام النموذج العلاقيّ في مجموعة متنوعة من المجالات جعل منه النموذج المعياري لإدارة البيانات. وحتى مع ظهور العديد من قواعد البيانات غير العلاقية NoSQL في السنوات الأخيرة، تبقى قواعد البيانات العلاقية هي السائدة لتخزين وتنظيم البيانات. كيف تنظم قواعد البيانات العلاقية البيانات الآن وبعد حصولك على فهمٍ عام لتاريخ النموذج العلاقيّ، لنلقِ نظرة أعمق على كيفية تنظيم البيانات وفق هذا النموذج. لعلّ أهم عناصر النموذج العلاقيّ هي العلاقات Relations، والتي تُعرف لدى المستخدمين وفي أنظمة إدارة قواعد البيانات العِلاقيَّة المعاصرة بمسمى الجداول Tabels. فالعلاقة هي مجموعة من الصفوف أو السجلات في جدول، ويشترك كل صف بمجموعة من السمات أو الأعمدة (الحقول): العمود هو أصغر هيكل تنظيمي في قاعدة البيانات العلاقيَّة، وهو يُمثّل الخصائص المختلفة التي تُعرّف السجلات ضمن الجدول. ولذا، تُعرف هذه الخصائص رسميًا باسم السمات. يمكن فهم كل صف على أنّه نسخة فريدة تًمثّل نوع ما من الأشخاص أو الكائنات أو الأحداث أو الروابط المحفوظة في الجدول. وقد تُمثّل هذه النسخ موظفي شركة أو مبيعات شركة تجارية عبر الإنترنت أو نتائج اختبارات مخبرية. على سبيل المثال، في جدول يحتوي على سجلات المدرسين في مدرسة ما، قد تتضمن الصفوف سمات مثل: الاسم name والمقررات الدراسية subjects وتاريخ بدء العمل start_date، وما إلى ذلك. ولدى إنشاء الأعمدة، يتعيّن عليك تحديد نمط البيانات الخاص بكل عمود، وهو ما يُحدّد القيم التي يمكن استقبالها فيه. وعادةً ما تُقدّم أنظمة إدارة قواعد البيانات العِلاقيَّة أنماطًا فريدة خاصة بها من البيانات والتي قد لا تكون متوافقة مباشرةً مع مثيلاتها في الأنظمة الأخرى. ومن أنماط البيانات شائعة الاستخدام كل من التواريخ، والسلاسل النصية، والأعداد الصحيحة، والقيم المنطقية. يتضمّن كل جدول في النموذج العِلاقيّ عمودًا واحدًا على الأقل يُستخدم لتمييز كل سجل على نحوٍ فريد، ويُعرف باسم المفتاح الأساسي Primary Key. وهو عمود مهم جدًا، إذ لا يحتاج المستخدمون لمعرفة مكان تخزين بياناتهم فيزيائيًا داخل الجهاز. وبدلاً من ذلك، يتولى نظام إدارة قواعد البيانات متابعة وتعقّب كل سجل واسترجاعه حسب الطلب. وبالتالي، لا يوجد ترتيب منطقي مُحدّد للسجلات، ويتمتّع المستخدمون بالحرية في استرجاع بياناتهم بالترتيب الذي يرغبون به أو باستخدام عوامل التصفية التي يختارونها. فبفرض كان لديك جدولين وتود ربطهما ببعضهما البعض، فإحدى الطرق لإنجاز ذلك هي باستخدام المفتاح الخارجي Foreign key، وهو نسخة من المفتاح الأساسي لجدول (يُعرف بالجدول "الأب") تُدرج في عمود داخل جدول آخر (يُعرف بالجدول "الابن"). يُظهر المثال التالي العلاقة بين جدولين، الأول يُستخدم لتسجيل المعلومات حول الموظفين في شركة، والثاني لتتبع مبيعات الشركة. وفي هذا المثال، يُستخدم المفتاح الأساسي لجدول الموظفين EMPLOYEES كمفتاح أجنبي لجدول المبيعات SALES: فإذا حاولت إضافة سجل إلى الجدول الابن وكانت القيمة المُدخلة في عمود المفتاح الأجنبي غير موجودة في المفتاح الأساسي للجدول الأب، فإن تعليمة الإدراج ستكون غير صالحة، وهذا يساعد في الحفاظ على صحّة مستوى العلاقة بين الجدولين (أو نزاهة العلاقة إن صح التعبير)، وبهذا ستكون السجلات في الجدولين مرتبطة على النحو الصحيح دائمًا. لقد ساعدت عناصر النموذج العلاقيّ الهيكلية في الحفاظ على تنظيم البيانات أثناء تخزينها، ولكن تخزين البيانات لن يكون مفيدًا إلا إذا كان من الممكن استرجاعها. ولاسترجاع البيانات من RDBMS، يُمكنك إنشاء ما يُسمّى بالاستعلام query وهو عبارة عن طلب منظّم لمجموعة من المعلومات. وتستخدم معظم قواعد البيانات العِلاقيَّة لغة SQL لإدارة البيانات والاستعلام عنها كما أشرنا سابقًا. إذ تتيح لغة SQL إمكانية تصفية نتائج الاستعلام ومعالجتها باستخدام مجموعة من البنى clauses، والجمل الشرطية predicates التي تقيم كصحيح TRUE أو خاطئ FALSE أو غير معروف، والتعبيرات expressions، ما يمنحك التحكم الدقيق في البيانات التي ستظهر ضمن نتائج الاستعلام. مزايا وقيود قواعد البيانات العلاقية لنفكّر في بعض مزايا وعيوب قواعد البيانات العلاقيَّة بأخذ هيكلها التنظيمي الأساسي في الحسبان. إنّ لغة SQL وقواعد البيانات التي تستخدمها في أيامنا هذه تختلف عما قدمه العالم كود Codd في نموذجه العلاقيّ الأول في عدة نواحٍ. فعلى سبيل المثال، يملي نموذج كود Codd بأنّ كل سجل في الجدول يجب أن يكون فريدًا. في حين تسمح العديد من قواعد البيانات العلاقيَّة المعاصرة بوجود سجلات مكررة. وهناك بالمقابل من يرى أن قواعد البيانات التي تستخدم لغة SQL ولا تتبع جميع مواصفات نموذج Codd لا يمكن عدها قواعد بيانات علاقيَّة حقيقية. ولكن وفي الواقع، أي نظام يستخدم SQL ويتبع نموذج Codd إلى حد معين يعدّ عادةً نظامًا لإدارة قواعد بيانات علاقيَّة. ورغم شهرة قواعد البيانات العِلاقيَّة التي ازدادت بسرعة، إلا أنّ بعض أوجه القصور المتعلقة في النموذج العِلاقيّ بدأت بالظهور مع تزايد قيمة البيانات وتوجه الشركات لتخزين كميات أكبر منها. ومن هذه التحديات والمعوقات، صعوبة توسيع قاعدة البيانات العلاقيَّة أفقيًا. والمقصود بالتوسع الأفقي أو الخارجي عملية إضافة المزيد من الأجهزة إلى نظام حالي لتوزيع الحمولة واستيعاب حركة مرور أكبر وتحقيق معالجة أسرع. وغالبًا ما تُقارن هذه العملية بالتوسع العمودي، الذي يتضمن تحسين مواصفات الخادم الحالي من خلال توسيع ذاكرة الوصول العشوائي RAM أو وحدة المعالجة المركزية CPU. والسبب وراء صعوبة توسيع قاعدة البيانات العلاقيَّة أفقيًا يعود إلى أنّ النموذج العلاقيّ مصمم لضمان الاتساق أو انسجام البيانات consistency، ما يعني أنّه عند استعلام العملاء ضمن قاعدة البيانات نفسها سيحصلون دائمًا على البيانات نفسها. فإذا قمت بتوسيع قاعدة البيانات العلاقيَّة أفقيًا عبر عدة أجهزة، سيصبح من الصعب ضمان هذا الاتساق، إذ قد يقوم العملاء بكتابة البيانات على عقدة معينة أو (جهاز) دون الباقي، وقد يكون هناك تأخير بين لحظة الكتابة الأولية والوقت الذي تُحدّث فيه العقد الأخرى لتعكس هذه التغييرات، ما يؤدي إلى عدم اتساق بينها. لقد واجهت أنظمة إدارة قواعد البيانات العلاقيَّة بعض التحديات، من بينها أن النموذج العلاقيّ قد صُمّم خصيصًا للتعامل مع البيانات المهيكلة structured data، أي البيانات التي تتوافق مع نمط بيانات مُحدد مسبقًا أو على الأقل تلك المُنظمّة على نحوٍ مُحدد. لكن مع انتشار الحواسيب الشخصية وظهور الإنترنت في أوائل التسعينات، أصبحت البيانات غير المهيكلة unstructured data، كالرسائل الإلكترونية والصور والفيديوهات أكثر شيوعًا. لا يعني كل ذلك أن قواعد البيانات العلاقيَّة باتت غير مفيدة. بل على العكس تمامًا، فالنموذج العلاقيّ ما زال هو الإطار السائد لإدارة البيانات منذ أكثر من 40 عامًا. وتدلّ شهرتها واستمراريتها على أنّ قواعد البيانات العلاقيَّة تقنية ناضجة، وهذا بحد ذاته من أبرز مزاياها. هناك العديد من التطبيقات التي صُممت للعمل مع النموذج العِلاقيّ، بالإضافة إلى وجود العديد من مدراء قواعد البيانات المحترفين الخبراء في مجال قواعد البيانات العلاقيَّة. كما تتوفر مجموعة واسعة من الموارد المطبوعة والإلكترونية متاحة لكل من يرغب في بدء التعامل مع قواعد البيانات العِلاقيَّة. ومن مميزات قواعد البيانات العلاقيَّة دعم معظمها لمجموعة من التعاملات transactions التي تضمن سلامة البيانات وتكاملها. والمعاملة transaction هي مجموعة من أوامر SQL التي تُنفذ وفق تسلسل معيّن كوحدة عمل مُنفصلة. إذ تعتمد المعاملات على مبدأ الكل أو لا شيء، بمعنى أنّ كل أمر في المعاملة يجب أن يكون صحيحًا، وإلا ستُلغى المعاملة بالكامل وبهذا نضمن صحّة البيانات ودقتها (نزاهة البيانات) عند التعديل على عدة سجلات أو جداول في الوقت نفسه. وأخيرًا، تعدّ قواعد البيانات العلاقيَّة مرنة للغاية. فقد استُخدمت في تطوير مجموعة واسعة من التطبيقات المختلفة، وتستمر في العمل بكفاءة حتى مع كميات ضخمة من البيانات. كما تعدّ لغة SQL قوية جدًا، إذ تتيح لك إمكانية إضافة وتعديل البيانات على نحوٍ فوري، بالإضافة إلى تغيير هيكلية تخطيط قواعد البيانات والجداول دون التأثير على البيانات الموجودة. الخلاصة تعرفنا في مقال اليوم على قواعد البيانات العلاقيَّة التي لا تزال وسيلة أساسية لإدارة وتخزين البيانات بعد أكثر من خمسين عامًا على وضع التصور الأولي لها، وذلك بفضل مرونتها وتصميمها الذي يضمن صحة البيانات ودقتها. وحتى مع ظهور قواعد البيانات غير العِلاقيَّة NoSQL في السنوات الأخيرة، لا زال فهم النموذج العلاقيّ ومعرفة كيفية التعامل مع أنظمة إدارة قواعد البيانات العلاقيَّة أمر أساسي لأي شخص يرغب في بناء التطبيقات المُعتمدة على قوة البيانات. وللتعرّف على المزيد حول بعض من أنظمة إدارة قواعد البيانات العِلاقيَّة الأشهر، وقواعد البيانات عمومًا، ننصحكم بالرجوع إلى قسم قواعد البيانات من أكاديمية حسوب. ترجمة -وبتصرف- للمقال Understanding Relational Databases لصاحبه Mark Drake. اقرأ أيضًا مدخل إلى تصميم قواعد البيانات تعرف على مكونات قاعدة البيانات نموذج الكيان والعلاقة ER لتمثيل البيانات وتخزينها في قاعدة البيانات ما هي محركات قواعد البيانات؟ أنواع قواعد البيانات وأهم مميزاتها واستخداماتها
×
×
  • أضف...