MySQL التعبيرات النمطية (Regexp)
⚡ ملخص ذكي
MySQL تُطابق التعابير النمطية (REGEXP) قيم الأعمدة مع أنماط مرنة لا يمكن للأحرف البديلة التعبير عنها. يشرح هذا بناء جملة REGEXP، ومرادف RLIKE، وكل حرف خاص مدعوم، وأمثلة استعلام مصححة على قاعدة بيانات myflixdb، ووظائف التعبير النمطي المضافة في MySQL 8.0.

ما هي MySQL التعبيرات النمطية؟
MySQL تعبيرات منتظمة تساعدك هذه الطريقة في البحث عن البيانات التي تطابق معايير معقدة. التعبير النمطي هو نمط يصف شكل القيمة التي تبحث عنها، وليس القيمة نفسها.
إذا كنت قد عملت بالفعل مع MySQL البدلقد تتساءل عن جدوى تعلم التعابير النمطية في حين أن دالة LIKE تُنتج نتائج مماثلة. والجواب هو قوة التعبير: فالأحرف البديلة لا تُتيح سوى رمزين، بينما تصف التعابير النمطية نطاقات الأحرف، والبدائل، والتكرار، ومواقع الكلمات في نمط واحد.
بعد تحديد الهدف، يقدم القسم التالي الصيغة التي ستستخدمها في كل استعلام REGEXP.
الصيغة الأساسية للتعبير النمطي (REGEXP)
الصيغة الأساسية للتعبير النمطي هي كما يلي.
SELECT * FROM table_name WHERE fieldname REGEXP 'pattern';
هنا:
- "عبارة SELECT" هو المعيار اختيار البيان.
- "أين اسم الحقل" هو اسم العمود الذي يتم تطبيق التعبير النمطي عليه.
- "نمط REGEXP" — REGEXP هو عامل التعبير النمطي، و'pattern' يمثل النمط المراد مطابقته. RLIKE هو مرادف لـ REGEXP ويعيد نفس النتائج. ولتجنب الخلط بينه وبين عامل التشغيل LIKE، يُفضّل استخدام REGEXP.
لنلقِ نظرة الآن على مثال عملي.
SELECT * FROM `movies` WHERE `title` REGEXP 'code';
يبحث الاستعلام أعلاه عن جميع عناوين الأفلام التي تحتوي على كلمة "code". لا يهم مكان ظهور كلمة "code" في العنوان، سواء في بدايته أو وسطه أو نهايته. طالما أن العنوان يحتوي على هذا النمط، فسيتم إرجاع السطر المطلوب.
مطابقة بداية القيمة مع قائمة الأحرف
لنفترض أننا نريد الأفلام التي تبدأ عناوينها بالحروف أ، ب، ج، أو د، متبوعة بأي عدد من الأحرف الأخرى. نجمع قائمة الأحرف مع رمز الإقحام (caret) لتحقيق هذه النتيجة.
SELECT * FROM `movies` WHERE `title` REGEXP '^[abcd]';
تنفيذ البرنامج النصي أعلاه في MySQL طاولة العمل مقارنة قاعدة بيانات myflixdb تعطينا النتائج التالية.
| movie_id | الاسم | مدير | year_released | معرف الفئة |
|---|---|---|---|---|
| 4 | Code الاسم: بلاك | إدغار جيمز | 2010 | اغية |
| 5 | بنات أبي الصغيرات | اغية | 2007 | 8 |
| 6 | الملائكة والشياطين | اغية | 2007 | 6 |
| 7 | دافينشي Code | اغية | 2007 | 6 |
في النمط '^[abcd]'، يتطلب رمز الإقحام (^) أن تبدأ المطابقة من بداية القيمة، وقائمة الأحرف [abcd] تقبل فقط العناوين التي يبدأ حرفها الأول بـ a أو b أو c أو d. المقارنة غير حساسة لحالة الأحرف في ظل الترتيب الافتراضي، ولهذا السبب "Code تم إرجاع اسم "أسود".
باستثناء الأحرف ذات قائمة الأحرف المنفية
لنقم الآن بتعديل البرنامج النصي وننفي قائمة الأحرف لنرى أي الصفوف يتم إرجاعها.
SELECT * FROM `movies` WHERE `title` REGEXP '^[^abcd]';
تنفيذ البرنامج النصي أعلاه في MySQL يعطينا برنامج Workbench على قاعدة بيانات myflixdb النتائج التالية.
| movie_id | الاسم | مدير | year_released | معرف الفئة |
|---|---|---|---|---|
| 1 | قراصنة الكاريبي 4 | روب مارشال | 2011 | 1 |
| 2 | نسيان سارة مارشال | نيكولاس ستولر | 2008 | 2 |
| 3 | X رجال | 2008 | ||
| 9 | Honey moonالمتطلبات البيئية | جون شولتز | 2005 | 8 |
| 16 | 67% مذنب | 2012 | ||
| 17 | الديكتاتور العظيم | تشالي تشابلي | 1920 | 7 |
| 18 | فيلم تجريبي | مجهول | 8 | |
| 19 | فيلم 3 | جون براون | 1920 | 8 |
داخل قائمة الأحرف، يتغير معنى علامة الإقحام: لا يزال الرمز '^[^abcd]' يثبت التطابق في البداية، بينما يستبعد الرمز [^abcd] الآن كل عنوان يبدأ بأحد الأحرف المضمنة.
يستخدم هذان المثالان فقط نقاط الارتكاز وقوائم الأحرف. أما القسم التالي فيغطي مجموعة الأحرف الوصفية الكاملة.
أحرف التعبير العادية
تُظهر الأمثلة أعلاه أبسط شكل للتعبير النمطي. تسمح لك الأحرف الخاصة بضبط البحث عن الأنماط بدقة: فهي تُعبّر عن التكرار والبدائل والنطاقات والمواضع. يسرد الجدول أدناه كل حرف خاص مدعوم من قِبل MySQL عامل REGEXP، مع مثال مصحح لكل منهما.
| فحم | الوصف | مثال | |
|---|---|---|---|
| * | استخدم النجمة (*) يطابق صفر (0) أو أكثر من حالات شخصية واحدة الذي يسبقه. | اختر * من الأفلام حيث العنوان REGEXP 'da*'؛ يطابق الحرف "d" متبوعًا بصفر أو أكثر من الأحرف "a"، لذا Da Vinci Code وتستوفي بنات أبي الصغيرات الشروط. استخدم "da+" عندما يكون الحرف "a" موجودًا بالفعل. | |
| + | استخدم زائد (+) يطابق حالة واحدة أو أكثر من حالات الحرف الذي يسبقه. | حدد * من "الأفلام" حيث "العنوان" REGEXP "mon+"؛ يعرض جميع الأفلام التي تحتوي على كلمة "mon" متبوعة بحرف "n" واحد أو أكثر. على سبيل المثال، فيلم "ملائكة وشياطين". | |
| ? | استخدم علامة استفهام (؟) يطابق صفر (0) أو حالة واحدة من الحرف الذي يسبقه. | SELECT * FROM `categories` WHERE `category_name` REGEXP 'com?'; يطابق الحرف "co" مع حرف "m" اختياري. على سبيل المثال، كوميديا وكوميديا رومانسية. | |
| . | استخدم نقطة (.) يطابق أي حرف واحد باستثناء سطر جديد. | اختر * من الأفلام حيث `year_released` REGEXP '200.'; يعرض جميع الأفلام التي صدرت في سنة تبدأ برقم "200" متبوعًا بأي حرف. على سبيل المثال، 2005، 2007، 2008. | |
| [اي بي سي] | استخدم قائمة الأحرف [abc] يطابق أيًا من الأحرف المرفقة. | حدد * من "الأفلام" حيث "العنوان" REGEXP "[vwxyz]"؛ يعرض جميع الأفلام التي تحتوي على أي شخصية من "vwxyz". على سبيل المثال، X-Men و Da Vinci Code. | |
| [^ أبك] | استخدم القائمة المنفية [^abc] يطابق أي حرف باستثناء الأحرف المضمنة. | حدد * من "الأفلام" حيث "العنوان" REGEXP '^[^vwxyz]'؛ يعرض جميع الأفلام التي لا يبدأ عنوانها بحرف في "vwxyz". | |
| [من الألف إلى الياء] | استخدم النطاق [AZ] يطابق أي حرف كبير. | حدد * من "الأعضاء" حيث "العنوان_البريدي" REGEXP '[AZ]'؛ يُمنح هذا العرض لجميع الأعضاء الذين يحتوي عنوانهم البريدي على حرف بين A و Z. على سبيل المثال، جانيت جونز برقم العضوية 1. | |
| [az] | استخدم المدى [az] يطابق أي حرف صغير. | حدد * من "الأعضاء" حيث "العنوان_البريدي" REGEXP '[az]'؛ يُظهر هذا التقرير جميع الأعضاء الذين يحتوي عنوانهم البريدي على حرف بين الحرفين a و z. لاحظ أن الترتيب الافتراضي غير حساس لحالة الأحرف، لذا فإن هذا النطاق يطابق الأحرف الكبيرة أيضًا. | |
| [0-9] | استخدم النطاق [0-9] يطابق أي رقم من 0 إلى 9. | SELECT * FROM `members` WHERE `contact_number` REGEXP '[0-9]'; يُدرج جميع الأعضاء الذين يحتوي رقم هاتفهم على رقم واحد على الأقل. على سبيل المثال، روبرت فيل. | |
| ^ | استخدم علامة الإقحام (^) يربط التطابق ببداية القيمة. | حدد * من "الأفلام" حيث "العنوان" REGEXP '^[cd]'؛ يعرض جميع الأفلام التي يبدأ عنوانها بالحرف "c" أو "d". على سبيل المثال، Code نيم بلاك، بنات أبي الصغيرات، ودافنشي Code. | |
| $ | استخدم علامة الدولار ($) يربط التطابق بنهاية القيمة. | SELECT * FROM `movies` WHERE `title` REGEXP 'code$'; يعرض جميع الأفلام التي ينتهي عنوانها بكلمة "code". على سبيل المثال، دافنشي Code. | |
| | | استخدم شريط عمودي (|) يعزل البدائل. | حدد * من "الأفلام" حيث "العنوان" REGEXP '^[cd]|^[u]'; يعرض جميع الأفلام التي تبدأ عناوينها بالحروف "c" أو "d" أو "u". على سبيل المثال، Code الاسم: بلاك، دافنشي Codeوعالم الجريمة السفلي Awakenجي. | |
| \b | استخدم حدود الكلمات (\b) يطابق بداية أو نهاية الكلمة. وهو يحل محل العلامتين القديمتين [[:<:]] و [[:>:]]، اللتين MySQL تمت إزالة الإصدار 8.0. | SELECT * FROM `movies` WHERE `title` REGEXP '\\bfor'; يعرض جميع الأفلام التي تبدأ كلماتها بـ "for". على سبيل المثال، فيلم Forgetting Sarah Marshal. MySQL 5.7 النمط المكافئ هو '[[:<:]]for'. | |
| [[:فصل:]] | استخدم فئة الأحرف يُطابق مجموعة مُسماة من الأحرف: [[:alpha:]] للأحرف، [[:space:]] للمسافات البيضاء، [[:punct:]] لعلامات الترقيم، و[[:upper:]] للأحرف الكبيرة. لاحظ مضاعفة أقواس مربعة. | SELECT * FROM `movies` WHERE `title` REGEXP '^[[:alpha:][:space:]]+$'; يعرض هذا التقرير جميع الأفلام التي تحتوي عناوينها على أحرف ومسافات فقط. على سبيل المثال، فيلم "نسيان سارة مارشال"، بينما تم استبعاد فيلم "قراصنة الكاريبي 4" بسبب وجود رقم. | |
علامة الخط المائل العكسي (\) هي رمز الهروب. لأن MySQL يقوم بتحليل السلسلة أولاً ثم النمط ثانياً، ويجب كتابة الشرطة المائلة العكسية الحرفية كشرطة مائلة عكسية مزدوجة (\\) داخل نمط REGEXP.
⚠️ تحذير بشأن الإصدار: MySQL استبدل الإصدار 8.0.4 محرك التعبيرات النمطية القديم بمكتبة ICU. تمت إزالة علامات الكلمات [[:<:]] و [[:>:]] في هذا الإصدار، لذا فإن الأنماط المنسوخة من مواد أقدم تفشل مع ظهور "خطأ في بناء الجملة". MySQL 8.0. استخدم \b بدلاً من ذلك.
الآن وقد تم تعريف كل حرف خاص، يتبادر إلى الذهن سؤال وجيه: متى يجب أن يحل التعبير النمطي محل عامل التشغيل LIKE الأبسط؟
REGEXP مقابل LIKE: أيهما يجب عليك استخدامه؟
كلا المعاملين يُصفّيان الصفوف حسب النمط، لكنهما يحلان مشكلات مختلفة. يفهم LIKE رمزين فقط، بينما يفهم REGEXP مجموعة الأحرف الخاصة الكاملة الموضحة أعلاه. هذه القدرة لها ثمن، لذا فإن الاختيار بينهما هو مفاضلة وليس تفضيلاً.
| معيار | LIKE | REGEXP |
|---|---|---|
| رموز الأنماط | % و _ فقط | Anchors، النطاقات، التناوب، المحددات الكمية، فئات الأحرف |
| الاستخدام النموذجي | عمليات البحث باستخدام البادئات واللواحق و"يحتوي على" | التحقق، البدائل المتعددة، المطابقة الواعية بالموقع |
| استخدام الفهرس | ممكن عندما لا يبدأ النمط بعلامة النسبة المئوية (%). | لا يستخدم فهرسًا أبدًا |
| قيمة الإرجاع | صحيحة أو خاطئة | 1 أو 0، وNULL عندما يكون أي من المعاملين NULL |
اختر دالة LIKE للمطابقة المباشرة، لأنها سهلة القراءة ويمكن استخدام الفهرس معها. اختر دالة REGEXP عندما يتطلب نمط واحد التعبير عن عدة قواعد في آن واحد، مثل "يبدأ بالحرف c أو d وينتهي برقم". في الجداول الكبيرة، قلّص عدد الصفوف أولاً باستخدام شرط مفهرس، ثم طبّق دالة REGEXP على هذه المجموعة الأصغر.
MySQL 8.0 دوال التعبير النمطي
لا يجيب عامل REGEXP إلا على سؤال واحد: هل تتطابق القيمة مع النمط؟ MySQL أضاف الإصدار 8.0 أربع وظائف تتجاوز ذلك وتتيح لك تحديد المواقع، على سبيل المثالtract، وإعادة كتابة النص المطابق. يقبل كل منهما وسيطاً اختيارياً match_type، حيث يفرض 'c' مقارنة حساسة لحالة الأحرف، بينما يفرض 'i' مقارنة غير حساسة لحالة الأحرف.
- REGEXP_LIKE(expr, pattern) تُرجع الدالة القيمة 1 عندما تتطابق القيمة مع النمط. وهي الصيغة الوظيفية لمعامل REGEXP، ويُحدد الوسيط match_type حساسية حالة الأحرف بشكل صريح.
- REGEXP_INSTR(expr, pattern) تُرجع موضع الحرف الأول من التطابق، أو 0 عندما لا يتم العثور على النمط.
- REGEXP_SUBSTR(expr, pattern) يقوم بإرجاع السلسلة الفرعية المطابقة نفسها، وهو أمر مفيد لاستخراج سنة أو رمز أو رقم من قيمة نصية أطول.
- REGEXP_REPLACE(expr, pattern, replacement) تُعيد القيمة مع استبدال كل تطابق، لذا يمكنها تنظيف البيانات داخل استعلام تحديث SQL.
SELECT title, REGEXP_SUBSTR(title, '[0-9]+') AS number_in_title FROM `movies` WHERE REGEXP_LIKE(title, '[0-9]');
يُعيد الاستعلام أعلاه جميع عناوين الأفلام التي تحتوي على رقم، بالإضافة إلى الأرقام نفسها. MySQL 5.7 هذه الوظائف غير متاحة، لذا يظل عامل REGEXP هو الخيار الوحيد.
