سنتعرف في مقال اليوم على طريقة استخدام بنى 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.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.