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

العروض (Views) في SQLite: CREATE VIEW و INSTEAD OF

كيف تعمل العروض في SQLite: حفظ الاستعلامات كجداول افتراضية، ومتى تستخدم العروض المؤقتة، ولماذا تكون للقراءة فقط افتراضيًا.

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

ما هو الـ View في SQLite؟ ببساطة استعلام محفوظ

الـ view في SQLite هو عبارة عن جملة SELECT أعطيتها اسماً. بعد ما تنشئه، تقدر تستعلم منه تماماً كأنه جدول عادي — لكن في الحقيقة لا شيء يُخزَّن فعلياً. كل ما تقرأ من العرض (view)، يقوم SQLite بتنفيذ الاستعلام الأساسي من جديد.

paid_orders يبدو ويتصرّف تمامًا مثل أي جدول. له أعمدة، تقدر تعمل عليه SELECT، وتقدر تستخدمه في الـ joins. لكن خلف الكواليس، كل استعلام يتوسّع إلى فلتر WHERE status = 'paid' الأصلي.

هذه هي الفكرة باختصار: الـ view ما هو إلا اسم مستعار لاستعلام.

فوائد العروض في SQLite

أكبر فائدة هي التسمية. استعلام معقّد يأخذ اسمًا قصيرًا ومعبّرًا، وبقية الكود يبقى مقروءًا وواضحًا:

بدون هذا العرض، سيضطر كل من يستعلم عن البيانات إلى كتابة GROUP BY بنفسه، وأي شخص منهم قد يخطئ في الفلترة. أما مع العرض فالتجميع مُعرَّف مرة واحدة فقط، ويكتفي المستخدمون بطلب customer_totals وإضافة ما يحتاجونه من فلاتر إضافية فوقه.

كذلك تعمل العروض في SQLite بمثابة حدود صلاحيات. فإذا كان هناك استعلام يجب ألا يكشف عمودًا مثل password_hash، أنشئ عرضًا يختار كل الأعمدة ما عدا هذا العمود، واجعل كود التطبيق يتعامل مع العرض بدلًا من الجدول مباشرةً.

صياغة CREATE VIEW في SQLite

الصيغة الكاملة:

CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name [(column_aliases)] AS
SELECT ...;

بعض النقاط المفيدة التي تستاهل تنتبه لها:

  • IF NOT EXISTS يتجاوز الإنشاء بصمت إذا كان العرض موجودًا أصلًا.
  • TEMPORARY (أو TEMP) ينشئ عرضًا مؤقتًا يختفي بمجرد إغلاق الاتصال.
  • أسماء الأعمدة البديلة بين القوسين تتيح لك إعادة تسمية أعمدة العرض دون الحاجة لتعديل جملة SELECT الأساسية.

يكشف العرض أسماء أوضح (item و dollars) دون الحاجة إلى تغيير أسماء الأعمدة في الجدول الأصلي.

استبدال العروض وحذفها

لا يدعم SQLite الأمر CREATE OR REPLACE VIEW ولا ALTER VIEW، لذا إذا أردت تعديل تعريف أي view، فعليك حذفه ثم إعادة إنشائه من جديد:

DROP VIEW IF EXISTS active_orders; هي الصيغة الآمنة، فهي لا تُسبّب خطأً إذا كان الـ view غير موجود أصلاً. كما أنّ حذف الـ view لا يمسّ الجداول الأصلية بأي شكل، فأنت تحذف الاستعلام المحفوظ فقط لا غير.

العروض المؤقتة (TEMPORARY VIEW) في SQLite

الـ TEMP VIEW يعيش فقط طوال عمر الاتصال الحالي بقاعدة البيانات، فبمجرّد إغلاق الاتصال يختفي العرض تلقائياً. وهذا مفيد جداً في جلسات التحليل السريعة عندما لا ترغب في ترك تعريفات دائمة خلفك:

العروض المؤقتة أيضاً بتسمح لك إنك «تظلِّل» اسم استعلام معيّن من غير ما تثبّته في الـ schema، وده مفيد جدًا وقت الاستكشاف والتجريب.

العروض في SQLite للقراءة فقط افتراضيًا

دي أهم نقطة يجب أن تنتبه لها. ما تقدرش تعمل INSERT أو UPDATE أو DELETE مباشرةً من خلال أي view:

sqlite> INSERT INTO paid_orders (customer, amount) VALUES ('Eve', 50);
Runtime error: لا يمكن تعديل paid_orders لأنه view

الحل هو استخدام مُحفِّزات INSTEAD OF. تكتب مُحفِّزًا (trigger) يعمل بدلًا من محاولة الكتابة، ويترجمها إلى عملية فعلية على الجدول الأصلي:

العرض يبقى عرضًا — لكن عمليات الكتابة عليه صار لها مكان تذهب إليه الآن. سنتناول الـ triggers بالتفصيل في الصفحة التالية.

لا يوجد Materialized Views — اصنعها بنفسك

بعض قواعد البيانات تتيح لك تخزين نتائج الـ view على القرص وتحديثها عند الطلب. SQLite لا يفعل ذلك. كل قراءة من view تعيد تنفيذ الاستعلام الأساسي من جديد. وهذا مقبول في معظم الحالات — فـ SQLite سريع ومخطط الاستعلامات (query planner) فيه جيد. أما إذا كان لديك تجميعات (aggregations) ثقيلة تُستعلم عنها مرارًا وتكرارًا، فالأفضل أن تبني جدولًا حقيقيًا وتتولى مزامنته بنفسك:

ستحتاج بعدها إلى تحديث هذا الـ cache دوريًا، أو ربط triggers على جدول orders للحفاظ على تزامن البيانات. صحيح أنها خطوات يدوية، لكنها الطريقة الوحيدة المتاحة في SQLite.

عرض كل views في SQLite

تُخزَّن بيانات تعريف الـ views داخل sqlite_master جنبًا إلى جنب مع الجداول والفهارس:

عمود sql يُرجِع لك جملة CREATE VIEW الأصلية — مفيد لما تنسى وظيفة الـ view. أما داخل CLI، فالأمر .schema view_name يطبع نفس النتيجة بشكل أنظف.

متى تلجأ لاستخدام view؟

الـ views تستحق العناء في الحالات التالية:

  • لما يكون عندك استعلام غير بسيط وتعيد استخدامه في ثلاثة مواضع أو أكثر. تسميته مرة واحدة أفضل بكثير من نسخه ولصقه في كل مكان.
  • لما تريد كشف مجموعة محددة من الأعمدة أو الصفوف لجزء معين من التطبيق.
  • لما يكون الـ aggregation كياناً مفاهيمياً واحداً (مثل monthly_sales أو active_users) ويُفترض أن يتعامل معه المستهلك كاسم مستقل.

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

  • الاستعلام مستخدم في موضع واحد فقط. اكتبه مباشرة بدون تغليف.
  • الأداء مهم والاستعلام الأساسي مكلف — لأنك ستدفع هذه التكلفة في كل قراءة. الأفضل أن تخزّن النتيجة في جدول حقيقي.
  • الـ view يعتمد على view آخر يعتمد بدوره على view ثالث. SQLite يتعامل مع التداخل بدون مشاكل، لكن سلسلة من ثلاثة أو أربعة views تجعل تتبّع الـ SQL الفعلي أثناء التصحيح أمراً مرهقاً.

التالي: المحفّزات (Triggers)

الـ views والـ triggers يتلازمان كثيراً — فنمط INSTEAD OF الذي يجعل الـ view قابلاً للكتابة هو أحد الأسباب الرئيسية لوجود الـ triggers أصلاً. والـ triggers مفيدة كذلك بمفردها في أمور مثل سجلات التدقيق (audit logging)، والتحديثات المتسلسلة (cascading updates)، وفرض القيود الثابتة (invariants). وهذا موضوع الصفحة التالية.

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

ما هو الـ View في SQLite؟

الـ View هو جملة SELECT محفوظة، تقدر تستعلم منها كأنها جدول عادي. لكنها لا تخزن أي بيانات فعليًا، فكل مرة تقرأ منها يقوم SQLite بإعادة تشغيل الاستعلام الأصلي. فائدتها الأساسية أنها تتيح لك تسمية استعلام معقد واستخدامه في أكثر من مكان، أو إخفاء أعمدة لا يجب أن يصل إليها المستخدم.

هل يمكن تنفيذ INSERT أو UPDATE عبر View في SQLite؟

ليس مباشرة. العروض في SQLite للقراءة فقط، فأي عملية INSERT أو UPDATE أو DELETE على View ستفشل. لكن تقدر تجعلها قابلة للكتابة عن طريق ربطها بمشغلات INSTEAD OF تترجم عملية الكتابة إلى عمليات على الجداول الأصلية.

هل يدعم SQLite العروض المُجسَّدة (Materialized Views)؟

لا. SQLite يوفر فقط العروض العادية (الافتراضية)، أي أن الاستعلام يُنفَّذ في كل مرة تقرأ فيها من الـ View. إذا كنت تحتاج نتائج مخزَّنة فعليًا، أنشئ جدولًا حقيقيًا وحدِّثه يدويًا، أو استخدم Trigger للحفاظ على تزامنه مع الجداول الأصلية.

كيف تعرض قائمة بكل الـ Views في قاعدة بيانات SQLite؟

نفّذ استعلامًا على sqlite_master بهذا الشكل: SELECT name FROM sqlite_master WHERE type = 'view';. ومن سطر الأوامر، يعرض لك الأمر .schema جمل CREATE VIEW كاملة، بينما يعرض .tables العروض جنبًا إلى جنب مع الجداول.

Coddy programming languages illustration

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

ابدأ الآن