تستخدم لغة الاستعلام البنيوية Structured Query Language -أو SQL اختصارًا- مجموعةً متنوعة من هياكل البيانات، وتُعدّ الجداول من أكثرها استخدامًا، ولكن يكون لهذه الجداول قيود أو محدوديات معينة، فمثلًا لا يمكنك تقييد المستخدمين للوصول إلى جزء من الجدول فقط، إذ يجب أن يتمكّن المستخدم من الوصول إلى الجدول بأكمله، وليس إلى بعض الأعمدة ضمنه فقط.
لنفترض مثلًا أنك تريد دمج البيانات من عدة جداول في هيكل بيانات جديد، ولكنك لا تريد حذف الجداول الأصلية، حيث يمكنك إنشاء جدول آخر فقط، ولكن سيكون لديك بيانات زائدة مخزَّنة في أماكن متعددة لاحقًا. قد يسبّب ذلك الكثير من الإزعاج، حيث إذا تغيرت بعض بياناتك، فيجب عليك أن تحدّثها في أماكن متعددة، لذا يمكن أن تكون العروض Views مفيدة في مثل هذه الحالات.
يُعَد العرض view في لغة SQL جدولًا افتراضيًا، وتكون محتوياته نتيجة لاستعلام محدّد لجدول واحد أو أكثر، حيث تُعرَف هذه الجداول باسم الجداول الأساسية Base Tables. يقدّم هذا المقال نظرة عامة حول عروض SQL وفوائدها، ويوضّح كيفية إنشاء العروض والاستعلام عنها وتعديلها وتدميرها باستخدام صيغة SQL المعيارية.
مستلزمات العمل
يجب أن يكون لديك حاسوب يشغّل أحد أنواع أنظمة إدارة قواعد البيانات العلاقية Relational Database Management System -أو RDBMS اختصارًا- التي تستخدم لغة SQL. اختبرنا التعليمات والأمثلة الواردة في هذا المقال باستخدام البيئة التالية:
- خادم عامل على توزيعة أوبنتو Ubuntu مع مستخدم ذو صلاحيات مسؤول مختلف عن المستخدم الجذر وجدار حماية مضبوط باستخدام أداة UFW كما هو موضح في دليل الإعداد الأولي للخادم مع الإصدار 20.04 من أوبنتو، كما يمكنك الاطلاع على مقال كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة.
- نظام MySQL مُثبَّت ومؤمَّن على الخادم كما هو موضح في مقال كيفية تثبيت MySQL على أوبنتو، وقد نفذنا الخطوات باستخدام مستخدم مُنشَأ وفق الطريقة الموضحة في الخطوة 3 من المقال.
ملاحظة: تجدر الإشارة إلى أنّ الكثير من أنظمة إدارة قواعد البيانات العلاقية RDBMS لها تقديماتها الفريدة من لغة SQL، إذ ستعمل الأوامر المُقدمة في هذا المقال بنجاح مع معظم هذه الأنظمة، ولكن قد تجد بعض الاختلافات في الصيغة أو الناتج عند اختبارها على أنظمة مختلفة عن MySQL.
ستحتاج أيضًا إلى قاعدة بيانات تحتوي على بعض الجداول المُحمَّلة ببيانات تجريبية نموذجية لتتمكن من التدرب على إنشاء العروض والتعامل معها، لذا اطّلع على القسم التالي للحصول على تفاصيل حول كيفية الاتصال بخادم MySQL وإنشاء قاعدة بيانات الاختبار المُستخدَمة في أمثلة هذا المقال.
الاتصال بخادم MySQL وإعداد قاعدة بيانات تجريبية نموذجية
إذا كان نظام قاعدة بيانات SQL الخاص بك يعمل على خادم بعيد، فاتصل بالخادم مُستخدمًا بروتوكول SSH من جهازك المحلي كما يلي:
$ ssh user@your_server_ip
ثم افتح واجهة سطر أوامر خادم MySQL مع وضع اسم حساب مستخدم MySQL الخاص بك مكان user
:
$ mysql -u user -p
أنشِئ قاعدة بيانات باسم views_db
في موجّه الأوامر:
mysql> CREATE DATABASE views_db;
إذا أُنشئِت قاعدة البيانات بنجاح، فسيظهر خرج كما يلي:
الخرج Query OK, 1 row affected (0.01 sec)
يمكنك اختيار قاعدة البيانات views_db
من خلال تنفيذ تعليمة USE
التالية:
mysql> USE views_db;
ويكون الخرج كما يلي:
الخرج Database changed
اخترنا قاعدة بيانات views_db
، وسننشئ جدولين ضمنها. لنفترض مثلًا أنك تدير خدمة رعاية للكلاب، فقررت استخدام قاعدة بيانات SQL لتخزين معلومات حول كل كلب مُسجَّل في الخدمة، بالإضافة إلى معلومات كل متخصص في رعاية الكلاب توظفه خدمتك، حيث نظّمت هذه المعلومات من خلال إنشاء جدولين: أحدهما يمثل الموظفين والآخر يمثل الكلاب التي تعتني بها خدمتك. سيحتوي الجدول الذي يمثل موظفيك على الأعمدة التالية:
-
emp_id
: رقم تعريف لكل موظف يقدّم رعايةً للكلاب، ونعبّر عنه باستخدام نوع البياناتint
، وسيكون هذا العمود هو المفتاح الرئيسي Primary Key للجدول، أي أن كل قيمة ستمثّل معرّفًا فريدًا للصف الخاص بها، وسيكون لهذا العمود أيضًا قيدUNIQUE
مطبَّق عليه، إذ يجب أن تكون كل قيمة في المفتاح الرئيسي فريدة. -
emp_name
: اسم الموظف، ونعبّر عنه باستخدام نوع البياناتvarchar
بحد أقصى 20 محرفًا.
نفّذ تعليمة CREATE TABLE
التالية لإنشاء جدول بالاسم employees
ويحتوي على العمودين التاليين:
mysql> CREATE TABLE employees ( mysql> emp_id int UNIQUE, mysql> emp_name varchar(20), mysql> PRIMARY KEY (emp_id) mysql> );
سيحتوي الجدول الآخر الذي يمثل الكلاب على الأعمدة الستة التالية:
-
dog_id
: رقم تعريف لكل كلب ويُعبَّر عنه بنوع البياناتint
، وسيكون هذا العمود هو المفتاح الرئيسي للجدولdogs
مثل العمودemp_id
في الجدولemployees
. -
dog_name
: اسم الكلب ويُعبَّر عنه باستخدام نوع البياناتvarchar
بحد أقصى 20 محرفًا. -
walker
: يخزّن هذا العمود رقم معرّف الموظف الذي يرعى كل كلب. -
walk_distance
: المسافة التي يجب أن يمشيها كل كلب عند اصطحابه للتمرين، ويُعبَّر عنه باستخدام نوع البياناتdecimal
، ويمكن أن تحتوي القيم في هذا العمود على ثلاثة أرقام على الأكثر مع وجود رقمين من هذه الأرقام على يمين الفاصلة العشرية. -
meals_perday
: توفر هذه الخدمة لكل كلب عددًا معينًا من الوجبات كل يوم، حيث يحتوي هذا العمود على عدد الوجبات التي يجب أن يحصل عليها كل كلب يوميًا حسب طلب مالكه، ويستخدم نوع البياناتint
فهو عدد صحيح. -
cups_permeal
: يمثل هذا العمود عدد أكواب الطعام التي يجب أن يحصل عليها كل كلب في كل وجبة، ويُعبَّر عنه بنوع البياناتdecimal
مثل العمودwalk_distance
، ويمكن أن تحتوي القيم في هذا العمود على ما يصل إلى ثلاثة أرقام مع وجود رقمين من هذه الأرقام على يمين الفاصلة العشرية.
نتأكد من أن العمود walker
يحتوي على القيم التي تمثل أرقام معرّف الموظف الصالحة فقط من خلال تطبيق قيد مفتاح خارجي Foreign Key على العمود walker
الذي يشير إلى العمود emp_ID
الخاص بالجدول employees
. يُعَد قيد المفتاح الخارجي طريقة للتعبير عن العلاقة بين جدولين من خلال اشتراط أن تكون القيم الموجودة في العمود الذي طُبِّق المفتاح الخارجي عليه موجودة في العمود الذي يشير إليه، حيث يشترط قيد FOREIGN KEY
في المثال التالي أن تكون أيّ قيمة مضافة إلى العمود walker
في الجدول dogs
موجودةً في العمود emp_ID
الخاص بالجدول employees
. لننشئ جدولًا بالاسم dogs
يحتوي على هذه الأعمدة باستخدام الأمر التالي:
mysql> CREATE TABLE dogs ( mysql> dog_id int UNIQUE, mysql> dog_name varchar(20), mysql> walker int, mysql> walk_distance decimal(3,2), mysql> meals_perday int, mysql> cups_permeal decimal(3,2), mysql> PRIMARY KEY (dog_id), mysql> FOREIGN KEY (walker) mysql> REFERENCES employees(emp_ID) );
يمكنك الآن تحميل الجدولين ببعض البيانات التجريبية النموذجية. نفّذ عملية الإدخال INSERT INTO
التالية لإضافة ثلاثة صفوف من البيانات تمثّل ثلاثة من موظفي الخدمة إلى الجدول employees
:
mysql> INSERT INTO employees mysql> VALUES mysql> (1, 'Peter'), mysql> (2, 'Paul'), mysql> (3, 'Mary');
ثم نفّذ العملية التالية لإدخال سبعة صفوف من البيانات في الجدول dogs
:
mysql> INSERT INTO dogs mysql> VALUES mysql> (1, 'Dottie', 1, 5, 3, 1), mysql> (2, 'Bronx', 3, 6.5, 3, 1.25), mysql> (3, 'Harlem', 3, 1.25, 2, 0.25), mysql> (4, 'Link', 2, 2.75, 2, 0.75), mysql> (5, 'Otto', 1, 4.5, 3, 2), mysql> (6, 'Juno', 1, 4.5, 3, 2), mysql> (7, 'Zephyr', 3, 3, 2, 1.5);
وأصبحتَ الآن جاهزًا لمتابعة بقية هذا المقال والبدء في تعلّم كيفية استخدام العروض في لغة SQL.
فهم وإنشاء العروض Views
يمكن أن تصبح استعلامات SQL معقدة، ولكن إحدى الفوائد الرئيسية للغة SQL هي أنها تتضمن العديد من الخيارات والتعليمات التي تسمح لك بترشيح بياناتك بمستوى عالٍ من الدقة والتحديد. إذا كانت لديك استعلامات معقدة تريد تشغيلها بصورة متكررة، فقد يصبح الاضطرار إلى كتابتها باستمرار أمرًا مملًا، وإحدى الطرق لحل هذه المشكلات هي استخدام العروض.
تُعَد العروض views جداولًا افتراضية كما ذكرنا سابقًا، وهذا يعني أنها تشبه الجداول وظيفيًا، ولكنها تمثّل نوعًا مختلفًا من هياكل البيانات لأن العرض لا يحتوي على أيّ بيانات خاصة به، فهو يسحب البيانات من جدول أساسي واحد أو أكثر، وتكون المعلومات الوحيدة حول العرض التي سيخزنها نظام إدارة قواعد البيانات DBMS هي هيكل العرض. تُسمَّى العروض أحيانًا بالاستعلامات المحفوظة Saved Queries، لأنها تمثّل الاستعلامات المحفوظة باسم مُحدَّد لتسهيل الوصول إليها.
ليكن لدينا المثال التالي، تخيل أن أعمال رعاية الكلاب الخاصة بك ناجحة وتريد طباعة جدول يومي لجميع موظفيك، إذ يجب أن يحتوي هذا الجدول على كل كلب ترعاه الخدمة، والموظف المكلف برعايته، والمسافة التي يجب أن يمشيها كل كلب يوميًا، وعدد الوجبات التي يجب إطعامها لكل كلب يوميًا، وكمية الطعام التي ينبغي أن يحصل كل كلب في كل وجبة.
استخدم مهاراتك في لغة SQL لإنشاء استعلام مع بياناتٍ تجريبية نموذجية من الخطوة السابقة لاسترجاع جميع هذه المعلومات للجدول، ولاحظ أن هذا الاستعلام يتضمن صيغة JOIN
لسحب البيانات من الجدولين employees
و dogs
:
mysql> SELECT emp_name, dog_name, walk_distance, meals_perday, cups_permeal mysql> FROM employees JOIN dogs ON emp_ID = walker;
الخرج +----------+----------+---------------+--------------+--------------+ | emp_name | dog_name | walk_distance | meals_perday | cups_permeal | +----------+----------+---------------+--------------+--------------+ | Peter | Dottie | 5.00 | 3 | 1.00 | | Peter | Otto | 4.50 | 3 | 2.00 | | Peter | Juno | 4.50 | 3 | 2.00 | | Paul | Link | 2.75 | 2 | 0.75 | | Mary | Bronx | 6.50 | 3 | 1.25 | | Mary | Harlem | 1.25 | 2 | 0.25 | | Mary | Zephyr | 3.00 | 2 | 1.50 | +----------+----------+---------------+--------------+--------------+ 7 rows in set (0.00 sec)
لنفترض أنه يجب تنفيذ هذا الاستعلام بشكل متكرر، إذ قد يصبح أمرًا مملًا إذا اضطررت إلى كتابة الاستعلام مرارًا وتكرارًا، وخاصةً عند إجراء تعليمات استعلام أطول وأكثر تعقيدًا، وإذا أردتَ إجراء تعديلات طفيفة على الاستعلام أو التوسّع فيه، فقد يكون الأمر مملًا عند استكشاف الأخطاء وإصلاحها مع وجود العديد من الاحتمالات للأخطاء الصياغية. يمكن أن يكون العرض مفيدًا في مثل هذه الحالات، لأنه يُعَد جدولًا مشتقًا من نتائج الاستعلام.
تستخدم معظم أنظمة RDBMS الصيغة التالية لإنشاء العروض:
CREATE VIEW view_name AS SELECT statement;
يمكنك بعد تعليمة CREATE VIEW
اختيار اسمٍ للعرض الذي ستستخدمه للإشارة إليه لاحقًا، ثم تدخِل الكلمة المفتاحية AS
، ثم تضع استعلام SELECT
الذي تريد حفظ خرجه. يمكن أن يكون الاستعلام الذي تستخدمه لإنشاء عرضك أيّ تعليمة SELECT
صالحة، ويمكن أن تستعلم التعليمة التي تضمّنها عن جدول أساسي واحد أو أكثر طالما أنك تستخدم الصيغة الصحيحة.
جرّب إنشاء عرض باستخدام استعلام المثال السابق، حيث تسمّي عملية CREATE VIEW
العرض بالاسم walking_schedule
:
mysql> CREATE VIEW walking_schedule mysql> AS mysql> SELECT emp_name, dog_name, walk_distance, meals_perday, cups_permeal mysql> FROM employees JOIN dogs mysql> ON emp_ID = walker;
ستتمكّن بعد ذلك من استخدام هذا العرض والتفاعل معه كما تفعل مع أيّ جدول آخر، فمثلًا يمكنك تنفيذ الاستعلام التالي لإعادة جميع البيانات الموجودة في العرض:
mysql> SELECT * FROM walking_schedule;
الخرج +----------+----------+---------------+--------------+--------------+ | emp_name | dog_name | walk_distance | meals_perday | cups_permeal | +----------+----------+---------------+--------------+--------------+ | Peter | Dottie | 5.00 | 3 | 1.00 | | Peter | Otto | 4.50 | 3 | 2.00 | | Peter | Juno | 4.50 | 3 | 2.00 | | Paul | Link | 2.75 | 2 | 0.75 | | Mary | Bronx | 6.50 | 3 | 1.25 | | Mary | Harlem | 1.25 | 2 | 0.25 | | Mary | Zephyr | 3.00 | 2 | 1.50 | +----------+----------+---------------+--------------+--------------+ 7 rows in set (0.00 sec)
يُعَد هذا العرض مشتقًا من جدولين آخرين، ولكنك لن تتمكّن من الاستعلام عن العرض لأيّ بيانات من هذين الجدولين إن لم تكن موجودة مسبقًا في هذا العرض. يحاول الاستعلام التالي استرجاع العمود walker
من العرض walking_schedule
، ولكن سيفشل هذا الاستعلام لأن العرض لا يحتوي على أيّ أعمدة بهذا الاسم:
mysql> SELECT walker FROM walking_schedule;
الخرج ERROR 1054 (42S22): Unknown column 'walker' in 'field list'
يعيد هذا الخرج رسالة خطأ لأن العمود walker
هو جزء من الجدول dogs
، ولكنه غير مُضمَّنٍ في العرض الذي أنشأناه.
يمكنك أيضًا تنفيذ الاستعلامات التي تتضمّن دوالًا تجميعية Aggregate Functions تعالج البيانات ضمن العرض، يستخدم المثال التالي الدالة التجميعية MAX
مع عبارة GROUP BY
للعثور على أطول مسافة يجب على الموظف أن يمشيها في يوم محدّد:
mysql> SELECT emp_name, MAX(walk_distance) AS longest_walks mysql> FROM walking_schedule GROUP BY emp_name;
الخرج +----------+---------------+ | emp_name | longest_walks | +----------+---------------+ | Peter | 5.00 | | Paul | 2.75 | | Mary | 6.50 | +----------+---------------+ 3 rows in set (0.00 sec)
توجد فائدة أخرى للعروض كما ذكرنا سابقًا، وهي أنه يمكنك استخدامها لتقييد وصول مستخدم قاعدة البيانات إلى العرض فقط بدلًا من الوصول إلى الجدول أو قاعدة البيانات بأكملها. لنفترض مثلًا أنك وظّفتَ مدير مكتب لمساعدتك في إدارة الجدول الزمني، وتريد أن يصل إلى معلومات الجدول دون الوصول لأي بيانات أخرى في قاعدة البيانات، حيث يمكنك إنشاء حساب مستخدم جديد له في قاعدة بياناتك كما يلي:
mysql> CREATE USER 'office_mgr'@'localhost' IDENTIFIED BY 'password';
يمكنك بعد ذلك منح هذا المستخدم الجديد صلاحية وصول للقراءة إلى العرض walking_schedule
فقط باستخدام التعليمة GRANT
كما يلي:
mysql> GRANT SELECT ON views_db.walking_schedule to 'office_mgr'@'localhost';
وبالتالي سيتمكّن الشخص الذي لديه صلاحية الوصول إلى حساب مستخدم MySQL الذي هو office_mgr
من تنفيذ استعلامات SELECT
في العرض walking_schedule
فقط.
تغيير وحذف العروض Views
إذا أضفتَ أو غيّرتَ بياناتٍ في أحد الجداول التي نشتق العرض منها، فستُضاف أو تُحدَّث البيانات ذات الصلة في العرض تلقائيًا. نفّذ الأمر INSERT INTO
التالي لإضافة صف آخر إلى الجدول dogs
:
mysql> INSERT INTO dogs VALUES (8, 'Charlie', 2, 3.5, 3, 1);
يمكنك بعد ذلك استرجاع جميع البيانات من العرض walking_schedule
مرة أخرى كما يلي:
mysql> SELECT * FROM walking_schedule;
الخرج +----------+----------+---------------+--------------+--------------+ | emp_name | dog_name | walk_distance | meals_perday | cups_permeal | +----------+----------+---------------+--------------+--------------+ | Peter | Dottie | 5.00 | 3 | 1.00 | | Peter | Otto | 4.50 | 3 | 2.00 | | Peter | Juno | 4.50 | 3 | 2.00 | | Paul | Link | 2.75 | 2 | 0.75 | | Paul | Charlie | 3.50 | 3 | 1.00 | | Mary | Bronx | 6.50 | 3 | 1.25 | | Mary | Harlem | 1.25 | 2 | 0.25 | | Mary | Zephyr | 3.00 | 2 | 1.50 | +----------+----------+---------------+--------------+--------------+ 8 rows in set (0.00 sec)
لاحظ وجود صف آخر في مجموعة نتائج الاستعلام، والذي يمثّل البيانات التي أضفتها إلى الجدول dogs
، ولكن لا يزال العرض يسحب البيانات ذاتها من الجداول الأساسية نفسها، لذلك لم تغيّر هذه العملية العرض.
تسمح لك العديد من أنظمة RDBMS بتحديث هيكل العرض بعد إنشائه باستخدام صيغة CREATE OR REPLACE VIEW
:
mysql> CREATE OR REPLACE VIEW view_name mysql> AS mysql> new SELECT statement
إذا كان العرض الذي اسمه view_name
موجودًا مسبقًا في هذه الصيغة، فسيحدّث نظام قاعدة البيانات هذا العرض بحيث يمثّل البيانات التي تعيدها التعليمة new SELECT statement
. إذا لم يكن العرض بهذا الاسم موجودًا، فسينشئ نظام إدارة قواعد البيانات DBMS عرضًا جديدًا.
لنفترض أنك تريد تغيير العرض walking_schedule
ليسرد إجمالي كمية الطعام التي تناولها كل كلب على مدار اليوم بدلًا من سرد عدد أكواب الطعام التي يتناولها كل كلب في كل وجبة، ويمكنك تغيير العرض باستخدام الأمر التالي:
mysql> CREATE OR REPLACE VIEW walking_schedule mysql> AS mysql> SELECT emp_name, dog_name, walk_distance, meals_perday, (cups_permeal * mysql> meals_perday) AS total_kibble mysql> FROM employees JOIN dogs ON emp_ID = walker;
إذا أجربتَ الآن استعلامًا على هذا العرض، فستمثّل مجموعة النتائج بيانات العرض الجديدة كما يلي:
mysql> SELECT * FROM walking_schedule;
الخرج +----------+----------+---------------+--------------+--------------+ | emp_name | dog_name | walk_distance | meals_perday | total_kibble | +----------+----------+---------------+--------------+--------------+ | Peter | Dottie | 5.00 | 3 | 3.00 | | Peter | Otto | 4.50 | 3 | 6.00 | | Peter | Juno | 4.50 | 3 | 6.00 | | Paul | Link | 2.75 | 2 | 1.50 | | Paul | Charlie | 3.50 | 3 | 3.00 | | Mary | Bronx | 6.50 | 3 | 3.75 | | Mary | Harlem | 1.25 | 2 | 0.50 | | Mary | Zephyr | 3.00 | 2 | 3.00 | +----------+----------+---------------+--------------+--------------+ 8 rows in set (0.00 sec)
يمكنك حذف العروض باستخدام صيغة DROP مثل معظم هياكل البيانات الأخرى التي يمكنك إنشاؤها في لغة SQL، وإليك مثالًا:
DROP VIEW view_name;
يمكنك مثلًا حذف العرض walking_schedule
باستخدام الأمر التالي:
mysql> DROP VIEW walking_schedule;
يؤدي الأمر السابق إلى إزالة العرض walking_schedule
من قاعدة بياناتك، ولكنه لن يحذف أيًّا من بيانات قاعدة بياناتك المتعلقة بالعرض إلّا إذا أزلتها من الجداول الأساسية.
الخلاصة
تعلّمنا في هذا المقال ما هي عروض SQL وكيفية إنشائها والاستعلام عنها وتغييرها وحذفها من قاعدة البيانات، وتعرّفنا على فوائد العروض، وأنشأنا مستخدم MySQL الذي يمكنه فقط قراءة البيانات من العرض التجريبي الذي أنشأناه.
يجب أن تعمل الأوامر الواردة في أمثلة هذا المقال على معظم قواعد البيانات العلاقية، ولكن يجب أن تدرك أن كل قاعدة بيانات SQL لها تقديمها الفريد من هذه اللغة، لذا يجب عليك الرجوع إلى التوثيق الرسمي لنظام إدارة قواعد البيانات DBMS الخاص بك للحصول على وصف أشمل لكل أمر ومجموعته الكاملة من الخيارات.
ننصحك بالاطلاع على سلسلة تعلم SQL في أكاديمية حسوب للمزيد حول كيفية التعامل مع لغة SQL.
ترجمة -وبتصرف- للمقال How To Use Views in SQL لصاحبه Mark Drake.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.