Menu
flag Ar iconالعربيةdown icon

جداول STRICT في SQLite: فرض أنواع الأعمدة

تعرّف على جداول STRICT في SQLite وكيف تُلغي مرونة التخزين وترفض القيم غير المطابقة لتمنحك التحقق الصارم من الأنواع الذي كنت تتوقعه.

تحتوي هذه الصفحة على محررات قابلة للتشغيل — حرّر، شغّل، وشاهد النتيجة فوراً.

لماذا ظهرت جداول STRICT في SQLite؟

تتعامل SQLite مع الأنواع بمرونة شديدة بشكل افتراضي، وهذا أمر معروف عنها. تُعرِّف عمودًا على أنه INTEGER، ثم تُدخل فيه النص "hello"، فتقبله SQLite دون اعتراض وتخزّنه كنص. هذه المرونة كانت قرار تصميم مقصودًا في التسعينيات، لكنها تُربك القادمين من Postgres أو MySQL، والأسوأ أنها تُخفي الأخطاء البرمجية بدلًا من كشفها.

جاءت جداول STRICT في الإصدار 3.37 من SQLite لمعالجة هذه المشكلة. تُفعّلها لكل جدول على حدة، وبمجرد تفعيلها تصبح أنواع الأعمدة ملزِمة فعلًا، تمامًا كما تُصرَّح.

الكلمة المفتاحية STRICT تُكتب بعد القوس المغلق، وما عدا ذلك فالأمر يبدو كأي CREATE TABLE عادي. الفرق الحقيقي يظهر لحظة محاولتك إدخال قيمة من نوع غير مناسب في أحد الأعمدة.

ما الذي يفرضه STRICT فعلياً؟

في الجداول العادية، تحاول آلية type affinity تحويل القيمة إلى النوع المُعلَن، فإن عجزت خزّنتها كما هي دون اعتراض. أما في جداول STRICT، فأي عدم تطابق في النوع يُعتبر خطأً صريحاً.

جرّب نفس الشيء على جدول غير STRICT وستجد أن عملية الإدراج الثالثة تنجح — وستقوم SQLite بكل أريحية بتخزين السلسلة 'oops' داخل عمود قلت إن نوعه INTEGER. وبعد أشهر، يُرجع لك استعلام تجميعي نتائج لا معنى لها، فتقضي عصر يوم كامل تبحث عن السبب. أما STRICT فيجعل الخطأ يظهر لحظة الإدراج نفسها، حيث يسهل عليك إصلاحه.

الخطأ الذي ستراه:

Runtime error: cannot store TEXT value in INTEGER column accounts.balance

واضحة، فورية، يصعب تجاهلها.

الأنواع الخمسة المسموح بها

تقبل جداول STRICT خمسة أنواع فقط لا غير:

  • INTEGER — الأعداد الصحيحة.
  • REAL — الأعداد العشرية (ذات الفاصلة).
  • TEXT — النصوص.
  • BLOB — البيانات الثنائية الخام.
  • ANY — أي نوع، دون أي تحويل.

هذا كل شيء. أما الأسماء البديلة المرنة التي يقبلها SQLite عادةً — مثل VARCHAR(255) وDOUBLE وBOOLEAN وDATETIME وINT — فجميعها يُطلق خطأً داخل جدول STRICT:

الخطأ:

خطأ في التحليل: نوع بيانات غير معروف لـ bad.name: "VARCHAR(255)"

الحل هو استخدام أحد الأسماء الخمسة المعتمدة. فبدلاً من VARCHAR(255) استخدم TEXT، وبدلاً من DATETIME استخدم TEXT أيضاً (فـ SQLite يخزّن التواريخ كسلاسل ISO على أي حال)، أما BOOLEAN فيصبح INTEGER (مع القيمتين 0 و1).

مخرج الطوارئ: عمود ANY

ANY هو النوع الوحيد الذي يسمح لعمود داخل جدول STRICT بقبول قيم من أنواع مختلفة، وهذا مفيد في حالات مثل عمود value العام في جدول مفتاح/قيمة:

ANY له معاملة خاصة داخل جداول STRICT: فهو يحفظ القيم بدون أي تحويل تلقائي للنوع، عكس ما تتوقعه من نفس الكلمة في سياقات أخرى. النص '100' يبقى نصاً، والعدد الصحيح 100 يبقى عدداً صحيحاً. واستدعاءات typeof() في الاستعلام أعلاه تثبت ذلك بوضوح.

أما في الجدول العادي (غير STRICT)، فإن العمود ذا الـ affinity من نوع ANY يقوم بتحويل النصوص التي تبدو رقمية إلى أرقام. لكن جداول STRICT تحافظ على النوع الأصلي كما هو تماماً.

جداول STRICT مع PRIMARY KEY

هناك فرق دقيق ينبغي الانتباه له: في الجدول العادي، يُعدّ INTEGER PRIMARY KEY حالة خاصة، إذ يصبح اسماً بديلاً (alias) لـ rowid ولا يقبل سوى الأعداد الصحيحة. أما باقي تعريفات المفتاح الأساسي فتكون أكثر تساهلاً.

في جدول STRICT، يُفرض نوع العمود بصرامة سواء كان مفتاحاً أساسياً أم لا:

الـ INSERT الثاني هيفشل. لو كان الجدول عادي (ليس STRICT)، كانت القيمة 42 هتتخزّن في عمود المفتاح الأساسي TEXT من غير ما حد يحس. لكن هنا، SQLite بتقولّك على الغلط صراحة.

خلط الجداول STRICT مع الجداول العادية

خاصية STRICT بتشتغل على مستوى الجدول، ليس على مستوى قاعدة البيانات كلها. يعني تقدر يكون عندك جدول users بنمط STRICT وجدول events عادي في نفس الملف. والمفاتيح الأجنبية (Foreign Keys) هتشتغل بينهم زي ما هي من غير أي مشاكل.

جدول events لا يستخدم STRICT ولا يحدد نوعًا للعمود payload، فيقبل أي شيء تضعه فيه. هذا مفيد أحيانًا، لكنه خطر إذا اعتمدته افتراضيًا. اجعل التخزين بلا نوع خيارًا محصورًا في الحالات التي تحتاج فيها فعلًا إلى عمود يستوعب أنواعًا متفرقة.

متى تستخدم جداول STRICT في SQLite؟

بالنسبة للمخططات الجديدة، الإجابة هي «في كل الحالات تقريبًا». التكلفة بسيطة: كلمة مفتاحية واحدة لكل جدول، وأن تتذكر أسماء الأنواع الخمسة المعتمدة. أما الفائدة فهي أن الأخطاء التي كانت ستختبئ بصمت داخل بياناتك ستظهر فورًا عند عملية الإدراج التي تسببت فيها.

تجنّب STRICT في هذه الحالات:

  • إذا كنت تتعامل مع قاعدة بيانات SQLite قديمة يعتمد مخططها الحالي على نظام الأنواع المرن.
  • إذا كان إصدار SQLite المستهدف أقدم من 3.37 (أكتوبر 2021)، فالكلمة المفتاحية ببساطة غير موجودة فيه.
  • إذا كنت تريد فعلًا أن يحتوي عمود ما على أنواع مختلطة. حتى في هذه الحالة، يفضّل استخدام STRICT مع عمود من النوع ANY بدلًا من جدول غير صارم، لأن باقي الأعمدة تبقى محكومة بالأنواع.

قائمة سريعة عند تحويل جدول عادي إلى جدول STRICT:

  • استبدل VARCHAR وCHAR وNVARCHAR بـ TEXT.
  • استبدل DOUBLE وFLOAT وNUMERIC بـ REAL.
  • استبدل BOOLEAN وBIT وTINYINT بـ INTEGER.
  • استبدل DATETIME وTIMESTAMP وDATE بـ TEXT (أو INTEGER إن كنت تخزّن طوابع زمنية unix).
  • أضف STRICT بعد القوس المغلق.

الخطوة التالية: المفاتيح الأساسية

جداول STRICT تُحكم طريقة تخزين البيانات داخل الأعمدة. الخطوة التالية التي تستحق الإحكام هي تحديد أي عمود يميّز كل صف. وللمفاتيح الأساسية في SQLite بعض الخصائص الغريبة (خصوصًا فيما يتعلق بـ INTEGER PRIMARY KEY وrowid) التي يجدر بك معرفتها قبل تصميم مخطط حقيقي.

الأسئلة الشائعة

ما هو جدول STRICT في SQLite؟

جدول STRICT يفرض نوع العمود كما أعلنته تماماً — إذا قلت إن العمود من نوع INTEGER، فإن SQLite سترفض أي قيمة ليست عدداً صحيحاً أو NULL. تُفعّل هذا الوضع بإضافة الكلمة المفتاحية STRICT بعد القوس الإغلاقي في جملة CREATE TABLE. بدون هذه الكلمة، تعتمد SQLite على ما يُعرف بـ type affinity، حيث تحوّل القيم إن استطاعت وتخزّنها كما هي إن لم تستطع.

ما الأنواع التي يمكن استخدامها في جدول STRICT؟

خمسة أنواع فقط لا غير: INTEGER، وREAL، وTEXT، وBLOB، وANY. أما الأسماء البديلة التي تعمل في الجداول العادية مثل VARCHAR وDOUBLE وBOOLEAN وDATETIME فجميعها تُسبّب خطأ داخل جدول STRICT. وعمود ANY بمثابة باب خلفي يقبل أي نوع من البيانات دون أي تحويل.

هل يُنصح باستخدام جداول STRICT في قواعد البيانات الجديدة؟

نعم في معظم المخططات الجديدة. جداول STRICT تكشف أخطاء كانت الجداول العادية تبتلعها بصمت — كنص يتسلل إلى عمود INTEGER، أو قائمة تحوّلت بالخطأ إلى قيمة في عمود REAL. الثمن بسيط: كلمة مفتاحية إضافية لكل جدول، والتخلّي عن أسماء الأنواع الغريبة. الميزة متاحة منذ إصدار SQLite 3.37 الصادر عام 2021.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن