في هذا الدرس 6تصفّح المواضيع
الإجراء المخزن (Stored Procedure) في محرك MySQL 8.4 هو وحدة برمجية مسماة تضم سلسلة من أوامر SQL المترابطة، تُحفظ مباشرةً داخل قاموس البيانات (Data Dictionary) على الخادم وتُنفَّذ دفعةً واحدة عند استدعائها بالأمر CALL. بدلاً من إرسال خمسة أو ستة استعلامات منفصلة عبر الشبكة من تطبيق الويب إلى قاعدة البيانات والانتظار بين كل رحلة اتصال (Network Round-Trip)، يرسل التطبيق أمر استدعاء واحد فقط فيتولى خادم MySQL تنفيذ خطوات الفحص والحساب والتحديث داخلياً بسرعة فائقة.
توفر الإجراءات المخزنة ثلاث مزايا هندسية رئيسية في الأنظمة الإنتاجية: أولاً، تقليل زمن انتقال الشبكة عبر دمج العمليات المتعددة في نداء واحد؛ ثانياً، توحيد منطق الأعمال (Business Logic) بحيث تشترك جميع التطبيقات في نفس القواعد الحسابية المعتمدة؛ وثالثاً، تعزيز الأمان الصارم عبر منح حساب التطبيق صلاحية تنفيذ الإجراء (Execution Privilege) دون كشف الجداول الأساسية الحساسة للتعديل المباشر.
الإجراءات المخزنة والمعاملات وبنى التحكم في MySQL
-- 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 ;.
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.
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.
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.
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$$
-- 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 مركب على الخادم وتنفيذه بنداء شبكي واحد. |
معامل IN | IN p_id INT | قيمة إدخال للقراءة فقط (الوضع الافتراضي عند عدم ذكر النوع). |
معاملا OUT وINOUT | OUT 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
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 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
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 SP SP
- Stored Procedure
- اختصار الإجراء المخزن المحفوظ داخل قاموس بيانات الخادم لتنفيذ العمليات المتعددة
- للمراجعة
- 02 INOUT INOUT
- Input Output Parameter
- نمط معامل ثنائي الاتجاه يستقبل قيمة ابتدائية ويعيد القيمة المعدلة لمتغير الجلسة
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
اكتب إجراءً مخزناً باستخدام DELIMITER $$ يضم معامل إدخال IN ومعامل إخراج OUT، ثم نفّذه بالأمر CALL واعرض قيمة متغير الجلسة.
-
بدّل بين السيناريوهات الثلاثة في المحاكي التفاعلي للإجراءات المخزنة وافحص صيغة الأوامر ومخرجاتها.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي4 أسئلة تنتظرك +
ما الأمر المخصص لتشغيل وتنفيذ الإجراء المخزن في MySQL 8.4؟
اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.
لماذا نستخدم الأمر DELIMITER $$ قبل تعريف إجراء مخزن متعدد الأوامر في عميل سطر أوامر MySQL؟
اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.
أين يجب وضع جمل DECLARE الخاصة بتعريف المتغيرات المحلية داخل كتلة BEGIN...END؟
اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.
أي نمط من أنماط المعاملات يستقبل قيمة ابتدائية من متغير جلسة ثم يعيد القيمة المحدَّثة إلى نفس المتغير بعد انتهاء الإجراء؟
اختر الإجابة الأدق وفق قواعد محرك MySQL 8.4.