دليل تنسيق SQL: أفضل ممارسات تنسيق الاستعلامات لعام 2026
دليل تنسيق SQL هو مجموعة من الاصطلاحات التي تجعل الاستعلامات سهلة القراءة وتُبقي فروقات (diffs) الفريق متّسقة. لغة SQL نفسها لا تكترث: الكلمات المفتاحية غير حساسة لحالة الأحرف، والمسافات البيضاء يُتجاهَل وجودها، لذا فإن SELECT وselect وSeLeCt تُنفَّذ كلها بالطريقة نفسها، واستعلام مكتوب في سطر واحد من 200 حرف يُعيد الصفوف ذاتها تمامًا التي يعيدها الاستعلام نفسه موزّعًا على عشرين سطرًا مزاحًا. التنسيق إذن يخصّ البشر الذين سيقرؤون الاستعلام لاحقًا، لا غير.
إن كنت تحتاج فقط إلى استعلام نظيف الآن، فالصقه في SQL منسّق، اختر لهجتك، وانسخ النتيجة. لكن فهم القواعد الكامنة وراء هذا الناتج هو ما يتيح لك وضع معيار للفريق بدل التجادل حوله في كل طلب دمج (pull request). يستعرض هذا الدليل الخيارات المهمة: حالة الكلمات المفتاحية، المسافات البادئة وفواصل الأسطر، التسمية، خصوصيات كل لهجة، وكيفية أتمتة العملية بأكملها.
يستحقّ مبدأ واحد التوضيح قبل الدخول في التفاصيل. لأن SQL تتجاهل المسافات البيضاء وحالة الأحرف، فلا قاعدة من هذه القواعد تفرضها قاعدة البيانات؛ إنها موجودة لخدمة البشر الذين يقرؤون الاستعلام ويراجعونه ويصونونه. ولهذا نادرًا ما توجد إجابة «صحيحة» واحدة؛ فمعظم هذه القرارات تدور حول اختيار اصطلاح معقول وتطبيقه في كل مكان، وهذا الدليل صريح بشأن مواضع المفاضلات الحقيقية بدل التظاهر بأن أسلوبًا واحدًا يتفوّق دائمًا. ولأن القواعد اصطلاحات لا متطلبات، فإنها لا تُقدِّم قيمتها إلا حين تُطبَّق باتساق، ولهذا ينتهي كل قسم إلى الخلاصة نفسها: قرّر مرة واحدة، ثم دع أداةً تفرض القرار.
لماذا يهمّ تنسيق SQL
أوضح حجة لصالح التنسيق تظهر في مراجعة الكود. كثيرًا ما يُخرِج أداة الربط الكائني-العلائقي (ORM) أو خطوة بناء الاستعلامات في سطر واحد متّصل:
select u.id,u.name,count(o.id) as orders from users u left join orders o on o.user_id=u.id where u.active=true group by u.id,u.name order by orders desc
لا أحد يستطيع مراجعة ذلك. وبعد إعادة التنسيق، تصبح البنية واضحة ويمكن مراجعة الفرق سطرًا سطرًا:
SELECT
u.id,
u.name,
COUNT(o.id) AS orders
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.active = true
GROUP BY u.id, u.name
ORDER BY orders DESC;
ويستفيد التنقيح (debugging) بالقدر نفسه. حين تنسخ استعلامًا من سطر واحد من سجل الاستعلامات البطيئة وفيه ثلاث عمليات ضمّ (joins) وشرط WHERE متشابك، فإن تنسيقه أولًا يحوّل سؤال «أين الخلل؟» إلى تفحّص لا يتجاوز ثلاثين ثانية. يصبح المُسنَد (predicate) المعطوب في سطره الخاص، وتتراكم عمليات الضمّ، ويظهر فجأةً ضربٌ ديكارتي (Cartesian product) عرَضي أو مرشّحٌ منسيّ بدل أن يبقى مدفونًا في جدارٍ من النصّ. وتنفع الطريقة نفسها حين تقرأ SQL ولّده نظام آخر، فأدوات بناء الاستعلامات وأدوات التقارير كثيرًا ما تُخرِج ناتجًا صحيحًا لكنه عسير القراءة.
الاتساق فائدته أقلّ ظهورًا لكنها تتراكم مع الوقت. حين يُنسّق الجميع بالطريقة نفسها، تُظهِر الفروقات ما تغيّر فعلًا فقط (عمود جديد، أو مرشّح معدّل) بدل ضجيج ناتج عن تعارض تفضيلات شخصٍ في المسافات مع تفضيلات آخر. انتباه المراجِع محدود؛ وإنفاقه على مسافاتٍ أُعيد رصفها هدر. كما أن التنسيق المتّسق يُسهّل الإعداد الأوّلي للموظفين الجدد: يقرأ الموظف الجديد استعلاماتٍ كلها متشابهة، فيتعلّم شكل الفريق مرة واحدة، ويطبّقه في كل مكان. لا شيء من هذا يتطلّب أن يُنسّق أحدٌ يدويًا، وهو محور القسم الأخير: أنت تقرّر القواعد، والأداة تطبّقها.
ثمة ثابتٌ واحد يقوم عليه كل ذلك، ويستحق التصريح به بوضوح لأنه يتكرّر طوال هذا الدليل: التنسيق لا يغيّر سوى المسافات البيضاء وفواصل الأسطر وحالة الكلمات المفتاحية والتعليقات. وهو لا يغيّر أبدًا منطق الاستعلام أو نتائجه. الاستعلام المنسَّق هو الاستعلام نفسه. لذلك يمكنك بأمان تمرير النسخة الفوضوية أعلاه عبر SQL منسّق دون قلقٍ بشأن ما تُعيده.
حالة الكلمات المفتاحية — UPPERCASE مقابل lowercase
أقدم جدلٍ في أيّ دليل تنسيق SQL هو ما إذا كان ينبغي كتابة الكلمات المحجوزة بحروف كبيرة UPPERCASE أم صغيرة lowercase. كلاهما صالح، لأن SQL غير حساسة لحالة الأحرف في الكلمات المفتاحية. الخلاف يخصّ قابلية القراءة، ويجدر فهم الجانبين قبل أن تختار.
الحجّة لصالح الكلمات المفتاحية بحروف كبيرة
الحجّة التقليدية هي التباين البصري. كتابة SELECT وFROM وWHERE وJOIN وGROUP BY بحروف كبيرة تجعل الكلمات المفتاحية تبرز فوق أسماء الجداول والأعمدة الصغيرة، فتستطيع تفحّص شكل الاستعلام — جُمَله، بنيته — من دون الاعتماد على محرّر يلوّنها.
ويهمّ ذلك أكثر مما يبدو، لأن SQL تمرّ عبر أماكن كثيرة لا تبرز فيها الصيغة بألوان: ملفات السجلّات، سلاسل البريد الإلكتروني، أوصاف طلبات الدمج، فرقٌ (diff) نصّيّ صِرف، رسالة على Slack، لوحة مراقبة، أثرُ استدعاء (stack trace). في كل تلك الأماكن، تكون الكلمات المفتاحية بحروف كبيرة هي الشيء الوحيد الذي يُبقي البنية مقروءة — انزع التلوين، فيغدو select id from users where active حساءً من كلماتٍ صغيرة، بينما يظلّ SELECT id FROM users WHERE active يُقرأ بوصفه استعلامًا للوهلة الأولى. هذا هو الاصطلاح الذي ستجده في معظم أدلّة الأنماط الأقدم، وفي توثيق قواعد البيانات، وفي كل كتابٍ مدرسي عن SQL تقريبًا، وهو أيضًا سبب وجدان كثيرٍ من المطوّرين الكلماتِ المفتاحية الكبيرة أكثر ألفةً حتى حين يلوّنها محرّرهم على أي حال.
الحجّة لصالح الكلمات المفتاحية بحروف صغيرة
الحجّة المضادة الحديثة هي أن تلوين الصيغة حلّ مشكلة التباين. كل محرّر وبيئة تطوير متكاملة (IDE) يلوّن الكلمات المفتاحية بوضوح، فتصبح كتابتها بحروف كبيرة زائدةً عن الحاجة — وعند بعض القرّاء، تُقرأ الحروف الكبيرة كلها وكأنها صراخ. كما أنها أسرع قليلًا في الكتابة دون الوصول إلى مفتاح shift مع كل كلمة مفتاحية.
للنمط الصغير زخمٌ حقيقي في عالم هندسة التحليلات. يعتمد مجتمع dbt وعدّة أدلّة أنماطٍ فِرَقية واسعة الاستشهاد الكلماتِ المفتاحيةَ الصغيرة افتراضيًا، انطلاقًا من منطق أن التلوين يحمل الثقل البصري وأن الحروف الصغيرة تُبقي الاستعلام أهدأ في القراءة. وهناك نقطة أدقّ في صالحهم أيضًا: الكلمات المفتاحية الصغيرة تجلس على المستوى البصري نفسه مع أسماء جداولك وأعمدتك بنمط snake_case، فيُقرأ الاستعلام كله قطعةً نصّية واحدة متّسقة بدل سجلّين يتنازعان الانتباه: كلماتٌ مفتاحية بارزة ومعرّفاتٌ هادئة. وكون ذلك ميزة أو عيبًا هو بالضبط ما تختلف عليه الفِرَق، ومن هنا يأتي الحُكم الوحيد الذي يصمد فعلًا.
الحُكم — الاتساق يتفوّق على الاختيار
أيّهما تختار أقلّ أهميةً بكثير من اختيار واحدٍ وفرضه. قاعدة كودٍ يصرخ نصف استعلاماتها SELECT ويهمس نصفها الآخر select هي أسوأ نتيجة، لأن عدم الاتساق نفسه يغدو ضجيجًا. والخلط بين الحالتين في استعلام واحد أسوأ بعد.
سبب انتصار الاتساق آليّ لا جماليّ. عدم اتساق الحالة يجعل الفروقات تكذب: يرى المراجِع «تغييرًا» في سطرٍ هو في الحقيقة مجرد إعادة شخصٍ تنسيقَ كلمة مفتاحية، فيختبئ التغيير الحقيقي وسط الضجيج. كما تصبح أدوات grep والبحث أقلّ موثوقية حين تظهر الكلمة المفتاحية نفسها بثلاث حالات. النمط الواحد المفروض يزيل كل هذا العبء بثمن قرارٍ واحد. فقرّروا كفريق، دوّنوا القرار، ودَعوا أداةً تفرضه بدل الاعتماد على الانضباط. يحتوي SQL منسّق على ضابط الكلمات المفتاحية (Keywords) بثلاثة خيارات — UPPERCASE وlowercase وPreserve — فتستطيع توحيد كومةٍ كاملة من الاستعلامات التاريخية إلى نمطٍ واحد بنقرة واحدة. الاستعلام نفسه، معروضًا بالطريقتين:
-- UPPERCASE
SELECT id, email FROM users WHERE active = true ORDER BY created_at DESC;
-- lowercase
select id, email from users where active = true order by created_at desc;
اختر ما يفضّله فريقك. الهدف أن تطابقه كل استعلاماتك.
المسافات البادئة وفواصل الأسطر
الحالة تقرّر شكل الكلمات المفتاحية. أما المسافات البادئة وفواصل الأسطر فتقرّر كيف يُرسَم منطق الاستعلام على الصفحة، وهنا يكمن معظم قابلية القراءة.
نمط «النهر» مقابل النمط الكتلي
عمّم دليل sqlstyle.guide الشهير لـSimon Holywell نمط «النهر» (river)، حيث تُحاذى الكلمات المفتاحية إلى اليمين (في الأصل اللاتيني إلى اليمين على حافتها) بحيث تنساب قناةٌ رأسية من المسافة البيضاء وسط الاستعلام:
SELECT id,
email,
created_at
FROM users
WHERE active = true
ORDER BY created_at DESC;
جاذبية النمط أن SELECT وFROM وWHERE تتراصف على حافتها، وتجلس قائمة الأعمدة بنظافة إلى جانب النهر. لكن مساوئه عملية. تعتمد المحاذاة على طول أطول كلمة مفتاحية لديك، فإضافة LEFT JOIN قد تُجبرك على إعادة الإزاحة بأكملها؛ وصيانته يدويًا مؤلمة؛ وهو يُنتج فروقاتٍ مزعجة، لأن تغيير طول كلمة مفتاحية واحدة يُزيح المسافة البيضاء في الأسطر المجاورة.
أما النمط الكتلي (أو المحاذى إلى اليسار) فيبدأ كل جملة رئيسية عند الهامش في سطرها الخاص ويُزيح محتوى الجملة:
SELECT
id,
email,
created_at
FROM users
WHERE active = true
ORDER BY created_at DESC;
هذا هو الافتراضي السائد والذي تُنتجه معظم الأدوات، تحديدًا لأنه مستقرّ: إضافة جملة لا تُعيد رصف الأسطر فوقها أبدًا، فتبقى الفروقات صغيرة ويصمد التخطيط أمام التنسيق الآلي. نمط النهر يُحسِّن لشكل الاستعلام المنتهي بمعزل عن غيره؛ والنمط الكتلي يُحسِّن لكيفية تغيّر الاستعلامات مع الوقت وكيفية مراجعتها في نظام التحكم بالإصدارات. لأيّ شيء يقطن مستودعًا ويخضع للتحرير، النمط الكتلي هو الرهان الأكثر أمانًا، وهو ما يفترضه بقية هذا الدليل.
كم مسافة — 2 مقابل 4 مقابل علامات التبويب
ما إن تُزيح، عليك أن تقرّر إلى أيّ مدى. للأجوبة الثلاثة الشائعة كلٍّ مسوّغه:
- مسافتان (2 spaces) — الافتراضي الأكثر شيوعًا. يُبقي الفروقات مدمجة ويمنع الاستعلامات المتداخلة من الزحف إلى حافة الشاشة.
- أربع مسافات (4 spaces) — تمنح كل مستوى تداخلٍ فصلًا بصريًا أكبر، وهو ما يساعد في الاستعلامات ذات الاستعلامات الفرعية العميقة أو مستويات تعبيرات الجداول العامة (CTE) المتعددة.
- علامات التبويب (Tabs) — تتيح لكل مطوّر اختيار عرض العرض الخاص به من دون تغيير الملف.
لا توجد إجابة صحيحة عالميًا هنا، ولهذا بالضبط يعرض SQL منسّق ضابط الإزاحة (Indent) بالخيارات الثلاثة كلها (2 spaces و4 spaces وTab). اختر واحدًا وطبّقه في كل مكان.
أين تكسر الأسطر
عرض المسافة البادئة هو الجزء السهل. القرار الأعلى أثرًا هو أين تُدرِج فواصل الأسطر:
- أعمدة
SELECT— عمود واحد لكل سطر في أيّ شيء غير تافه، بحيث تمسّ إضافة عمود أو إزالته سطرًا واحدًا بالضبط في الفرق. أما الاستعلامات القصيرة جدًا فيمكنها البقاء في سطر واحد. FROMوJOIN— ابدأ كل عملية ضمّ في سطرها الخاص، مع شرطONإما لاحقًا له أو مزاحًا تحته. هذا يُبقي مخطّط الضمّ مقروءًا.WHERE— ضع كلAND/ORفي سطره الخاص بحيث يُقرأ المنطق المنطقي (boolean) من الأعلى إلى الأسفل. ولشروطAND/ORالمختلطة، ضع الأقواس وأزِح المجموعات بحيث تكون الأولوية صريحة لا شيئًا على القارئ استنتاجه.
هذه إرشادات لا قوانين. استعلامٌ تافه مثل SELECT id FROM users WHERE id = 1 لا يحتاج خمسة أسطر، وإجباره عليها يضرّ بقابلية القراءة لا يساعدها. الحُكم تقريبًا: اكسر حين يحوي الاستعلام أكثر من عمود أو عمودين، أو أكثر من جدول، أو أكثر من شرط. دون تلك العتبة، السطر الواحد أوضح؛ فوقها، اكسر بقوة. المنسّق الجيّد يُرمِّز لك عتبةً معقولة، لكن يجدر فهم المبدأ كي لا يفاجئك الناتج أبدًا.
وبتطبيق تلك القواعد على الاستعلام الفوضوي من سطر واحد السابق، نحصل على تخطيطٍ تكون فيه كل جملة وكل عملية ضمّ مرئية للوهلة الأولى:
SELECT
u.id,
u.name,
COUNT(o.id) AS orders
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.active = true
GROUP BY u.id, u.name
ORDER BY orders DESC;
الفواصل البادئة مقابل اللاحقة
سؤال أصغر لكنه دائم: أين تُوضَع الفاصلة في قائمة أعمدةٍ متعددة الأسطر؟
-- Leading commas
SELECT
id
, email
, created_at
FROM users;
-- Trailing commas
SELECT
id,
email,
created_at
FROM users;
للفواصل البادئة ميزة حقيقية: إضافة عمود أو إزالته يغيّر سطرًا واحدًا، والفاصلة الناقصة سهلة الرصد لأن السطر المُخالف يبرز. والفواصل اللاحقة تُقرأ بطبيعية أكبر وهي أكثر شيوعًا في الواقع. كلاهما جيّد — اختر واحدًا، ودَع المنسّق يطبّقه كي لا يضطر أحد للتفكير فيه ثانيةً.
اصطلاحات التسمية للجداول والأعمدة
التنسيق يحكم المسافة البيضاء؛ والتسمية تحكم المعرّفات نفسها، ودليل الأنماط ناقصٌ من دونها.
المعيار الفعلي لمعرّفات SQL هو snake_case — كلها حروف صغيرة، والكلمات مفصولة بشُرَط سفلية: user_id وcreated_at وorder_items. وهو يكسب تلك المكانة لسببٍ ملموس لا مجرد عادة: معرّفات snake_case لا تحتاج اقتباسًا أبدًا وتتصرّف باتساق عبر اللهجات، بينما يصطدم camelCase (الشائع في كود التطبيقات) بكيفية طيّ قواعد البيانات للحالة، وهو ما سنصل إليه بعد قليل.
ويجدر التصريح بسبب اختلاف هذا عن كود التطبيقات. في معظم لغات البرمجة، الكود المحيط يتحكّم في المعرّفات، وcamelCase أو PascalCase هو العُرف. أما معرّفات SQL فتُفسَّر بقواعد طيّ الحالة الخاصة بقاعدة البيانات نفسها، وتلك القواعد هي بالضبط ما يجعل الأسماء المختلطة الحالة هشّة. snake_case يتفادى المسألة بأكملها: لا حالة لطيّها، ولا سبب للاقتباس، ولا شيء يتصرّف على نحوٍ مختلف من محرّكٍ لآخر.
بضعة اصطلاحات أخرى تظهر في كل دليل تنسيق SQL تقريبًا:
- المفرد مقابل الجمع في أسماء الجداول انقسامٌ حقيقي.
users(جمع، «الجدول يحوي مستخدمين») وuser(مفرد، «كل صفّ مستخدم») كلاهما له أنصار. ومثل الحالة، الاختيار أقلّ أهميةً من تطبيقه باتساق على كل جدول. - تجنّب الكلمات المحجوزة كمعرّفات. تسمية عمود
orderأوuserأوtableتُجبرك على اقتباسه في كل مكان وتستدعي أخطاءً مُربكة. اِلجأ إلىorder_idأوaccountبدلًا من ذلك. - حافظ على اتساق تسمية المفاتيح. مفتاح أساسي اسمه
idومفاتيح خارجية مسمّاة<referenced_table>_id(مثلuser_id) تجعل عمليات الضمّ متوقَّعة وموثِّقة لذاتها.
ثمة فخّ واحد يستحقّ الإشارة إليه صراحةً، لأنه يلسع الفِرَق التي تسمّي أعمدة قاعدة البيانات كما تسمّي متغيّرات التطبيقات. في PostgreSQL، يُطوى المعرّف غير المقتبَس إلى الحروف الصغيرة، فإن SELECT userId FROM t يبحث فعليًا عن عمود اسمه userid. وفي اللحظة التي تقتبسه فيها — "userId" — تحفظ قاعدة البيانات الحالة وتعامل "userId" وuserid كعمودين مختلفين:
-- يُنشئ عمودًا اسمه الفعلي بأحرف صغيرة "userid"
CREATE TABLE t (userId integer);
-- كلاهما يعمل -- لأن الاسم طُوي إلى الحروف الصغيرة
SELECT userId FROM t;
SELECT userid FROM t;
-- هذا يفشل: "column \"userId\" does not exist"
-- الاقتباس يفرض مطابقة دقيقة حسّاسة لحالة الأحرف
SELECT "userId" FROM t;
لاحظ أن قواعد البيانات المختلفة تطوي الحالة في اتجاهات مختلفة (Oracle تطوي المعرّفات غير المقتبَسة إلى الحروف الكبيرة، وعدّةٌ أخرى إلى الصغيرة)، فالمعرّفات المقتبَسة المختلطة الحالة ليست محمولة (portable) أصلًا. والمخرج النظيف هو تجنّب المعرّفات المقتبَسة المختلطة الحالة كليًا والالتزام بـsnake_case، الذي يلتفّ على المشكلة بأكملها ويُبقي مخطّطك مقروءًا في كل لهجة.
لمقارنة أعمق بين camelCase وsnake_case وkebab-case — بما في ذلك متى يكون كلٌّ منها الخيار الصحيح عبر الكود والبيانات — راجع دليل اصطلاحات التسمية.
التنسيق عبر لهجات SQL
كل ما سبق غير مرتبطٍ باللهجة إلى حدّ كبير — الحالة والإزاحة وفواصل الأسطر والتسمية تنطبق مهما كانت قاعدة البيانات التي تستهدفها. لكن «نسّق هذا الـSQL» يصطدم بجدارٍ في اللحظة التي يستخدم فيها استعلامك صيغة خاصة بقاعدة بيانات واحدة، لأن مُحلِّلًا عامًّا لا يتعرّف على تلك الصيغة سيُشوّهها: قد يشطر رمزًا (token) في الموضع الخطأ، أو يُسيء قراءة مُعامِل، أو يعامل حرف اقتباس كفاصل سلاسل نصية فيبتلع نصف الاستعلام. هنا يثبت التنسيق المدرك للهجة جدارته، وهو سبب طلب المنسّق منك اختيار قاعدة بيانات أولًا بدل التخمين. الاختلافات أدناه هي الأكثر مصادفةً في الاستعلامات اليومية.
إليك مقارنة سريعة لأكثر الاختلافات شيوعًا بين اللهجات:
| العملية | PostgreSQL | MySQL / MariaDB | SQL Server (T-SQL) | Oracle | Standard SQL |
|---|---|---|---|---|---|
| سَلسلة النصوص | || أو CONCAT() | CONCAT() | + أو CONCAT() | || أو CONCAT() | || |
| التعامل مع NULL | COALESCE() | COALESCE() / IFNULL() | COALESCE() / ISNULL() | COALESCE() / NVL() | COALESCE() |
| تحديد عدد الصفوف | LIMIT | LIMIT | TOP / OFFSET … FETCH | FETCH FIRST | FETCH FIRST |
| اقتباس المعرّفات | علامات اقتباس مزدوجة ("…") | علامات خلفية | أقواس مربّعة ([…]) | علامات اقتباس مزدوجة ("…") | علامات اقتباس مزدوجة ("…") |
تفصّل الأقسام التالية كلّ صفّ من هذه الصفوف مع أمثلة فعلية.
دمج السلاسل النصية ومعالجة NULL
اثنتان من أكثر العمليات اليومية شيوعًا تُكتبان بطرق مختلفة عبر اللهجات.
دمج السلاسل النصية:
-- PostgreSQL, Oracle, SQLite (standard operator)
SELECT first_name || ' ' || last_name AS full_name FROM users;
-- SQL Server (T-SQL uses +)
SELECT first_name + ' ' + last_name AS full_name FROM users;
-- Portable across dialects
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
بدائل NULL:
-- Standard SQL (works everywhere)
SELECT COALESCE(nickname, name) AS display_name FROM users;
-- SQL Server only
SELECT ISNULL(nickname, name) AS display_name FROM users;
-- MySQL / MariaDB only
SELECT IFNULL(nickname, name) AS display_name FROM users;
قد لا يفهم منسّقٌ مضبوطٌ على اللهجة الخطأ ISNULL أو المُعامِل || فيُسيء تحليل الاستعلام المحيط.
تحديد الصفوف واقتباس المعرّفات
تحديد عدد صفوف النتيجة من أكثر أجزاء الصيغة تباينًا بين اللهجات:
-- PostgreSQL, MySQL, SQLite
SELECT id, name FROM users ORDER BY created_at DESC LIMIT 10;
-- SQL Server (T-SQL)
SELECT TOP 10 id, name FROM users ORDER BY created_at DESC;
-- Standard SQL / Oracle
SELECT id, name FROM users ORDER BY created_at DESC FETCH FIRST 10 ROWS ONLY;
وينقسم اقتباس المعرّفات إلى ثلاث طرق أيضًا. حين يتوجّب عليك اقتباس معرّف — عادةً لاستخدام كلمة محجوزة أو الحفاظ على الحالة — يعتمد الفاصل على قاعدة البيانات:
-- MySQL / MariaDB use backticks
SELECT `order`, `user` FROM `select`;
-- SQL Server (T-SQL) uses square brackets
SELECT [order], [user] FROM [select];
-- Standard SQL (PostgreSQL, Oracle, SQLite) uses double quotes
SELECT "order", "user" FROM "select";
منسّقٌ يظنّ أن العلامات الخلفية (backticks) في MySQL فواصل سلاسل نصية، أو أن أقواس T-SQL المربّعة شيء آخر، سيُنتج ناتجًا معطوبًا. إعداد اللهجة هو ما يُخبره أيٌّ هو أيّ. وهذا أيضًا سبب أن لصق استعلام بين قواعد البيانات نادرًا ما يكون تبديلًا نظيفًا: النيّة المنطقية نفسها (دمج سلسلتين نصيتين، أو التراجع إلى NULL، أو التحديد بعشرة صفوف، أو اقتباس كلمة محجوزة) مكتوبة بأربع طرق مختلفة عبر اللهجات، ولا يستطيع إعادة تنسيقها دون إفسادها إلا المُحلِّل الذي يعرف قاعدة بياناتك.
لماذا يهمّ التنسيق المدرك للهجة
هذا بالضبط سبب أن SQL منسّق يأتي بتسع لهجات — PostgreSQL وMySQL وSQL Server (T-SQL) وBigQuery وSnowflake وOracle وSQLite وMariaDB وStandard SQL — بدل نمطٍ عامّ واحد. اختيار اللهجة الصحيحة يعني أن المُحلِّل يعالج بشكل صحيح سلاسل PostgreSQL المقتبَسة بعلامة الدولار (dollar-quoted) وعمليات التحويل ::، ومعرّفات T-SQL المحصورة بأقواس وTOP، والدوال الخاصة بالمستودعات في BigQuery وSnowflake، وقواعد الاقتباس أعلاه، بدل أن يخمّن فيُخطئ. اختر قاعدة بياناتك الفعلية من القائمة المنسدلة قبل أن تُنسّق، فيعود الناتج صحيحًا وأصيلًا.
أتمتة تنسيق SQL
قراءة القواعد شيء؛ ولا ينبغي لأحدٍ أن يطبّقها يدويًا. الغاية كلها من دليل الأنماط أن تفرضه آلة. هناك ثلاثة مواضع لإدراج التنسيق، تبعًا لمقدار الاحتكاك الذي تريد إزالته.
في محرّرك (التنسيق عند الحفظ)
الخيار الأقلّ جهدًا هو التنسيق تلقائيًا كلما حفظت. لدى VS Code إضافات منسّق SQL تعمل عند الحفظ، وتأتي JetBrains DataGrip وأدوات قواعد البيانات في بيئات التطوير الأخرى بمنسّقٍ مدمج يمكنك ربطه بضغطة مفتاح أو خطّاف حفظ (save hook). ما إن يُعدّ، تصبح استعلاماتك ببساطة غير منسَّقةٍ أبدًا — النموذج نفسه مثل Prettier لـJavaScript أو gofmt لـGo. والمأخذ أن إعدادات المحرّر تقطن جهاز كل مطوّر، فالتنسيق عند الحفظ يُبقي SQL الخاصة بك مرتّبة لكنه لا يضمن وحده ذلك لبقية الفريق. لهذا تحتاج الطبقة التالية.
في التكامل المستمر مع مُدقّق
لفرض النمط عبر فريق كامل، انقل الفحص إلى التكامل المستمر (CI). يقوم مُدقّق SQL مثل sqlfluff بالتدقيق والإصلاح التلقائي معًا: تُرمِّز قواعدك — اللهجة، حالة الكلمات المفتاحية، الإزاحة، موضع الفاصلة — في ملف إعداد .sqlfluff، وتُشغّل sqlfluff lint لوضع علامة على المخالفات وsqlfluff fix لإصلاحها، وتجعل التكامل المستمر يُفشل أيّ طلب دمج ينحرف عن النمط المتّفق عليه. هذه الفكرة نفسها مثل ESLint أو Prettier وهما يحرسان مستودع الواجهة الأمامية: يكفّ النمط عن كونه تعليق مراجعةٍ على أحدهم تذكّر تركه، ويغدو فحصًا ناجحًا أو فاشلًا لا تنساه الآلة أبدًا. والمردود أن جدالات النمط تحدث مرة واحدة، حين تكتب الإعداد، بدل أن تحدث في كل طلب دمج.
التنسيق لمرّة واحدة عبر الإنترنت
أحيانًا يكون لديك استعلامٌ قبيح واحد فقط ولا رغبة في تثبيت أيّ شيء — مقتطفٌ من سجلّ، رسالة زميلٍ على Slack، استعلامٌ تلصقه في التوثيق. لذلك، الصقه في SQL منسّق، اختر اللهجة والحالة والإزاحة، وانسخ النتيجة النظيفة.
تفصيل الخصوصية يهمّ هنا، ومن السهل إغفاله. كثير من المنسّقات عبر الإنترنت ترسل النصّ الذي تلصقه إلى خادم لإنجاز العمل، ما يعني أن نسخة من استعلامك — أسماء الجداول، أسماء الأعمدة، وأحيانًا قيم حرفية من حادثة إنتاج — تغادر جهازك. أما SQL منسّق فيعمل بالكامل داخل متصفّحك، فلا تُرفَع SQL الخاصة بك إلى أي مكان أبدًا. وهذا يجعل من الآمن تنسيق استعلاماتٍ تمسّ مخطّطات الإنتاج أو منطقًا مملوكًا، وهو بالضبط الموقف الذي تريد فيه تنسيقًا نظيفًا أكثر ما تريد، وتريد فيه أقلّ ما تريد تسليم استعلامك إلى طرفٍ ثالث. وإن كنت تتعامل مع صيغ أخرى في سير العمل نفسه، فالأداة الشقيقة JSON منسّق تعمل بالطريقة نفسها — معالجةٌ داخل المتصفّح نفسها، ونسخٌ بنقرة واحدة نفسه.
النُّهج الثلاثة لا يستبعد بعضها بعضًا، وأفضل إعدادٍ عادةً يجمعها: التنسيق عند الحفظ للحلقة الداخلية السريعة أثناء الكتابة، ومُدقّق التكامل المستمر سندًا يفرض معيار الفريق، ومنسّقٌ عبر الإنترنت للمقتطفات العابرة التي لا تمسّ مستودعك أبدًا. أيًّا ما تلجأ إليه، تذكّر الثابت مرة أخيرة — لا شيء من هذه الأدوات يغيّر ما يفعله استعلامك. إنها تُعيد ترتيب المسافة البيضاء وفواصل الأسطر والحالة والتعليقات، لا غير.
الأسئلة الشائعة
هل ينبغي أن تكون كلمات SQL المفتاحية بحروف كبيرة أم صغيرة؟
كلاهما صالح، لأن كلمات SQL المفتاحية غير حسّاسة لحالة الأحرف. الحروف الكبيرة UPPERCASE تجعل الكلمات المفتاحية تبرز في البيئات الخالية من تلوين الصيغة، كالسجلّات والفروقات؛ والحروف الصغيرة lowercase أسهل في الكتابة وتلائم المحرّرات الحديثة التي تلوّن الكلمات المفتاحية أصلًا. ما يهمّ فعلًا أن يختار الفريق كله واحدًا وأن يفرضه منسّق — الخلط بين الحالتين هو أسوأ خيار.
ما أفضل إزاحة لـSQL؟
مسافتان هي الافتراضي الأكثر شيوعًا وتُبقي الفروقات مدمجة؛ وأربع مسافات تجعل الاستعلامات العميقة التداخل أسهل قراءة؛ وعلامات التبويب تتيح لكل مطوّر اختيار عرض العرض الخاص به. لا توجد إجابة صحيحة واحدة — اختر واحدة وطبّقها باتساق عبر فريقك. تدعم معظم منسّقات SQL، ومنها هذا، الخيارات الثلاثة كلها.
كيف أنسّق SQL تلقائيًا؟
هناك ثلاث طرق لتنسيق SQL تلقائيًا: التنسيق عند الحفظ في محرّرك (VS Code أو DataGrip)، أو مُدقّق في التكامل المستمر مثل sqlfluff يُصلح النمط تلقائيًا، أو منسّق SQL عبر الإنترنت للّصق لمرّة واحدة. الطريق عبر الإنترنت هو الأسرع لأنه لا يحتاج تثبيتًا — فقط الصق، اختر لهجتك، وانسخ النتيجة.
هل أستخدم فواصل بادئة أم لاحقة في SQL؟
الفواصل البادئة (الفاصلة في بداية كل سطر) تمنح فروقاتٍ أنظف عند إضافة الأعمدة أو إزالتها وتجعل الفاصلة الناقصة سهلة الرصد؛ والفواصل اللاحقة (الفاصلة في النهاية) تُقرأ بطبيعية أكبر وهي أكثر شيوعًا. كلاهما مقبول في أيّ دليل تنسيق SQL — المفتاح اختيار واحدٍ والسماح لمنسّق بتطبيقه تلقائيًا.
هل يغيّر تنسيق SQL طريقة تنفيذ الاستعلام؟
لا. تنسيق SQL لا يغيّر سوى المسافة البيضاء وفواصل الأسطر وحالة الكلمات المفتاحية والتعليقات — وهو لا يغيّر أبدًا منطق الاستعلام. الاستعلام المنسَّق يُعيد النتائج ذاتها تمامًا التي يعيدها الأصل، ولهذا من الآمن تمامًا تجميل حتى استعلامات الإنتاج قبل مراجعتها أو تشغيلها.
ما اصطلاح التسمية الذي أستخدمه لجداول وأعمدة SQL؟
snake_case — كلها حروف صغيرة مع شُرَط سفلية — هو المعيار الفعلي لأسماء جداول وأعمدة SQL لأنه يتفادى الاقتباس ويبقى آمنًا عبر اللهجات. حافظ على تسمية المفاتيح الأساسية (id) والمفاتيح الخارجية (user_id) باتساق، وتجنّب استخدام الكلمات المحجوزة مثل order أو user كمعرّفات منعًا لمتاعب الاقتباس.
كيف أنسّق SQL للهجة معيّنة مثل PostgreSQL أو T-SQL؟
اختر اللهجة المطابقة في المنسّق أولًا. وضع PostgreSQL يعالج بشكل صحيح عمليات التحويل :: والسلاسل المقتبَسة بعلامة الدولار؛ ووضع SQL Server (T-SQL) يفهم المعرّفات المحصورة بأقواس [identifiers] وTOP. اختيار اللهجة الخطأ يجعل مُحلِّلًا عامًّا يُشوّه الصيغة الخاصة باللهجة، فاضبطه دومًا على قاعدة بياناتك الفعلية قبل التنسيق.
هل يوجد دليل تنسيق SQL معياري؟
لا يوجد معيار رسمي، لكن توجد عدّة أدلّة واسعة الاستشهاد: دليل sqlstyle.guide لـSimon Holywell وأدلّة الأنماط العلنية من فِرَقٍ مثل Mozilla ومجتمع dbt. وإجماعها المشترك — إزاحة متّسقة، معرّفات snake_case، وفاصل سطرٍ قبل كل جملة رئيسية — هو ما يُرمّزه هذا الدليل، ويستطيع منسّقٌ أن يفرضه عنك.