انتقل إلى محتوى الدرس
الدرس 56
دورة MySQL

الإجراءات المخزنة والمعاملات وبنى التحكم في MySQLMySQL Stored Procedures Parameters and Control Flow

تعلّم الإجراءات المخزنة والمعاملات وبنى التحكم في MySQL بأسلوب MySQL 8 الحديث مع أمثلة استعلامات SQL وتطبيقات تفاعلية.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
7
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

الإجراء المخزن (Stored Procedure) في محرك MySQL 8.4 هو وحدة برمجية مسماة تضم سلسلة من أوامر SQL المترابطة، تُحفظ مباشرةً داخل قاموس البيانات (Data Dictionary) على الخادم وتُنفَّذ دفعةً واحدة عند استدعائها بالأمر CALL. بدلاً من إرسال خمسة أو ستة استعلامات منفصلة عبر الشبكة من تطبيق الويب إلى قاعدة البيانات والانتظار بين كل رحلة اتصال (Network Round-Trip)، يرسل التطبيق أمر استدعاء واحد فقط فيتولى خادم MySQL تنفيذ خطوات الفحص والحساب والتحديث داخلياً بسرعة فائقة.

توفر الإجراءات المخزنة ثلاث مزايا هندسية رئيسية في الأنظمة الإنتاجية: أولاً، تقليل زمن انتقال الشبكة عبر دمج العمليات المتعددة في نداء واحد؛ ثانياً، توحيد منطق الأعمال (Business Logic) بحيث تشترك جميع التطبيقات في نفس القواعد الحسابية المعتمدة؛ وثالثاً، تعزيز الأمان الصارم عبر منح حساب التطبيق صلاحية تنفيذ الإجراء (Execution Privilege) دون كشف الجداول الأساسية الحساسة للتعديل المباشر.

الإجراءات المخزنة والمعاملات وبنى التحكم في MySQL

مخطط معماري يوضح بنية الإجراءات المخزنة في MySQL 8.4 وتغيير الفاصل DELIMITER وتمرير المعاملات وبنى التحكم الشرطية والتكرارية.
الإجراءات المخزنة والمعاملات وبنى التحكم في MySQL
الإجراءات المخزنة والمعاملات وبنى التحكم في MySQL
SQL
-- Create and call a basic stored procedure
CREATE PROCEDURE sp_active_customers(IN p_city VARCHAR(50))
BEGIN
    SELECT customer_id, full_name, city, loyalty_points
    FROM customers
    WHERE is_active = 1 AND city = p_city
    ORDER BY loyalty_points DESC;
END;

CALL sp_active_customers('Riyadh');

عند كتابة إجراء مخزن يحتوي على عدة عبارات SQL داخل كتلة BEGIN ... END، تنتهي كل عبارة داخلية بفاصلة منقوطة ;. في الوضع الافتراضي، يفسر عميل سطر الأوامر (MySQL Client) أول فاصلة منقوطة يصادفها على أنها نهاية أمر CREATE PROCEDURE بأكمله، فيرسل نصف الكود إلى الخادم مما يتسبب فوراً في خطأ نحوي (Syntax Error 1064).

لحل هذه المشكلة، نستخدم الأمر DELIMITER $$ (أو DELIMITER //) قبل تعريف الإجراء لتغيير رمز إنهاء الأمر الخارجي مؤقتاً إلى $$. بذلك يمرر العميل جميع الفواصل المنقوطة الداخلية كما هي ضمن نص الإجراء، وعندما يصل إلى END$$ يرسل الإجراء كاملاً للخادم، ثم نعيد الفاصل إلى وضعه الطبيعي بكتابة DELIMITER ;.

SQL
DELIMITER $$
CREATE PROCEDURE sp_archive_summary(IN p_min_points INT)
BEGIN
    UPDATE customers SET tier = 'Gold'
    WHERE loyalty_points >= p_min_points;
    SELECT COUNT(customer_id) AS gold_members
    FROM customers WHERE tier = 'Gold';
END$$
DELIMITER ;

CALL sp_archive_summary(500);

محاكي الإجراءات المخزنة التفاعلي

يدعم محرك MySQL 8.4 ثلاثة أوضاع لتمرير المعاملات إلى الإجراء المخزن: الوضع الافتراضي IN يستقبل قيمة من المستدعي للقراءة فقط ولا تنعكس أي تعديلات تجري عليه خارج الإجراء؛ والوضع OUT يبدأ بقيمة NULL داخل الإجراء ويُستخدم لإرجاع نتيجة محسوبة إلى متغير جلسة (مثل @total)؛ أما الوضع INOUT فيجمع الميزتين معاً حيث يستقبل قيمة ابتدائية من متغير الجلسة، يعدّلها داخل الإجراء، ويعيد القيمة المحدَّثة إلى نفس المتغير.

عند استدعاء إجراء يحتوي على معاملات OUT أو INOUT بواسطة CALL، يجب تمرير متغيرات جلسة مسبوقة بالرمز @ لاستلام القيم المخرجة، ثم قراءتها عبر SELECT @var_name.

SQL
DELIMITER $$
CREATE PROCEDURE sp_apply_bonus(
    IN p_id INT, OUT p_name VARCHAR(60), INOUT p_pts INT
)
BEGIN
    SELECT full_name, loyalty_points + p_pts
    INTO p_name, p_pts FROM customers WHERE customer_id = p_id;
END$$
DELIMITER ;
SET @bonus_pts = 150;
CALL sp_apply_bonus(101, @cust_name, @bonus_pts);
SELECT @cust_name AS customer, @bonus_pts AS new_points;

تُستخدم المتغيرات المحلية (Local Variables) لحفظ القيم المرحلية والحسابات المؤقتة أثناء تنفيذ الإجراء المخزن، وتنتهي صلاحيتها تلقائياً بمجرد الوصول إلى نهاية كتلة BEGIN ... END. على عكس متغيرات الجلسة غير المقيدة بنوع (@var)، تُعرَّف المتغيرات المحلية بأمر DECLARE مع تحديد نوع بيانات صارم (مثل DECIMAL(10,2) أو INT) وقيمة ابتدائية اختيارية عبر DEFAULT.

يفرض محرك MySQL 8.4 قاعدة ترتيب صارمة داخل كل كتلة BEGIN ... END: يجب أن تأتي جميع جمل DECLARE الخاصة بالمتغيرات المحلية في بداية الكتلة مباشرةً قبل أي جملة تنفيذية مثل SET أو SELECT أو UPDATE.

SQL
DELIMITER $$
CREATE PROCEDURE sp_order_tax_summary(IN p_order_id INT)
BEGIN
    DECLARE v_subtotal DECIMAL(10,2) DEFAULT 0.00;
    DECLARE v_tax_rate DECIMAL(4,2) DEFAULT 0.15;
    DECLARE v_final DECIMAL(10,2) DEFAULT 0.00;
    SELECT amount INTO v_subtotal FROM orders WHERE order_id = p_order_id;
    SET v_final = ROUND(v_subtotal * (1 + v_tax_rate), 2);
    SELECT p_order_id AS id, v_subtotal AS net, v_final AS gross;
END$$
DELIMITER ;
CALL sp_order_tax_summary(501);

تتيح الإجراءات المخزنة في MySQL 8.4 كتابة منطق تحكم إجرائي متكامل لا يتوفر في استعلامات SQL المفردة. يمكنك توجيه مسار التنفيذ بين عدة كتل أوامر باستخدام جملة IF ... THEN ... ELSEIF ... ELSE ... END IF; (لاحظ أنها جملة تحكم مستقلة وليست دالة IF(cond, a, b) المضمنة داخل الاستعلامات)، أو عبر جملة CASE الإجرائية.

ولتنفيذ العمليات التكرارية مثل توليد دفعات الأقساط أو معالجة الفترات الزمنية المتسلسلة، يوفر المحرك حلقة WHILE condition DO ... END WHILE; التي تفحص الشرط قبل كل دورة، بالإضافة إلى REPEAT ... UNTIL condition END REPEAT; مع إمكانية الخروج المبكر من الحلقة المسماة بأمر LEAVE أو تخطي الدورة الحالية بأمر ITERATE.

SQL
DELIMITER $$
CREATE PROCEDURE sp_loyalty_tier(
    IN p_points INT, OUT p_tier VARCHAR(20), OUT p_coupons INT
)
BEGIN
    DECLARE v_step INT DEFAULT 0;
    IF p_points >= 800 THEN SET p_tier = 'Platinum';
    ELSEIF p_points >= 400 THEN SET p_tier = 'Gold';
    ELSE SET p_tier = 'Silver'; END IF;
    WHILE v_step < p_points DO SET v_step = v_step + 250; END WHILE;
    SET p_coupons = FLOOR(p_points / 250);
END$$
SQL
-- Inspect and safely drop stored procedures
SHOW PROCEDURE STATUS LIKE 'sp_%';

SHOW CREATE PROCEDURE sp_loyalty_tier;

DROP PROCEDURE IF EXISTS sp_archive_summary;

يُلخص الجدول المرجعي التالي أهم أوامر وبنى الإجراءات المخزنة في MySQL 8.4 ومقارنة المعاملات والمتغيرات وبنى التحكم:

العنصر / الأمرالصيغة القياسية في MySQL 8.4الوظيفة والقاعدة الهندسية
إنشاء واستدعاءCREATE PROCEDURE ... / CALL sp_name(args)حفظ منطق SQL مركب على الخادم وتنفيذه بنداء شبكي واحد.
معامل ININ p_id INTقيمة إدخال للقراءة فقط (الوضع الافتراضي عند عدم ذكر النوع).
معاملا OUT وINOUTOUT p_res DECIMAL(10,2), INOUT p_cnt INTإرجاع مخرجات محسوبة إلى متغيرات الجلسة @var الممررة في CALL.
المتغيرات المحليةDECLARE v_total DECIMAL(10,2) DEFAULT 0.00;تُعرَّف في مطلع كتلة BEGIN...END قبل أي أمر تنفيذي وتنتهي بنهايتها.
بنى التحكم والفحصIF...END IF / WHILE...END WHILE / DROP PROCEDUREالتفرع الشرطي والحلقات التكرارية وإدارة دورة حياة الإجراء بأمان.
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

أتقنت في هذا الدرس إنشاء الإجراءات المخزنة بـ CREATE PROCEDURE، وضبط فاصل العميل DELIMITER، وتمرير معاملات IN وOUT وINOUT عبر CALL، وتعريف المتغيرات المحلية بـ DECLARE، وبناء الشروط IF والحلقات WHILE، وفحص الإجراءات وحذفها بأمان.

الخطوة التالية والدرس القادم

في الدرس القادم سنتعلم كيفية إنشاء الدوال المخزنة (Stored Functions) بـ CREATE FUNCTION ومفهوم التنفيذ الحتمي DETERMINISTIC واستدعائها مباشرةً داخل جمل SELECT.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Stored Procedure الإجراء المخزن (Stored Procedure)
وحدة برمجية مسماة تُحفظ داخل قاموس بيانات MySQL وتُستدعى بالأمر CALL لتنفيذ سلسلة أوامر SQL مترابطة على الخادم.
للمراجعة
02 DELIMITER Directive توجيه الفاصل (DELIMITER)
أمر خاص بواجهة عميل MySQL يغيّر رمز إنهاء الأوامر مؤقتاً لإرسال جسم الإجراء المخزن كاملاً دفعةً واحدة دون تقطيع عند الفواصل المنقوطة.
للمراجعة
03 IN / OUT / INOUT Parameters معاملات الإدخال والإخراج (IN / OUT / INOUT)
أنماط تمرير المعاملات في الإجراء المخزن لتحديد ما إذا كان المعامل للقراءة فقط أو لإرجاع مخرجات لمتغير جلسة أو لكليهما معاً.
للمراجعة
04 Local Variable (DECLARE) المتغير المحلي (DECLARE)
متغير ذو نوع بيانات محدد يُصرَّح عنه في بداية كتلة BEGIN...END لحفظ الحسابات المرحلية وينتهي وجوده بانتهاء الكتلة.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات2

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 2 مفهومةأول بطاقة، أول خطوة
01 SP SP
Stored Procedure
اختصار الإجراء المخزن المحفوظ داخل قاموس بيانات الخادم لتنفيذ العمليات المتعددة
للمراجعة
02 INOUT INOUT
Input Output Parameter
نمط معامل ثنائي الاتجاه يستقبل قيمة ابتدائية ويعيد القيمة المعدلة لمتغير الجلسة
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. اكتب إجراءً مخزناً باستخدام DELIMITER $$ يضم معامل إدخال IN ومعامل إخراج OUT، ثم نفّذه بالأمر CALL واعرض قيمة متغير الجلسة.

  2. بدّل بين السيناريوهات الثلاثة في المحاكي التفاعلي للإجراءات المخزنة وافحص صيغة الأوامر ومخرجاتها.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

4أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي4 أسئلة تنتظرك
01

ما الأمر المخصص لتشغيل وتنفيذ الإجراء المخزن في MySQL 8.4؟

اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.

02

لماذا نستخدم الأمر DELIMITER $$ قبل تعريف إجراء مخزن متعدد الأوامر في عميل سطر أوامر MySQL؟

اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.

03

أين يجب وضع جمل DECLARE الخاصة بتعريف المتغيرات المحلية داخل كتلة BEGIN...END؟

اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.

04

أي نمط من أنماط المعاملات يستقبل قيمة ابتدائية من متغير جلسة ثم يعيد القيمة المحدَّثة إلى نفس المتغير بعد انتهاء الإجراء؟

اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.