في
مقال سابق
، وصفت مفهوم وتنفيذ قاعدة بيانات مبنية على أساس الوظائف ، وليس على الجداول والحقول كما في قواعد البيانات العلائقية. أعطت العديد من الأمثلة التي تبين مزايا هذا النهج على الكلاسيكية. وجد الكثير منهم غير مقنعين بما فيه الكفاية.
في هذه المقالة ، سأبين كيف يتيح لك هذا المفهوم تحقيق التوازن بين الكتابة والقراءة بسرعة وسهولة في قاعدة البيانات دون أي تغيير في منطق العمل. لقد حاولوا تنفيذ وظائف مماثلة في أنظمة إدارة قواعد البيانات التجارية الحديثة (على وجه الخصوص ، Oracle و Microsoft SQL Server). في نهاية المقال ، سأبين ما حدث لهم ، بعبارة ملطفة ، وليس غاية.
وصف
كما كان من قبل ، من أجل فهم أفضل ، سأبدأ الوصف بالأمثلة. لنفترض أننا بحاجة إلى تنفيذ منطق من شأنه أن يعيد قائمة الإدارات بعدد الموظفين فيها ورواتبهم الإجمالية.
في قاعدة البيانات الوظيفية ، ستبدو كما يلي:
سوف يكون تعقيد تنفيذ هذا الاستعلام في أي DBMS معادلًا لـ
O (عدد الموظفين) ، نظرًا لأنك بحاجة إلى مسح جدول الموظفين بالكامل ، ثم تجميعهم حسب القسم. سيكون هناك أيضًا بعض الإضافات الصغيرة (نعتقد أن هناك عددًا أكبر بكثير من الموظفين أكثر من الإدارات) وفقًا للخطة المختارة
O (رقم سجل الموظفين) أو
O (عدد الإدارات) للتجميع وما إلى ذلك.
من الواضح أن النفقات العامة للتنفيذ يمكن أن تكون مختلفة في نظم إدارة قواعد البيانات المختلفة ، لكن التعقيد لن يتغير بأي طريقة.
في التطبيق المقترح ، ستشكل قواعد إدارة قواعد البيانات الوظيفية استعلامًا فرعيًا واحدًا ، والذي سيحسب القيم اللازمة للإدارة ، ثم يقوم بإنشاء JOIN مع جدول القسم للحصول على الاسم. ومع ذلك ، لكل وظيفة ، عند التصريح ، من الممكن تحديد علامة MATERIALIZED خاصة. سيقوم النظام تلقائيًا بإنشاء حقل مناسب لكل وظيفة من هذا القبيل. عندما تتغير قيمة الوظيفة ، ستتغير قيمة الحقل في نفس المعاملة. عند الوصول إلى هذه الوظيفة ، سيتم بالفعل تقديم نداء إلى الحقل المحسوب.
على وجه الخصوص ، إذا قمت بوضع MATERIALIZED لعدد الوظائف ،
فسيتم إضافة
حقلين في الجدول مع قائمة الإدارات التي سيتم فيها تخزين عدد الموظفين
ورواتبهم الإجمالية. مع أي تغيير في الموظفين أو رواتبهم أو انتمائهم إلى الإدارات ، سيغير النظام تلقائيًا قيم هذه الحقول. سيبدأ الاستعلام أعلاه في الوصول إلى هذه الحقول مباشرةً وسيتم تنفيذه على
O (عدد الأقسام) .
ما هي القيود؟ شيء واحد فقط: يجب أن تحتوي هذه الوظيفة على عدد محدد من قيم الإدخال التي يتم تحديد قيمتها الخاصة بها. وإلا ، فسيكون من المستحيل إنشاء جدول يخزن جميع قيمه ، حيث لا يمكن أن يكون هناك جدول به عدد لا حصر له من الصفوف.
مثال:
يتم تعريف هذه الوظيفة لعدد لا حصر له من قيم الرقم N (على سبيل المثال ، أي قيمة سلبية مناسبة). لذلك ، لا يمكن وضعه مواد. وبالتالي ، يعد هذا عائقًا منطقيًا وليس تقنيًا (أي ، ليس لأننا لم نتمكن من تنفيذ هذا). خلاف ذلك ، لا قيود. يمكنك استخدام التجميع والفرز و AND و OR ، PARTITION ، التكرار ، إلخ.
على سبيل المثال ، في المهمة 2.2 من المقالة السابقة ، يمكنك وضع MATERIALIZED على كلتا الوظيفتين:
سيقوم النظام نفسه بإنشاء جدول واحد مع مفاتيح أنواع
العملاء والمنتج و
INTEGER ، وإضافة حقلين إليه وتحديث قيم الحقل فيها مع أي تغييرات. عند إجراء المزيد من المكالمات لهذه الوظائف ، لن يتم حسابها ، ولكن سيتم قراءة القيم من الحقول المقابلة.
باستخدام هذه الآلية ، يمكنك ، على سبيل المثال ، التخلص من العودية (CTE) في الاستعلامات. على وجه الخصوص ، ضع في اعتبارك المجموعات التي تتألف منها الشجرة باستخدام علاقة الطفل / الوالد (كل مجموعة لها رابط إلى والدها):
في قاعدة بيانات وظيفية ، يمكن تعريف منطق العودية كما يلي:
نظرًا لأن MATERIALIZED مُلصقة على الدالة
isParent ،
فسيتم إنشاء جدول به مفتاحان (مجموعة) له ، يكون
فيه الحقل
isParent صحيحًا فقط إذا كان المفتاح الأول هو سليل الثاني. سيكون عدد الإدخالات في هذا الجدول مساوياً لعدد المجموعات التي تضاعف متوسط عمق الشجرة. إذا كان ذلك ضروريًا ، على سبيل المثال ، لحساب عدد أحفاد مجموعة معينة ، فيمكنك الوصول إلى هذه الوظيفة:
لن يكون هناك CTE في استعلام SQL. بدلاً من ذلك ، سيكون هناك GROUP BY بسيط.
باستخدام هذه الآلية ، يمكنك أيضًا إزالة قاعدة البيانات بسهولة إذا لزم الأمر:
عند استدعاء دالة
التاريخ لسطر الطلب ، ستكون القراءة من الجدول مع خطوط ترتيب للحقل الذي يوجد فهرس له. عند تغيير تاريخ الطلب ، سيقوم النظام تلقائيًا بإعادة حساب التاريخ غير الطبيعي في السطر.
الفوائد
لماذا هذه الآلية كلها مطلوبة؟ في DBMSs الكلاسيكية ، بدون إعادة كتابة الاستعلامات ، يمكن للمطور أو DBA فقط تغيير الفهارس وتحديد الإحصائيات وإخبار مخطط الاستعلام عن كيفية تنفيذها (علاوة على ذلك ، تتوفر HINTs فقط في DBMSs التجارية). بغض النظر عن مدى صعوبة المحاولة ، فلن يتمكنوا من تلبية الطلب الأول في المقالة لـ
O (عدد الأقسام) دون تغيير الطلبات وإضافة المشغلات. في المخطط المقترح ، في مرحلة التطوير ، لا يتعين عليك التفكير في بنية تخزين البيانات والتجمعات التي يجب استخدامها. كل هذا يمكن تغييره بسهولة على الطاير ، مباشرة في العملية.
في الممارسة العملية ، وهذا هو على النحو التالي. يطور بعض الأشخاص المنطق استنادًا إلى المهمة. ليست على دراية بالخوارزميات وتعقيداتها ، ولا في خطط التنفيذ ، ولا في أنواع join'ov ، ولا في أي مكون تقني آخر. هؤلاء الناس هم أكثر المحللين الأعمال من المطورين. ثم ، كل شيء يذهب إلى الاختبار أو العملية. يتم تمكين تسجيل الاستعلامات الطويلة. عند اكتشاف طلب طويل ، يقرر أشخاص آخرون (أكثر تقنية - في الواقع DBA) تضمين MATERIALIZED في بعض الوظائف الوسيطة. وبالتالي ، يتم إبطاء التسجيل قليلاً (نظرًا لأن تحديث حقل إضافي في معاملة مطلوب). ومع ذلك ، لا يتم تسريع هذا الطلب بشكل كبير ، ولكن أيضًا كل الطلبات الأخرى التي تستخدم هذه الوظيفة. في نفس الوقت ، يكون اتخاذ قرار بشأن الوظيفة المحددة التي يجب تحقيقها أمرًا بسيطًا نسبيًا. معلمتان أساسيتان: عدد قيم المدخلات المحتملة (بالضبط عدد السجلات التي ستكون في الجدول المقابل) ، وعدد مرات استخدامها في وظائف أخرى.
النظير
DBMSs التجارية الحديثة لديها آليات مماثلة: عرض المواد مع التحديث السريع (Oracle) و INDEXED VIEW (Microsoft SQL Server). في PostgreSQL MATERIALIZED VIEW ، لا يمكن التحديث في معاملة ، ولكن فقط عند الطلب (وحتى مع وجود قيود صارمة للغاية) ، لذلك نحن لا نعتبر ذلك. ولكن لديهم العديد من المشاكل ، مما يحد كثيرا من استخدامها.
أولاً ، لا يمكنك تمكين التجسيد إلا إذا كنت قد أنشأت بالفعل عرضًا منتظمًا. وإلا ، فسيتعين عليك إعادة كتابة الطلبات المتبقية للوصول إلى العرض الذي تم إنشاؤه حديثًا لاستخدام هذا التجسيد. أو اترك كل شيء كما هو ، ولكن سيكون على الأقل غير فعال إذا كانت هناك بعض البيانات المحسوبة بالفعل ، ولكن العديد من الاستعلامات لا تستخدمها دائمًا ، ولكن يتم حسابها مرة أخرى.
ثانياً ، لديهم عدد كبير من القيود:
وحي5.3.8.4 القيود العامة على التحديث السريع
يقتصر الاستعلام المحدد في العرض المادي على النحو التالي:
- يجب ألا يحتوي العرض المادي على إشارات إلى تعبيرات غير مكررة مثل
SYSDATE
و SYSDATE
. - يجب ألا يحتوي العرض المادي على مراجع لأنواع بيانات
RAW
أو LONG
RAW
. - لا يمكن أن يحتوي على استعلام فرعي لقائمة
SELECT
. - لا يمكن أن يحتوي على وظائف تحليلية (على سبيل المثال ، تصنيف) في جملة
SELECT
. - لا يمكن الرجوع إلى جدول يتم تعريف فهرس
XMLIndex
. - لا يمكن أن تحتوي على جملة
MODEL
. - لا يمكن أن يحتوي على جملة
HAVING
مع استعلام فرعي. - لا يمكن أن يحتوي على استعلامات متداخلة لها
ANY
أو EXISTS
أو NOT
EXISTS
. - لا يمكن أن يحتوي على جملة
[START WITH …] CONNECT BY
. - لا يمكن أن يحتوي على جداول تفاصيل متعددة في مواقع مختلفة.
- لا يمكن أن تحتوي طرق العرض
COMMIT
ON
COMMIT
ON
جداول تفصيلية عن بُعد. - يجب أن تحتوي طرق العرض المادية المتداخلة على صلة أو مجمعة.
- لا يمكن تحديد طرق عرض الصلة الملموسة وطرق العرض التجميعية المضمّنة مع جملة
GROUP
BY
من جدول منظم بالفهرس.
5.3.8.5 القيود المفروضة على التحديث السريع على طرق العرض المادية باستخدام الصلات فقط
تحديد استعلامات طرق العرض المادية مع الصلات فقط وليس هناك أي تجميعات القيود التالية على التحديث السريع:
- جميع القيود المفروضة على " القيود العامة على التحديث السريع ".
- لا يمكن أن تحتوي على
GROUP
BY
أو مجاميع. - يجب أن تظهر Rowids من جميع الجداول في قائمة
FROM
في قائمة SELECT
الاستعلام. - يجب أن توجد سجلات العرض الملموسة مع rowids لكل الجداول الأساسية في قائمة
FROM
للاستعلام. - لا يمكنك إنشاء طريقة عرض سريعة قابلة للتحديث من جداول متعددة مع صلات بسيطة تتضمن عمود نوع كائن في
SELECT
.
أيضًا ، لن تكون طريقة التحديث التي تختارها فعالة على النحو الأمثل إذا:
- يستخدم الاستعلام المحدد صلة خارجية تتصرف مثل صلة داخلية. إذا كان الاستعلام المحدد يحتوي على مثل هذا الصلة ، ففكر في إعادة كتابة الاستعلام المحدد ليتضمن صلة داخلية.
- تحتوي قائمة
SELECT
للعرض المادي على تعبيرات على أعمدة من جداول متعددة.
5.3.8.6 القيود المفروضة على التحديث السريع على المشاهدات المادية مع المجاميع
تحديد استعلامات طرق العرض الملموسة مع التجميعات أو الصلات لها القيود التالية على التحديث السريع:
يتم دعم التحديث السريع لكلا COMMIT
ON
COMMIT
و ON
DEMAND
، ولكن تنطبق القيود التالية:
- يجب أن تحتوي جميع الجداول في طريقة العرض الملموسة على سجلات عرض مادية ، ويجب أن تكون سجلات المشاهدة الموضحة:
- احتواء جميع الأعمدة من الجدول المشار إليه في طريقة العرض الملموسة.
- حدد مع
ROWID
INCLUDING
VALUES
NEW
. - حدد جملة
SEQUENCE
إذا كان من المتوقع أن يحتوي الجدول على مزيج من عمليات الإدراج / التحميل المباشر ، الحذف ، والتحديثات.
- يتم دعم
SUM
و COUNT
و AVG
و VARIANCE
و VARIANCE
و MIN
و MAX
فقط للتحديث السريع. - يجب تحديد
COUNT(*)
. - يجب أن تحدث الدالات التجميعية فقط باعتبارها أقصى جزء من التعبير. أي أنه لا يُسمح بتجميعات مثل
AVG(AVG(x))
أو AVG(x)
+ AVG(x)
. - لكل مجموعة مثل
AVG(expr)
، يجب أن يكون COUNT(expr)
المقابل موجودًا. توصي Oracle بتحديد SUM(expr)
. - إذا تم تحديد
VARIANCE(expr)
أو STDDEV(expr
) ، فيجب تحديد COUNT(expr)
و SUM(expr)
. توصي Oracle بتحديد SUM(expr *expr)
. - لا يمكن أن يكون العمود
SELECT
في استعلام التعريف تعبيرًا معقدًا مع أعمدة من جداول أساسية متعددة. للمشكلة المحتملة لهذا استخدام طريقة عرض المتداخلة المتداخلة. - يجب أن تحتوي قائمة
SELECT
على جميع أعمدة GROUP
BY
. - طريقة العرض الملموسة لا تستند إلى جدول بعيد أو أكثر.
- إذا كنت تستخدم نوع بيانات
CHAR
في أعمدة التصفية في سجل عرض ملموس ، فيجب أن تكون مجموعات الأحرف في الموقع الرئيسي وطريقة العرض الملموسة هي نفسها. - إذا كان العرض المادي يحتوي على واحد مما يلي ، فلن يتم دعم التحديث السريع إلا في عمليات إدراج DML التقليدية والأحمال المباشرة.
- المشاهدات المادية مع مجاميع
MIN
أو MAX
- المشاهدات المادية التي تحتوي على
SUM(expr)
ولكن لا تحتوي على COUNT(expr)
- المشاهدات المادية دون
COUNT(*)
تسمى طريقة العرض الملموسة هذه طريقة عرض يتم إدراجها فقط. - طريقة العرض
MAX
مع MAX
أو MIN
قابلة للتحديث بسرعة بعد حذف أو خلط بيانات DML إذا لم يكن لها WHERE
.
لا يكون للتحديث السريع كحد أقصى / دقيقة بعد الحذف أو DML المختلط نفس سلوك حالة الإدراج فقط. يقوم بحذف وإعادة حساب القيم القصوى / الدقيقة للمجموعات المتأثرة. يجب أن تكون مدركًا لتأثير أدائها. - يمكن تحديث طرق العرض المادية مع طرق العرض المسماة أو الاستعلامات الفرعية في جملة
FROM
بشرط أن يتم دمج طرق العرض بالكامل. للحصول على معلومات حول طرق العرض التي سيتم دمجها ، راجع مرجع لغة Oracle Database SQL . - إذا لم تكن هناك روابط خارجية ، فقد يكون لديك اختيارات تعسفية ووصلات في
WHERE
. - يمكن تجديد طرق العرض التجميعية المادية مع الوصلات الخارجية بسرعة بعد DML التقليدية والأحمال المباشرة ، بشرط تعديل الجدول الخارجي فقط. أيضًا ، يجب أن توجد قيود فريدة على أعمدة الصلة بجدول الصلة الداخلي. إذا كان هناك روابط خارجية ، فيجب أن تكون جميع الروابط متصلة بواسطة
AND
ويجب أن تستخدم عامل المساواة ( =
). - بالنسبة إلى طرق
ROLLUP
باستخدام CUBE
أو ROLLUP
أو مجموعات التجميع أو متسلسلة لها ، يتم تطبيق القيود التالية:
- يجب أن تحتوي قائمة
SELECT
على أداة تمييز للتجميع يمكن أن تكون إما دالة GROUPING_ID
في جميع تعبيرات GROUP
BY
أو وظائف GROUPING
واحدة لكل تعبير GROUP
BY
. على سبيل المثال ، إذا كانت جملة GROUP
BY
في المشاهدة CUBE(a, b)
هي " GROUP
BY
CUBE(a, b)
" ، فيجب أن تحتوي قائمة SELECT
إما على " GROUPING_ID(a, b)
" أو " GROUPING(a)
AND
GROUPING(b)
"لتجسد طريقة العرض المراد تحديثها بسرعة. - يجب ألا ينتج عن
GROUP
BY
أي تجمعات مكررة. على سبيل المثال ، " GROUP BY a, ROLLUP(a, b)
" ليست قابلة للتحديث السريع لأنها تؤدي إلى تجمعات مكررة " (a), (a, b), AND (a)
".
5.3.8.7 القيود المفروضة على التحديث السريع على المشاهدات المادية مع UNION ALL
المشاهدات المادية مع المشغل UNION
ALL
تدعم خيار REFRESH
FAST
إذا تم استيفاء الشروط التالية:
لا أريد الإساءة إلى معجبي Oracle ، ولكن استنادًا إلى قائمة القيود الخاصة بهم ، يبدو أن هذه الآلية لم تتم كتابتها في الحالة العامة باستخدام نوع من النماذج ، ولكن الآلاف من الهنود ، حيث سُمح للجميع بكتابة سلسلة الرسائل الخاصة بهم ، ويمكن لكل منهم وفعل. استخدام هذه الآلية لمنطق حقيقي يشبه المشي في حقل ألغام. في أي وقت ، يمكنك الحصول على منجم ، وضرب أحد القيود غير الواضحة. كيف يعمل هذا أيضًا مسألة منفصلة ، لكنها خارج نطاق هذه المقالة.
مايكروسوفت مزود خادممتطلبات إضافية
بالإضافة إلى خيارات SET ومتطلبات الوظيفة الحتمية ، يجب تلبية المتطلبات التالية:
- يجب أن يكون المستخدم الذي يقوم بتنفيذ
CREATE INDEX
هو مالك العرض. - عند إنشاء الفهرس ، يجب تعيين الخيار
IGNORE_DUP_KEY
على OFF (الإعداد الافتراضي). - يجب الرجوع إلى الجداول بأسماء من جزأين ، المخطط . tablename في تعريف العرض.
- يجب إنشاء الوظائف المعرفة من قبل المستخدم المشار إليها في طريقة العرض باستخدام خيار
WITH SCHEMABINDING
. - يجب الرجوع إلى أي وظائف معرفة من قِبل المستخدم والمشار إليها في العرض بأسماء من جزأين ، <schema> . <وظيفة> .
- يجب أن تكون خاصية الوصول إلى البيانات الخاصة بوظيفة معرفة من قبل المستخدم
NO SQL
، ويجب أن تكون خاصية الوصول الخارجي NO
. - يمكن أن تظهر وظائف وقت تشغيل اللغة العامة (CLR) في قائمة تحديد طريقة العرض ، ولكن لا يمكن أن تكون جزءًا من تعريف مفتاح الفهرس المجمع. لا يمكن أن تظهر وظائف CLR في جملة WHERE للعرض أو جملة ON لعملية JOIN في المشاهدة.
- يجب أن يكون لوظائف وطرق CLR للأنواع المعرفة من قبل المستخدم والمستخدمة في تعريف العرض الخصائص المحددة كما هو موضح في الجدول التالي.
- يجب إنشاء العرض باستخدام خيار
WITH SCHEMABINDING
. - يجب أن يشير العرض إلى الجداول الأساسية الموجودة في نفس قاعدة البيانات مثل طريقة العرض. لا يمكن للعرض الرجوع إلى طرق عرض أخرى.
- يجب ألا تحتوي عبارة SELECT في تعريف العرض على عناصر Transact-SQL التالية:
1 يمكن أن تحتوي طريقة العرض المفهرسة على أعمدة عائمة . ومع ذلك ، لا يمكن تضمين هذه الأعمدة في مفتاح الفهرس متفاوت المسافات. - في حالة وجود
GROUP BY
، يجب أن يحتوي تعريف VIEW على COUNT_BIG(*)
ويجب ألا يحتوي على HAVING
. تنطبق قيود GROUP BY
فقط على تعريف طريقة العرض المفهرسة. يمكن أن يستخدم الاستعلام طريقة عرض مفهرسة في خطة التنفيذ الخاصة به ، حتى لو لم يكن مستوفياً لقيود GROUP BY
هذه. - إذا كان تعريف طريقة العرض يحتوي على جملة
GROUP BY
، فيمكن لمفتاح الفهرس العنقودي الفريد الإشارة إلى الأعمدة المحددة في جملة GROUP BY
.
هنا يمكنك أن ترى أن الهنود لم ينجذبوا ، لأنهم قرروا أن يفعلوا وفقًا للمخطط "سوف نفعل القليل ، ولكن الخير". أي أن لديهم المزيد من الألغام في الميدان ، لكن موقعها أكثر شفافية. الشيء الأكثر إثارة للحزن هو هذا القيد:
يجب أن يشير العرض إلى الجداول الأساسية الموجودة في نفس قاعدة البيانات مثل طريقة العرض. لا يمكن للعرض الرجوع إلى طرق عرض أخرى.
في مصطلحاتنا ، هذا يعني أن الوظيفة لا يمكنها الوصول إلى وظيفة أخرى ملموسة. إنها تقطع الأيديولوجية كلها في مهدها.
أيضًا ، يقلل هذا القيد (وكذلك في النص) بشكل كبير من حالات الاستخدام:
يجب ألا تحتوي عبارة SELECT في تعريف العرض على عناصر Transact-SQL التالية:
يحظر الانضمام إلى الخارج والاتحاد والنظم BY وغيرها. ربما كان من السهل الإشارة إلى ما يمكن استخدامه أكثر من غيره. القائمة ربما تكون أصغر بكثير.
لتلخيص: مجموعة كبيرة من القيود في كل (لاحظت التجارية) DBMS مقابل لا شيء (باستثناء واحد منطقي وليس تقني) في تقنية LGPL. ومع ذلك ، تجدر الإشارة إلى أن تنفيذ هذه الآلية في المنطق العلائقي أكثر تعقيدًا إلى حد ما مما هو عليه في الوظيفة الموصوفة.
تطبيق
كيف يعمل؟ يستخدم بوستجرس ك "آلة افتراضية". يوجد في الداخل خوارزمية معقدة تبني الاستفسارات. هنا هو
شفرة المصدر . وليس هناك مجرد مجموعة كبيرة من الاستدلال مع مجموعة من ifs. لذلك ، إذا كان لديك بضعة أشهر للدراسة ، فيمكنك محاولة فهم الهندسة المعمارية.
هل تعمل بكفاءة؟ فعال بما فيه الكفاية. لسوء الحظ ، إثبات هذا صعب. لا أستطيع إلا أن أقول إنك إذا نظرت في آلاف الطلبات الموجودة في التطبيقات الكبيرة ، فستكون في المتوسط أكثر فاعلية من المطور الجيد. يمكن لمبرمج SQL ممتاز كتابة أي استعلام بشكل أكثر كفاءة ، ولكن مع وجود ألف استفسار ، لن يكون لديه أي دافع أو وقت للقيام بذلك. الشيء الوحيد الذي يمكنني الآن تقديمه كدليل على الفعالية هو أنه على أساس المنصة المبنية على قواعد البيانات هذه ، تعمل العديد
من مشاريع
نظام ERP التي يوجد فيها الآلاف من وظائف MATERIALIZED المختلفة ، مع الآلاف من المستخدمين وقواعد بيانات terrabyte مع مئات الملايين من السجلات العاملة على خادم ثنائي المعالج العادية. ومع ذلك ، يمكن لأي شخص اختبار / دحض الفعالية عن طريق تنزيل
النظام الأساسي و PostgreSQL ،
مما يتيح تسجيل استعلام SQL ومحاولة تغيير المنطق والبيانات هناك.
في المقالات التالية ، سأتحدث أيضًا عن كيفية تعليق القيود على الوظائف ، والعمل مع جلسات التغيير ، وغير ذلك الكثير.