الفرق بين المراجعتين لصفحة: «Python/sqlite3»
أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:الوحدة <code>sqlite3</code> في بايثون}}</noinclude> SQLite هي مكتبة مكتوبة بلغة C تتيح إنشاء قواع...' |
لا ملخص تعديل |
||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:الوحدة <code>sqlite3</code> في بايثون}}</noinclude> | <noinclude>{{DISPLAYTITLE:الوحدة <code>sqlite3</code> في بايثون}}</noinclude> | ||
SQLite هي مكتبة مكتوبة بلغة C تتيح إنشاء قواعد بيانات على القرص الصلب ولا تحتاج إلى خادوم خاص لمعالجتها، وتتيح الوصول إلى قاعدة البيانات باستخدام نسخة غير قياسية من لغة الاستعلام SQL. | SQLite هي مكتبة مكتوبة بلغة C تتيح إنشاء قواعد بيانات على القرص الصلب ولا تحتاج إلى خادوم خاص لمعالجتها، وتتيح الوصول إلى قاعدة البيانات باستخدام نسخة غير قياسية من لغة الاستعلام [[SQL]]. | ||
تستخدم بعض التطبيقات والبرامج قاعدة بيانات SQLite لتخزين بياناتها الداخلية، ويمكن إنشاء نماذج أولية من التطبيق باستخدام SQLite ثم نقل الشيفرة إلى قواعد بيانات أكبر مثل PostgreSQL أو Oracle. | تستخدم بعض التطبيقات والبرامج قاعدة بيانات SQLite لتخزين بياناتها الداخلية، ويمكن إنشاء نماذج أولية من التطبيق باستخدام SQLite ثم نقل الشيفرة إلى قواعد بيانات أكبر مثل PostgreSQL أو Oracle. | ||
كُتبت وحدة sqlite3 من قبل Gerhard Häring، وتقدّم واجهة SQL متوافقة مع معايير DB-API 2.0 الموصوفة في PEP 249. | كُتبت وحدة <code>sqlite3</code> من قبل Gerhard Häring، وتقدّم واجهة [[SQL]] متوافقة مع معايير DB-API 2.0 الموصوفة في [https://www.python.org/dev/peps/pep-0249 PEP 249]. | ||
لاستخدام هذه الوحدة يجب إنشاء كائن اتصال Connection يمثّل قاعدة البيانات. يبين المثال التالي طريقة استخدام الوحدة مع افتراض أن البيانات مخزّنة في ملف باسم example.db. | == الاتصال بقاعدة بيانات SQLite == | ||
لاستخدام هذه الوحدة يجب إنشاء كائن اتصال <code>Connection</code> يمثّل قاعدة البيانات. يبين المثال التالي طريقة استخدام الوحدة مع افتراض أن البيانات مخزّنة في ملف باسم <code>example.db</code>. | |||
<syntaxhighlight lang="python3"> | <syntaxhighlight lang="python3"> | ||
سطر 14: | سطر 15: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
يمكن كذلك استخدام الاسم الخاص :memory: لإنشاء قاعدة البيانات في ذاكرة الوصول العشوائي RAM. | يمكن كذلك استخدام الاسم الخاص <code>:memory:</code> لإنشاء قاعدة البيانات في ذاكرة الوصول العشوائي RAM. | ||
بعد إجراء الاتصال مع قاعدة البيانات يمكن إنشاء كائن مؤشر Cursor واستدعاء التابع execute() لتنفيذ أوامر SQL: | بعد إجراء الاتصال مع قاعدة البيانات يمكن إنشاء كائن مؤشر <code>Cursor</code> واستدعاء التابع <code>[[Python/sqlite3/cursor/execute|execute()]]</code> لتنفيذ أوامر [[SQL]]: | ||
<syntaxhighlight lang="python3"> | <syntaxhighlight lang="python3"> | ||
سطر 34: | سطر 35: | ||
# ولكن يجب التأكد من حفظ جميع التعديلات تجنبًا لفقدانها كلّها | # ولكن يجب التأكد من حفظ جميع التعديلات تجنبًا لفقدانها كلّها | ||
conn.close() | conn.close() | ||
</syntaxhighlight>تكون البيانات المحفوظة من النوع المستمر persistent وهي متاحة للاستخدام في الجلسات اللاحقة:<syntaxhighlight lang="python3"> | |||
تكون البيانات المحفوظة من النوع المستمر persistent وهي متاحة للاستخدام في الجلسات اللاحقة: | |||
import sqlite3 | import sqlite3 | ||
conn = sqlite3.connect('example.db') | conn = sqlite3.connect('example.db') | ||
c = conn.cursor() | c = conn.cursor() | ||
</syntaxhighlight> | </syntaxhighlight>ستحتاج في العادة إلى استخدام القيم المخزّنة في متغيرات بايثون لإجراء [[SQL|عمليات SQL]]، ولكن عليك أن تتجنب استخدام [[Python/str|سلاسل بايثون النصية]] لإنشاء أوامر الاستعلام عن البيانات لأنّ ذلك غير آمن، إذ يكون برنامجك عرضة لهجمات حقن SQL. | ||
ينصح باستخدام معامل الاستبدال الخاصّ بواجهة DB-API، حيث يوضع الرمز <code>?</code> عوضًا عن القيم التي تريد إدراجها في جملة الاستعلام، ثم تزويد تابع <code>execute()</code> بمعامل ثانٍ يكون على هيئة [[Python/tuple|صفّ tuple]] يتضمّن تلك القيم حسب ترتيبها في جملة الاستعلام. (قد تستخدم وحدات قواعد البيانات الأخرى رموز مختلفة، مثل <code>%s</code> أو <code>:1</code>). فعلى سبيل المثال: | |||
ينصح باستخدام معامل الاستبدال الخاصّ بواجهة DB-API، حيث يوضع الرمز ? عوضًا عن القيم التي تريد إدراجها في جملة الاستعلام، ثم تزويد تابع execute() بمعامل ثانٍ يكون على هيئة صفّ يتضمّن تلك القيم حسب ترتيبها في جملة الاستعلام. (قد تستخدم وحدات قواعد البيانات الأخرى رموز مختلفة، مثل %s أو :1). فعلى سبيل المثال: | |||
<syntaxhighlight lang="python3"> | <syntaxhighlight lang="python3"> | ||
سطر 64: | سطر 61: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
بعد تنفيذ جملة الاستعلام SELECT يمكن استرجاع البيانات إمّا عن طريق التعامل مع المؤشر كمكرِّر iterator، أو استدعاء التابع fetchone() لاسترجاع صفّ واحد فقط، أو استدعاء التابع fetchall() للحصول على قائمة بالصفوف المطابقة. | بعد تنفيذ جملة الاستعلام [[SQL/select|SELECT]] يمكن استرجاع البيانات إمّا عن طريق التعامل مع المؤشر كمكرِّر iterator، أو استدعاء التابع <code>fetchone()</code> لاسترجاع صفّ row واحد فقط، أو استدعاء التابع <code>fetchall()</code> للحصول على قائمة بالصفوف rows المطابقة. | ||
يستخدم المثال التالي طريقة المكرِّر: | يستخدم المثال التالي طريقة المكرِّر: | ||
سطر 78: | سطر 75: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== ثوابت الوحدة sqlite | == ثوابت الوحدة sqlite == | ||
تقدّم وحدة sqlite الثوابت التالية: | تقدّم وحدة <code>sqlite</code> الثوابت التالية: | ||
sqlite3.version | |||
=== الثابت <code>sqlite3.version</code> === | |||
رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة سلسلة نصية. | رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة سلسلة نصية. | ||
sqlite3.version_info | === الثابت <code>sqlite3.version_info</code> === | ||
رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة صفّ من الأعداد الصحيحة. | رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة صفّ من الأعداد الصحيحة. | ||
sqlite3.sqlite_version | === الثابت <code>sqlite3.sqlite_version</code> === | ||
رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة سلسلة نصية. | رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة سلسلة نصية. | ||
sqlite3.sqlite_version_info | === الثابت <code>sqlite3.sqlite_version_info</code> === | ||
رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة صفّ من الأعداد الصحيحة. | رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة صفّ من الأعداد الصحيحة. | ||
sqlite3.PARSE_DECLTYPES | === الثابت <code>sqlite3.PARSE_DECLTYPES</code> === | ||
يستخدم هذا الثابت مع معامل detect_types في دالة connect(). | يستخدم هذا الثابت مع معامل <code>detect_types</code> في دالة <code>connect()</code>. | ||
تفسر وحدة sqlite3 -عند تعيين قيمة لهذا الثابت- الأنواع المصرّح عنها لكل عمود تعيده. تفسّر الوحدة أول كلمة في النوع المصرّح عنه، أي تفسر النوع "integer primary key" إلى "integer"، والنوع "number(10)" إلى "number". ثم تبحث الوحدة في قاموس المحوّلات عن الدالة المحوّلة المسجَّلة لذلك النوع. | تفسر وحدة <code>sqlite3</code> -عند تعيين قيمة لهذا الثابت- الأنواع المصرّح عنها لكل عمود تعيده. تفسّر الوحدة أول كلمة في النوع المصرّح عنه، أي تفسر النوع <code>"integer primary key"</code> إلى <code>"integer"</code>، والنوع <code>"number(10)"</code> إلى <code>"number"</code>. ثم تبحث الوحدة في قاموس المحوّلات عن الدالة المحوّلة المسجَّلة لذلك النوع. | ||
sqlite3.PARSE_COLNAMES | === الثابت <code>sqlite3.PARSE_COLNAMES</code> === | ||
يستخدم هذا الثابت مع معامل detect_types في دالة connect(). | يستخدم هذا الثابت مع معامل <code>detect_types</code> في دالة <code>connect</code>(). | ||
تفسّر واجهة SQLite -عند تعيين قيمة لهذا الثابت- اسم العمود لكل عمود تعيده. | تفسّر واجهة SQLite -عند تعيين قيمة لهذا الثابت- اسم العمود لكل عمود تعيده. | ||
ستبحث الواجهة عن سلسلة نصية بهيئة [mytype] في جملة الاستعلام لتقرّر أن العمود هو من نوع 'mytype'. ستحاول الواجهة البحث عن مدخل من نوع 'mytype' في قاموس المحوّلات ثم تستخدم الدالة المحوّلة التي تجدها لإعادة القيمة. | ستبحث الواجهة عن سلسلة نصية بهيئة <code>[mytype]</code> في جملة الاستعلام لتقرّر أن العمود هو من نوع <code>'mytype'</code>. ستحاول الواجهة البحث عن مدخل من نوع <code>'mytype'</code> في قاموس المحوّلات ثم تستخدم الدالة المحوّلة التي تجدها لإعادة القيمة. | ||
يكون اسم العمود الموجود في Cursor.description مقصورًا على الكلمة الأولى من اسم العمود، بمعنى أنّه لو استخدمت | يكون اسم العمود الموجود في <code>Cursor.description</code> مقصورًا على الكلمة الأولى من اسم العمود، بمعنى أنّه لو استخدمت مثلًا العبارة <code>'as "x [datetime]"'</code> في [[SQL]]، فإنّها ستفسّر إلى حين الوصول إلى أول فراغ في اسم العمود، وبهذا يصبح اسم العمود هو <code>"x"</code> فقط. | ||
الاستثناءات | == الاستثناءات في وحدة <code>sqlite3</code> == | ||
=== الاستثناء <code>sqlite3.Warning</code> === | |||
صنف متفرّع من الصنف Exception. | صنف متفرّع من الصنف <code>[[Python/exceptions|Exception]]</code>. | ||
=== الاستثناء <code>sqlite3.Error</code> === | |||
الصنف الأساسي لبقية الاستثناءات في هذه الوحدة، وهو صنف متفرّع من الصنف <code>[[Python/exceptions|Exception]]</code>. | |||
الصنف الأساسي لبقية الاستثناءات في هذه الوحدة، وهو صنف متفرّع من الصنف Exception. | |||
=== الاستثناء <code>sqlite3.DatabaseError</code> === | |||
يطلق هذا الاستثناء عند حدوث الأخطاء المتعلّقة بقاعدة البيانات. | يطلق هذا الاستثناء عند حدوث الأخطاء المتعلّقة بقاعدة البيانات. | ||
=== الاستثناء <code>sqlite3.IntegrityError</code> === | |||
يطلق هذا الاستثناء عند حدوث خلل في العلاقات التي تربط بين جداول قاعدة البيانات، كحدوث خلل في المفتاح الخارجي foreign key. هذا الاستثناء متفرّع من الصنف <code>DatabaseError</code>. | |||
يطلق هذا الاستثناء عند حدوث خلل في العلاقات التي تربط بين جداول قاعدة البيانات، كحدوث خلل في المفتاح الخارجي foreign key. هذا الاستثناء متفرّع من الصنف DatabaseError. | |||
يُطلق هذا الاستثناء عند | === الاستثناء <code>sqlite3.ProgrammingError</code> === | ||
يُطلق هذا الاستثناء عند حدوث أخطاء برمجية، مثل عدم العثور على الجدول المحدّد أو وجود الجدول المراد إنشاؤه أصلًا، أو وجود خلل في جمل [[SQL]]، أو تحديد عدد خاطئ من المعاملات... الخ. هذا الاستثناء متفرّع من الصنف <code>DatabaseError</code>. | |||
=== الاستثناء <code>sqlite3.OperationalError</code> === | |||
يُطلق هذا الاستثناء عند حدوث الأخطاء المتعلّقة بالعمليات الخاصّة بقواعد البيانات والتي لا تكون بالضرورة تحت سيطرة المبرمج، مثل: انقطاع الاتصال بقاعدة البيانات على نحو مفاجئ، أو عدم العثور على اسم مصدر البيانات، أو تعذّر معالجة إجراء معيّن... الخ. هذا الاستثناء متفرّع من الصنف <code>DatabaseError</code>. | |||
=== الاستثناء <code>sqlite3.NotSupportedError</code> === | |||
يُطلق هذا الاستثناء عند استخدام تابع أو واجهة برمجية لقواعد البيانات لا تدعمها قاعدة البيانات الحالية، مثل: استدعاء التابع <code>rollback()</code> مع اتصال لا يدعم الإجراءات transaction أو أنّ الإجراءات تكون مغلقة. هذا الاستثناء متفرّع من الصنف <code>DatabaseError</code>. | |||
== استخدام sqlite3 بكفاءة == | == استخدام sqlite3 بكفاءة == | ||
=== استخدام التوابع المختصرة === | === استخدام التوابع المختصرة === | ||
يؤدي استخدام التوابع غير المعيارية execute() و executemany() و executescript() في كائن Connection إلى اختصار الشيفرة البرمجية المكتوبة نظرًا لانتفاء الحاجة إلى إنشاء كائن المؤشر Cursor والذي يكون في كثير من الأحيان زائدًا عن الحاجة. | يؤدي استخدام التوابع غير المعيارية <code>execute()</code> و <code>executemany()</code> و <code>executescript()</code> في كائن <code>[[Python/connection|Connection]]</code> إلى اختصار الشيفرة البرمجية المكتوبة نظرًا لانتفاء الحاجة إلى إنشاء كائن المؤشر [[Python/cursor|<code>Cursor</code>]] والذي يكون في كثير من الأحيان زائدًا عن الحاجة. | ||
عوضًا عن ذلك، يجري إنشاء كائن Cursor ضمنيًا وتعيد هذه التوابع المختصرة كائنات المؤشر، وهكذا يمكنك تنفيذ جملة SELECT والمرور على النتائج مباشرة وعن طريق تنفيذ استدعاء واحد فقط على كائن الاتصال. | عوضًا عن ذلك، يجري إنشاء كائن [[Python/cursor|<code>Cursor</code>]] ضمنيًا وتعيد هذه التوابع المختصرة كائنات المؤشر، وهكذا يمكنك تنفيذ جملة <code>[[SQL/select|SELECT]]</code> والمرور على النتائج مباشرة وعن طريق تنفيذ استدعاء واحد فقط على كائن الاتصال. | ||
<syntaxhighlight lang="python3"> | <syntaxhighlight lang="python3"> | ||
import sqlite3 | import sqlite3 | ||
سطر 170: | سطر 160: | ||
=== الوصول إلى الأعمدة عن طريق أسمائها عوضًا عن فهارسها === | === الوصول إلى الأعمدة عن طريق أسمائها عوضًا عن فهارسها === | ||
الصنف الداخلي sqlite3.Row هو من الميزات المفيدة في وحدة | الصنف الداخلي <code>sqlite3.Row</code> هو من الميزات المفيدة في وحدة <code>sqlite3</code>، وقد صمّم هذا الصنف لاستخدامه كمنتج للصفوف row factory. | ||
يمكن الوصول إلى الصفوف rows المغلّفة بهذا الصنف إما عن طريق الفهرس (مثل الصفوف tuples) أو عن طريق الاسم دون تحسس حالة الأحرف: | يمكن الوصول إلى الصفوف <code>rows</code> المغلّفة بهذا الصنف إما عن طريق الفهرس (مثل [[Python/tuples|الصفوف tuples]]) أو عن طريق الاسم دون تحسس حالة الأحرف: | ||
<syntaxhighlight lang="python3"> | <syntaxhighlight lang="python3"> | ||
سطر 215: | سطر 205: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
مشاكل شائعة | == مشاكل شائعة == | ||
=== تعدد الخيوط Multithreading === | |||
تعاني إصدارات SQLite القديمة من مشاكل في مشاركة الاتصال بين خيوط متعددة، ولهذا السبب تمنع وحدة بايثون مشاركة الاتصالات والمؤشرات بين الخيوط، وتطلق اللغة استثناء في وقت التشغيل عند القيام بذلك. | تعاني إصدارات SQLite القديمة من مشاكل في مشاركة الاتصال بين خيوط متعددة، ولهذا السبب تمنع وحدة بايثون مشاركة الاتصالات والمؤشرات بين الخيوط، وتطلق اللغة استثناء في وقت التشغيل عند القيام بذلك. | ||
الاستثناء الوحيد هو في استدعاء التابع interrupt() والذي يعدّ استدعاؤه من خيط آخر أمرًا منطقيًا. | الاستثناء الوحيد هو في استدعاء التابع <code>interrupt()</code> والذي يعدّ استدعاؤه من خيط آخر أمرًا منطقيًا. | ||
== مصادر == | == مصادر == |
مراجعة 08:42، 16 سبتمبر 2018
SQLite هي مكتبة مكتوبة بلغة C تتيح إنشاء قواعد بيانات على القرص الصلب ولا تحتاج إلى خادوم خاص لمعالجتها، وتتيح الوصول إلى قاعدة البيانات باستخدام نسخة غير قياسية من لغة الاستعلام SQL.
تستخدم بعض التطبيقات والبرامج قاعدة بيانات SQLite لتخزين بياناتها الداخلية، ويمكن إنشاء نماذج أولية من التطبيق باستخدام SQLite ثم نقل الشيفرة إلى قواعد بيانات أكبر مثل PostgreSQL أو Oracle.
كُتبت وحدة sqlite3
من قبل Gerhard Häring، وتقدّم واجهة SQL متوافقة مع معايير DB-API 2.0 الموصوفة في PEP 249.
الاتصال بقاعدة بيانات SQLite
لاستخدام هذه الوحدة يجب إنشاء كائن اتصال Connection
يمثّل قاعدة البيانات. يبين المثال التالي طريقة استخدام الوحدة مع افتراض أن البيانات مخزّنة في ملف باسم example.db
.
import sqlite3
conn = sqlite3.connect('example.db')
يمكن كذلك استخدام الاسم الخاص :memory:
لإنشاء قاعدة البيانات في ذاكرة الوصول العشوائي RAM.
بعد إجراء الاتصال مع قاعدة البيانات يمكن إنشاء كائن مؤشر Cursor
واستدعاء التابع execute()
لتنفيذ أوامر SQL:
c = conn.cursor()
# إنشاء جدول
c.execute('''CREATE TABLE stocks
(date text, trans text, symbol text, qty real, price real)''')
# إدراج صف من البيانات
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
# حفظ التعديلات
conn.commit()
# يمكن كذلك إغلاق الاتصال بعد الانتهاء
# ولكن يجب التأكد من حفظ جميع التعديلات تجنبًا لفقدانها كلّها
conn.close()
تكون البيانات المحفوظة من النوع المستمر persistent وهي متاحة للاستخدام في الجلسات اللاحقة:
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
ستحتاج في العادة إلى استخدام القيم المخزّنة في متغيرات بايثون لإجراء عمليات SQL، ولكن عليك أن تتجنب استخدام سلاسل بايثون النصية لإنشاء أوامر الاستعلام عن البيانات لأنّ ذلك غير آمن، إذ يكون برنامجك عرضة لهجمات حقن SQL.
ينصح باستخدام معامل الاستبدال الخاصّ بواجهة DB-API، حيث يوضع الرمز ?
عوضًا عن القيم التي تريد إدراجها في جملة الاستعلام، ثم تزويد تابع execute()
بمعامل ثانٍ يكون على هيئة صفّ tuple يتضمّن تلك القيم حسب ترتيبها في جملة الاستعلام. (قد تستخدم وحدات قواعد البيانات الأخرى رموز مختلفة، مثل %s
أو :1
). فعلى سبيل المثال:
# لا تقم بهذا - هذا خطر.
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
# استخدم هذه الطريقة
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())
# يبين المثال التالي طريقة إدراج عدد من القيم
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)
بعد تنفيذ جملة الاستعلام SELECT يمكن استرجاع البيانات إمّا عن طريق التعامل مع المؤشر كمكرِّر iterator، أو استدعاء التابع fetchone()
لاسترجاع صفّ row واحد فقط، أو استدعاء التابع fetchall()
للحصول على قائمة بالصفوف rows المطابقة.
يستخدم المثال التالي طريقة المكرِّر:
>>> for row in c.execute('SELECT * FROM stocks ORDER BY price'):
print(row)
('2006-01-05', 'BUY', 'RHAT', 100, 35.14)
('2006-03-28', 'BUY', 'IBM', 1000, 45.0)
('2006-04-06', 'SELL', 'IBM', 500, 53.0)
('2006-04-05', 'BUY', 'MSFT', 1000, 72.0)
ثوابت الوحدة sqlite
تقدّم وحدة sqlite
الثوابت التالية:
الثابت sqlite3.version
رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة سلسلة نصية.
الثابت sqlite3.version_info
رقم الإصدار الخاص بالوحدة -وليس مكتبة SQLite- على هيئة صفّ من الأعداد الصحيحة.
الثابت sqlite3.sqlite_version
رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة سلسلة نصية.
الثابت sqlite3.sqlite_version_info
رقم الإصدار الخاص بمكتبة SQLite في وقت التشغيل، على هيئة صفّ من الأعداد الصحيحة.
الثابت sqlite3.PARSE_DECLTYPES
يستخدم هذا الثابت مع معامل detect_types
في دالة connect()
.
تفسر وحدة sqlite3
-عند تعيين قيمة لهذا الثابت- الأنواع المصرّح عنها لكل عمود تعيده. تفسّر الوحدة أول كلمة في النوع المصرّح عنه، أي تفسر النوع "integer primary key"
إلى "integer"
، والنوع "number(10)"
إلى "number"
. ثم تبحث الوحدة في قاموس المحوّلات عن الدالة المحوّلة المسجَّلة لذلك النوع.
الثابت sqlite3.PARSE_COLNAMES
يستخدم هذا الثابت مع معامل detect_types
في دالة connect
().
تفسّر واجهة SQLite -عند تعيين قيمة لهذا الثابت- اسم العمود لكل عمود تعيده.
ستبحث الواجهة عن سلسلة نصية بهيئة [mytype]
في جملة الاستعلام لتقرّر أن العمود هو من نوع 'mytype'
. ستحاول الواجهة البحث عن مدخل من نوع 'mytype'
في قاموس المحوّلات ثم تستخدم الدالة المحوّلة التي تجدها لإعادة القيمة.
يكون اسم العمود الموجود في Cursor.description
مقصورًا على الكلمة الأولى من اسم العمود، بمعنى أنّه لو استخدمت مثلًا العبارة 'as "x [datetime]"'
في SQL، فإنّها ستفسّر إلى حين الوصول إلى أول فراغ في اسم العمود، وبهذا يصبح اسم العمود هو "x"
فقط.
الاستثناءات في وحدة sqlite3
الاستثناء sqlite3.Warning
صنف متفرّع من الصنف Exception
.
الاستثناء sqlite3.Error
الصنف الأساسي لبقية الاستثناءات في هذه الوحدة، وهو صنف متفرّع من الصنف Exception
.
الاستثناء sqlite3.DatabaseError
يطلق هذا الاستثناء عند حدوث الأخطاء المتعلّقة بقاعدة البيانات.
الاستثناء sqlite3.IntegrityError
يطلق هذا الاستثناء عند حدوث خلل في العلاقات التي تربط بين جداول قاعدة البيانات، كحدوث خلل في المفتاح الخارجي foreign key. هذا الاستثناء متفرّع من الصنف DatabaseError
.
الاستثناء sqlite3.ProgrammingError
يُطلق هذا الاستثناء عند حدوث أخطاء برمجية، مثل عدم العثور على الجدول المحدّد أو وجود الجدول المراد إنشاؤه أصلًا، أو وجود خلل في جمل SQL، أو تحديد عدد خاطئ من المعاملات... الخ. هذا الاستثناء متفرّع من الصنف DatabaseError
.
الاستثناء sqlite3.OperationalError
يُطلق هذا الاستثناء عند حدوث الأخطاء المتعلّقة بالعمليات الخاصّة بقواعد البيانات والتي لا تكون بالضرورة تحت سيطرة المبرمج، مثل: انقطاع الاتصال بقاعدة البيانات على نحو مفاجئ، أو عدم العثور على اسم مصدر البيانات، أو تعذّر معالجة إجراء معيّن... الخ. هذا الاستثناء متفرّع من الصنف DatabaseError
.
الاستثناء sqlite3.NotSupportedError
يُطلق هذا الاستثناء عند استخدام تابع أو واجهة برمجية لقواعد البيانات لا تدعمها قاعدة البيانات الحالية، مثل: استدعاء التابع rollback()
مع اتصال لا يدعم الإجراءات transaction أو أنّ الإجراءات تكون مغلقة. هذا الاستثناء متفرّع من الصنف DatabaseError
.
استخدام sqlite3 بكفاءة
استخدام التوابع المختصرة
يؤدي استخدام التوابع غير المعيارية execute()
و executemany()
و executescript()
في كائن Connection
إلى اختصار الشيفرة البرمجية المكتوبة نظرًا لانتفاء الحاجة إلى إنشاء كائن المؤشر Cursor
والذي يكون في كثير من الأحيان زائدًا عن الحاجة.
عوضًا عن ذلك، يجري إنشاء كائن Cursor
ضمنيًا وتعيد هذه التوابع المختصرة كائنات المؤشر، وهكذا يمكنك تنفيذ جملة SELECT
والمرور على النتائج مباشرة وعن طريق تنفيذ استدعاء واحد فقط على كائن الاتصال.
import sqlite3
persons = [
("Hugo", "Boss"),
("Calvin", "Klein")
]
con = sqlite3.connect(":memory:")
# إنشاء الجدول
con.execute("create table person(firstname, lastname)")
# تعبئة الجدول بالبيانات
con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
# طباعة محتويات الجدول
for row in con.execute("select firstname, lastname from person"):
print(row)
print("I just deleted", con.execute("delete from person").rowcount, "rows")
الوصول إلى الأعمدة عن طريق أسمائها عوضًا عن فهارسها
الصنف الداخلي sqlite3.Row
هو من الميزات المفيدة في وحدة sqlite3
، وقد صمّم هذا الصنف لاستخدامه كمنتج للصفوف row factory.
يمكن الوصول إلى الصفوف rows
المغلّفة بهذا الصنف إما عن طريق الفهرس (مثل الصفوف tuples) أو عن طريق الاسم دون تحسس حالة الأحرف:
import sqlite3
con = sqlite3.connect(":memory:")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select 'John' as name, 42 as age")
for row in cur:
assert row[0] == row["name"]
assert row["name"] == row["nAmE"]
assert row[1] == row["age"]
assert row[1] == row["AgE"]
استخدام الاتصال كمدير للسياق context manager
يمكن استخدام كائنات الاتصال كمدراء للسياق يمكنها حفظ أو استرجاع الإجراءات على نحو تلقائي. في حال حدوث أي استثناء، يتم التراجع عن الإجراء، وفيما عدا ذلك يُحفظ الإجراء:
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")
# يستدعى التابع con.commit() تلقائيًا بعد ذلك ودون حدوث أي مشاكل
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
# يستدعى التابع con.rollback() بعد انتهاء الإجراء باستثناء، وسيبقى الاستثناء طليقًا ويجب الإمساك به.
try:
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
print("couldn't add Joe twice")
مشاكل شائعة
تعدد الخيوط Multithreading
تعاني إصدارات SQLite القديمة من مشاكل في مشاركة الاتصال بين خيوط متعددة، ولهذا السبب تمنع وحدة بايثون مشاركة الاتصالات والمؤشرات بين الخيوط، وتطلق اللغة استثناء في وقت التشغيل عند القيام بذلك.
الاستثناء الوحيد هو في استدعاء التابع interrupt()
والذي يعدّ استدعاؤه من خيط آخر أمرًا منطقيًا.