لماذا يهمّ تنسيق SQL
استعلام SQL مكتوب على سطر واحد طويل قد يعمل بكفاءة تامّة، لكنّه يكلّفك ساعات حين تحاول قراءته بعد ستّة أشهر، أو حين يحاول زميل مراجعته في Pull Request. التنسيق ليس ترفاً جمالياً؛ هو أداة هندسية تقلّل الأخطاء، تُسرّع المراجعات، وتجعل الفروقات في Git قابلة للقراءة سطراً سطراً.
في هذا الدليل نمرّ على ما يجعل استعلام SQL «نظيفاً»: قواعد المسافات والمحاذاة، اختيار حالة الكلمات المفتاحية، تسمية الجداول والأعمدة، وكيف يرتبط كلّ ذلك بالأداء فعلياً — لا بمظهر الشيفرة فقط.
قواعد التنسيق الأساسية
هناك ثلاث قواعد متّفق عليها في معظم أدلّة أسلوب SQL الحديثة (مثل دليل Mozilla ودليل GitLab الداخلي):
- ضع كلّ بند رئيسي على سطر مستقلّ:
SELECT،FROM،JOIN،WHERE،GROUP BY،HAVING،ORDER BY،LIMIT. - حاذِ الأعمدة في
SELECTرأسياً حين تتجاوز ثلاثة أعمدة. السطر الواحد جيّد لاستعلام بسيط؛ الاستعلام التحليلي يحتاج عموداً لكلّ سطر. - استخدم اسماء أعمدة صريحة بدل
SELECT *. النجمة تُكسر في أوّل مرّة يُضاف فيها عمود جديد، وتُربك الفهارس وتنقل بيانات لا تحتاجها فعلاً.
أمّا الكلمات المفتاحية، فالخلاف بين UPPERCASE و lowercase قديم. القاعدة العمليّة: اختر واحدة والتزم بها في المشروع كلّه. الأدوات الحديثة مثل sql-formatter (الذي تستخدمه أداتنا أعلاه) تفرض الاتساق بنقرة واحدة.
الفروقات بين اللهجات
SQL ليس لغة واحدة. ما يعمل في PostgreSQL قد يكسر في MySQL، وما تكتبه لـ T-SQL في Microsoft SQL Server قد يحتاج تعديلاً جذرياً ليعمل في Oracle. أبرز الفروقات:
- تحديد عدد الصفوف: PostgreSQL و MySQL يستخدمان
LIMIT 10؛ T-SQL يستخدمTOP 10؛ Oracle يستخدمFETCH FIRST 10 ROWS ONLY. - اقتباس المعرّفات: PostgreSQL يقبل علامتي الاقتباس المزدوجتين؛ MySQL يستخدم backticks افتراضياً؛ T-SQL يستخدم القوسين المربعين
[column]. - دوال التاريخ:
NOW()في PostgreSQL و MySQL،GETDATE()في T-SQL،SYSDATEفي Oracle. - التسلسلات الرقمية:
AUTO_INCREMENTفي MySQL،SERIALأوIDENTITYفي PostgreSQL،SEQUENCEفي Oracle.
عند نقل استعلام بين لهجات، نسّقه أوّلاً ثم راجع كلّ بند يدوياً. أداتنا تدعم ثماني لهجات لتساعدك على رؤية كيف تبدو الشيفرة في كلّ واحدة منها.
التنسيق وأثره على الأداء
المسافات والأسطر الجديدة لا تؤثّر على خطّة التنفيذ (Execution Plan) إطلاقاً. محسّن الاستعلامات يتجاهلها قبل أن يبدأ عمله. لكن التنسيق الجيّد يكشف مشاكل أداء كانت مخفيّة في السطر الطويل:
- JOIN ضمنيّ خطير: حين ترى
FROM users, orders WHERE ...بدلJOIN ... ON، ذلك جدول ضرب (Cartesian) محتمل. التنسيق يجعل الفرق واضحاً فوراً. - دوال على أعمدة مفهرسة:
WHERE UPPER(email) = ...يُلغي الفهرس علىemail. التنسيق يُبرز الدوال في الأماكن غير المتوقّعة. - استعلامات فرعية مكرّرة: نفس الـ subquery يظهر مرّتين أو ثلاث؟ ربّما يحتاج
CTE(WITH clause) واحد بدل ثلاث رحلات للجدول.
CTE مقابل Subquery: متى تستخدم أيّاً
عبارات WITH (Common Table Expressions) أحدثت ثورة هادئة في قراءة SQL. بدل عشّ subqueries عميق، تكتب كلّ خطوة باسمها ثمّ تبني عليها:
WITH active_users AS ( SELECT id, name FROM users WHERE status = 'active' ), recent_orders AS ( SELECT user_id, COUNT(*) AS orders_count FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '30 days' GROUP BY user_id ) SELECT u.name, COALESCE(o.orders_count, 0) AS orders_30d FROM active_users u LEFT JOIN recent_orders o ON o.user_id = u.id ORDER BY orders_30d DESC LIMIT 50;
نفس الاستعلام بـ subqueries متداخلة يصبح كتلة واحدة صعبة القراءة. القاعدة: إذا تكرّر subquery مرّتين أو زاد عمق التداخل عن مستويين، حوّله إلى CTE.
تسمية الجداول والأعمدة
أسماء واضحة تختصر التعليقات وتجعل التنسيق يبدو أنظف. القواعد المتعارف عليها:
- أسماء الجداول جمع وصغيرة:
usersلاUserأوtbl_users. - أسماء الأعمدة مفردة وصغيرة مع
snake_case:created_atلاCreatedAtأوcreatedat. - الأعمدة المرجعية بصيغة
<table>_id:user_id،order_id. - تواريخ بـ
_at(لحظات) أو_on(تواريخ فقط):created_at،birth_on.
ملاحظة أمنية: لا تُنسّق فقط، تحقّق
أدوات التنسيق — بما فيها أداتنا — لا تتحقّق من الأمان. أهمّ ثغرة في تطبيقات SQL ما زالت SQL Injection. القاعدة الذهبية: لا تبنِ استعلاماً بدمج سلاسل نصّية من المستخدم أبداً. استخدم parameterized queries أو prepared statements دائماً، في كلّ لغة وكلّ مكتبة. التنسيق يساعدك في القراءة؛ Parameter binding يحميك من الاختراق.
خلاصة
استعلام SQL منسّق جيّداً يُقرأ مرّة ويُكتب مرّات. القواعد بسيطة: بنود رئيسية على أسطر منفصلة، حالة موحّدة للكلمات المفتاحية، أسماء واضحة، CTE بدل subqueries المتداخلة، و parameter binding دائماً. أداتنا أعلاه تتكفّل بالتنسيق نفسه عبر ثماني لهجات، بشكل محليّ داخل متصفّحك — استعلاماتك لا تُرسَل لأيّ خادم.
فرض الأسلوب آلياً: SQL في CI
أفضل دليل أسلوب لا يَنفع إن لم يُفرَض. الحلّ: شغّل linter لـ SQL في كلّ Pull Request. SQLFluff هو المعيار الفعليّ اليوم — مكتوب بـ Python، يَدعم 14 لهجة (PostgreSQL، MySQL، BigQuery، Snowflake، Redshift، SQL Server، Oracle، DuckDB، وغيرها)، ويُمكن إعداده عبر ملفّ .sqlfluff في جذر المشروع. أمر واحد (sqlfluff fix .) يُعيد تنسيق كلّ ملفّات SQL في المستودع.
داخل GitHub Actions، يكفي خطوتان: pip install sqlfluffثمّ sqlfluff lint --dialect postgres ./sql/. أيّ مخالفة توقف CI وتمنع الدمج. النتيجة: المستودع كلّه يتبع نفس الأسلوب بعد أسابيع قليلة، ومراجعات Pull Requests تركّز على المنطق بدل الجدال حول المسافات. مشاريع dbt الحديثة تَستخدم نفس النمط عبر dbt-checkpoint و dbt-osmosisلتطبيق قواعد على نماذج البيانات.
إن كان فريقك على VS Code، أضِف إضافة SQLTools معvscode-sqlfluff ليرى المطوّر التحذيرات لحظيّاً أثناء الكتابة. تجربة المطوّر العربيّ تتحسّن كذلك: محرّر RTL يَدعم تعليقات عربيّة داخل الاستعلام (-- شرح بالعربيّة) بدون كسر التحليل، لأنّ SQL يَعتبر كلّ شيء بعد --نصّاً حرّاً حتّى نهاية السطر.
أدوات ذات صلة
أدوات أخرى مجانية على ArabToolBox، كلها تعمل في متصفّحك بدون تسجيل.
- محوّل Excel ↔ CSV ↔ JSONحوّل بين Excel، CSV، JSON بدقة + دعم العربية
- منسّق JSONتنسيق وتحقق JSON مع مقارنة Diff وتحويل لـ CSV/YAML
- محوّل YAML ↔ JSON ↔ TOMLتحويل بين صيغ الإعدادات الثلاث + تحقق فوري
- اختبار Regexاختبر Regex على نصوص عربية وإنجليزية — مع شرح
- Base64 ترميز وفكترميز وفك Base64 — نصوص، صور، ملفات — محلياً 100%
- ترميز URLترميز URL مع دعم كامل للأحرف العربية + Query Strings