<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>SQLite on Dev TLDRLSS</title>
        <link>https://dev.tldrlss.com/ar/tags/sqlite/</link>
        <description>Recent content in SQLite on Dev TLDRLSS</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>ar</language>
        <lastBuildDate>Tue, 19 May 2026 18:10:00 +0800</lastBuildDate><atom:link href="https://dev.tldrlss.com/ar/tags/sqlite/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>لا تنخدع بعفوية SQLite! ما هي فخاخ الأنواع الديناميكية؟ ولماذا ALTER TABLE غير مكتمل؟ وكيف تبني بنية برمجية دفاعية في Node.js لترقية مخطط الجدول بدون ألم؟</title>
        <link>https://dev.tldrlss.com/ar/article/2026/05/sqlite-pitfall-intro/</link>
        <pubDate>Tue, 19 May 2026 18:10:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ar/article/2026/05/sqlite-pitfall-intro/</guid>
        <description>&lt;img src="https://dev.tldrlss.com/global-assets/images/database/sqlite-type-pitfall-1.jpg" alt="Featured image of post لا تنخدع بعفوية SQLite! ما هي فخاخ الأنواع الديناميكية؟ ولماذا ALTER TABLE غير مكتمل؟ وكيف تبني بنية برمجية دفاعية في Node.js لترقية مخطط الجدول بدون ألم؟" /&gt;&lt;p&gt;تخيل سلة إعادة تدوير وضعت عليها بوضوح ملصقًا يقول &amp;quot;للزجاجات البلاستيكية فقط&amp;quot;، ولكن عندما يلقي شخص ما قطعة ورق داخلها، فإنها تقبلها بصمت دون كلمة احتجاج واحدة؟&lt;/p&gt;
&lt;p&gt;هذه هي التجربة المثيرة للقشعريرة التي يمر بها المطورون عندما يقابلون نظام أنواع &lt;code&gt;SQLite&lt;/code&gt; لأول مرة.&lt;/p&gt;
&lt;p&gt;إذا كنت معتادًا على أسلوب موظف الجمارك الصارم في &lt;code&gt;PostgreSQL&lt;/code&gt; (حيث يتم رفض الأنواع غير الصحيحة مباشرة من الدخول)، فإن عفوية وسهولة &lt;code&gt;SQLite&lt;/code&gt; قد تجعلك تشك في حياتك.&lt;/p&gt;
&lt;p&gt;والأكثر رعبًا من ذلك، عندما تريد &lt;strong&gt;تعديل بنية جدول&lt;/strong&gt;، ستخبرك قاعدة البيانات بالتالي:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;لا يمكن تعديل الجدول مباشرة. يرجى بناء منزل جديد، ونقل الأثاث إليه، ثم تفجير المنزل القديم.&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;تحت-الغطاء-تمتلك-sqlite-5-فئات-تخزين-فقط&#34;&gt;تحت الغطاء، تمتلك SQLite 5 فئات تخزين فقط
&lt;/h2&gt;&lt;p&gt;بغض النظر عن أسماء الأنواع الفخمة التي تعلن عنها في &lt;code&gt;CREATE TABLE&lt;/code&gt; مثل (&lt;code&gt;VARCHAR(255)&lt;/code&gt;، &lt;code&gt;BIGINT&lt;/code&gt;، &lt;code&gt;DECIMAL&lt;/code&gt;)، فإن &lt;code&gt;SQLite&lt;/code&gt; تحت الغطاء لا تتعرف إلا على &lt;strong&gt;فئات التخزين الخمس&lt;/strong&gt; التالية:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;فئة التخزين&lt;/th&gt;
          &lt;th&gt;الوصف&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;NULL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;قيمة فارغة&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;INTEGER&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;عدد صحيح (يشغل تلقائيًا من 1 إلى 8 بايت اعتمادًا على حجم القيمة)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;REAL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;رقم عشري عائم (ثابت 8 بايت)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;TEXT&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;سلسلة نصية (ترميز UTF-8 افتراضي)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;BLOB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;كائن ثنائي كبير (يتم تخزينه تمامًا كما تم إدخاله)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;الأنواع التي تحددها في الأعمدة &lt;strong&gt;هي مجرد &amp;quot;توصية&amp;quot; لـ &lt;code&gt;SQLite&lt;/code&gt; وليست &amp;quot;قواعد إلزامية&amp;quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;يطلق على هذا اسم &lt;strong&gt;&amp;quot;Type Affinity&amp;quot; (أفيونيتي النوع)&lt;/strong&gt;. ستحاول &lt;code&gt;SQLite&lt;/code&gt; تحويل بياناتك إلى النوع الموصى به، ولكن إذا لم تتمكن من ذلك، فستقوم بإدخال البيانات الأصلية على أي حال دون إظهار أي خطأ.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;يمكنك الإعلان عن عمود &lt;code&gt;age INTEGER&lt;/code&gt; في &lt;code&gt;SQLite&lt;/code&gt; ثم إدخال السلسلة النصية &lt;code&gt;&#39;ثمانية عشر عامًا للأبد&#39;&lt;/code&gt;؛ وسوف تقبله بكل سرور.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;ثلاثة-فخاخ-أنواع-هي-الأسهل-في-الوقوع-بها&#34;&gt;ثلاثة فخاخ أنواع هي الأسهل في الوقوع بها
&lt;/h2&gt;&lt;h3 id=&#34;الفخ-1-غياب-نوع-boolean-الأصلي&#34;&gt;الفخ 1: غياب نوع Boolean الأصلي
&lt;/h3&gt;&lt;p&gt;لا تحتوي &lt;code&gt;SQLite&lt;/code&gt; على &lt;strong&gt;نوع boolean أصلي&lt;/strong&gt;. يمكن تمثيل قيمتي &lt;code&gt;True&lt;/code&gt; و &lt;code&gt;False&lt;/code&gt; بالأعداد الصحيحة &lt;code&gt;1&lt;/code&gt; و &lt;code&gt;0&lt;/code&gt; فقط.&lt;/p&gt;
&lt;p&gt;عندما تسترجع البيانات من &lt;code&gt;SQLite&lt;/code&gt; باستخدام &lt;code&gt;Node.js&lt;/code&gt;، ستحصل على الرقم &lt;code&gt;1&lt;/code&gt; أو &lt;code&gt;0&lt;/code&gt; وليس &lt;code&gt;true&lt;/code&gt; أو &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;إذا قمت مباشرة بإجراء فحص مثل &lt;code&gt;if (user.is_admin === true)&lt;/code&gt;، فلن يكون صحيحًا أبدًا.&lt;/p&gt;
&lt;h3 id=&#34;الفخ-2-غياب-نوع-datetime&#34;&gt;الفخ 2: غياب نوع Date/Time
&lt;/h3&gt;&lt;p&gt;لا تحتوي &lt;code&gt;SQLite&lt;/code&gt; على &lt;strong&gt;نوع للتاريخ/الوقت&lt;/strong&gt;. لا يمكنك تخزين الوقت إلا بالطرق التالية:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;طريقة التخزين&lt;/th&gt;
          &lt;th&gt;مثال&lt;/th&gt;
          &lt;th&gt;الميزات والعيوب&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;TEXT (سلسلة ISO-8601)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&#39;2026-05-19T18:00:00Z&#39;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;الأكثر توصية&lt;/strong&gt;، وضوح عالٍ، وتحويل سلس عند الانتقال إلى PostgreSQL مستقبلاً&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;INTEGER (طابع Unix الزمني)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;1747656000&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;يشغل مساحة صغيرة، ولكنه غير مقروء للبشر&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;لا تخزن التواريخ مطلقًا بتنسيقات مخصصة عشوائية مثل &lt;code&gt;19/5/2026 6:00 مساءً&lt;/code&gt;، وإلا فسيكون ترحيل البيانات مستقبلاً كارثة حقيقية.&lt;/p&gt;
&lt;h3 id=&#34;الفخ-3-إدخال-سلسلة-نصية-في-عمود-integer-لن-يؤدي-لحدوث-خطأ&#34;&gt;الفخ 3: إدخال سلسلة نصية في عمود INTEGER لن يؤدي لحدوث خطأ
&lt;/h3&gt;&lt;p&gt;في &lt;code&gt;PostgreSQL&lt;/code&gt; يؤدي إدخال سلسلة نصية في عمود &lt;code&gt;INTEGER&lt;/code&gt; إلى حدوث خطأ على الفور. ولكن &lt;code&gt;SQLite&lt;/code&gt; ستحاول التحويل بصمت فقط، وعند الفشل، ستقبل البيانات كما هي.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;هذا يعني أن &lt;strong&gt;البيانات الملوثة قد تتسلل بصمت إلى قاعدة بياناتك&lt;/strong&gt; حتى يأتي يوم يتوقف فيه برنامجك فجأة بسبب تلقي نوع غير متوقع، وعندها فقط تكتشف المشكلة.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;البرمجة-الدفاعية-مواجهة-قاعدة-بيانات-عفوية-بموقف-صارم&#34;&gt;البرمجة الدفاعية: مواجهة قاعدة بيانات عفوية بموقف صارم
&lt;/h2&gt;&lt;p&gt;في مواجهة عفوية وسهولة &lt;code&gt;SQLite&lt;/code&gt;، يجب عليك بناء &lt;strong&gt;آليات دفاع صارمة&lt;/strong&gt; في تطوير تطبيقات &lt;code&gt;Node.js&lt;/code&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;مستوى الدفاع&lt;/th&gt;
          &lt;th&gt;الأداة&lt;/th&gt;
          &lt;th&gt;الدور&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;حارس وقت الترجمة&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;التقاط الأنواع غير الصحيحة في مرحلة كتابة الكود&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;التحقق من مدخلات API&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Zod&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;التحقق من صحة البيانات الواردة بصرامة (ضمان أن يكون age رقمًا دائمًا)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تحويل الأنواع الداخلي&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Prisma / Drizzle ORM&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;معالجة فروق الأنواع تلقائيًا بين SQLite و PostgreSQL&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;إن نقل &lt;strong&gt;&amp;quot;حارس بوابة التحقق من البيانات&amp;quot;&lt;/strong&gt; من مستوى قاعدة البيانات إلى مستوى تطبيق &lt;code&gt;Node.js&lt;/code&gt; هو استراتيجية رئيسية للاستفادة من سرعة تطوير SQLite مع ضمان قابلية التوسع مستقبلاً.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;عند استخدام ORM، طالما أنك تعلن عن &lt;code&gt;type: &#39;boolean&#39;&lt;/code&gt; في كودك، فإن الـ ORM يقوم تلقائيًا بتحويله إلى &lt;code&gt;1/0&lt;/code&gt; عند الحفظ في &lt;code&gt;SQLite&lt;/code&gt; ويحوله مجددًا إلى &lt;code&gt;true/false&lt;/code&gt; عند القراءة، مما يخفي فروق الأنواع الأساسية تمامًا.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;alter-table-غير-مكتمل-ما-يمكن-وما-لا-يمكن-تعديله&#34;&gt;ALTER TABLE غير مكتمل: ما يمكن وما لا يمكن تعديله
&lt;/h2&gt;&lt;p&gt;دعم &lt;code&gt;SQLite&lt;/code&gt; لتعديل بنية الجداول محدود للغاية:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;العملية&lt;/th&gt;
          &lt;th&gt;مدعومة&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;إضافة عمود (&lt;code&gt;ADD COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;نعم&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;إعادة تسمية عمود (&lt;code&gt;RENAME COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;نعم&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;حذف عمود (&lt;code&gt;DROP COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;نعم&lt;/strong&gt; (في الإصدارات الحديثة)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;إعادة تسمية جدول (&lt;code&gt;RENAME TO&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;نعم&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تغيير نوع العمود&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;لا&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;إضافة/إزالة قيود &lt;code&gt;UNIQUE&lt;/code&gt; و &lt;code&gt;NOT NULL&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;لا&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تعديل المفتاح الأساسي&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;لا&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تعديل المفتاح الأجنبي&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;لا&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;بمجرد أن تحتاج إلى إجراء أي من التعديلات &amp;quot;غير المدعومة&amp;quot;، تتطلب منك &lt;code&gt;SQLite&lt;/code&gt; تنفيذ استراتيجية &lt;strong&gt;&amp;quot;إعادة الإنشاء والنقل&amp;quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;أربع-خطوات-لإعادة-الإنشاء-والنقل-طريقة-ترقية-جداول-sqlite&#34;&gt;أربع خطوات لإعادة الإنشاء والنقل: طريقة ترقية جداول SQLite
&lt;/h2&gt;&lt;p&gt;نظرًا لعدم إمكانية التعديل المباشر، فإن الطريقة القياسية الموصى بها في الوثائق الرسمية هي &lt;strong&gt;بناء منزل جديد، ونقل الأثاث، وتفجير المنزل القديم، وتعليق اللوحة الجديدة&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;الخطوة&lt;/th&gt;
          &lt;th&gt;الإجراء&lt;/th&gt;
          &lt;th&gt;الوصف&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;إنشاء جدول جديد&lt;/td&gt;
          &lt;td&gt;إنشاء &lt;code&gt;CREATE TABLE users_new (...)&lt;/code&gt; بالبنية الصحيحة&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;نسخ البيانات&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;INSERT INTO users_new SELECT ... FROM users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;حذف الجدول القديم&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;DROP TABLE users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;إعادة تسمية الجدول&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ALTER TABLE users_new RENAME TO users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;يجب تنفيذ هذه الخطوات الأربع &lt;strong&gt;دفعة واحدة ومن دون انقطاع&lt;/strong&gt;؛ أي انقطاع في الطاقة أو تعطل للتطبيق في منتصف الطريق سيؤدي إلى فقدان البيانات.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;ضمان-عدم-فقدان-البيانات-أثناء-الترقية-خطان-للدفاع-عن-الأمان&#34;&gt;ضمان عدم فقدان البيانات أثناء الترقية: خطان للدفاع عن الأمان
&lt;/h2&gt;&lt;h3 id=&#34;خط-الدفاع-1-الدفاع-المادي-نسخ-الملف-مباشرة&#34;&gt;خط الدفاع 1: الدفاع المادي، نسخ الملف مباشرة
&lt;/h3&gt;&lt;p&gt;تعتبر &lt;code&gt;SQLite&lt;/code&gt; في جوهرها مجرد ملف واحد. قبل تنفيذ أي تغييرات في المخطط، يكفي ببساطة نسخ ملف &lt;code&gt;.db&lt;/code&gt; ليكون نسخة احتياطية.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;fs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;copyFileSync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project_backup.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;إذا سارت الأمور بشكل سيء، فإن استبدال الملف يستعيد كل شيء في لمحة بصر. هذه ميزة لا توفرها قواعد البيانات الكبيرة الأخرى.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;خط-الدفاع-2-تغليف-المعاملة-transaction-آلة-الزمن-لقاعدة-البيانات&#34;&gt;خط الدفاع 2: تغليف المعاملة (Transaction), آلة الزمن لقاعدة البيانات
&lt;/h3&gt;&lt;p&gt;قم بتغليف جميع خطوات الترحيل داخل معاملة &lt;code&gt;Transaction&lt;/code&gt; واحدة؛ وإذا فشلت أي خطوة، فسيتم &lt;strong&gt;التراجع تلقائيًا (Rollback)&lt;/strong&gt; عن العملية بأكملها وكأن شيئًا لم يكن.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;better-sqlite3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;migrateData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;transaction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    CREATE TABLE users_new (
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      id INTEGER PRIMARY KEY AUTOINCREMENT,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      name TEXT NOT NULL,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      age INTEGER NOT NULL DEFAULT 18
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    INSERT INTO users_new (id, name, age)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    SELECT id, name, COALESCE(age, 18) FROM users
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;DROP TABLE users&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ALTER TABLE users_new RENAME TO users&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;migrateData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;اكتملت ترقية الجدول&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;فشلت الترقية، تم استعادة البيانات بأمان:&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;ملف النسخ الاحتياطي + ربط المعاملة&amp;quot;&lt;/strong&gt; هو الوسادة الهوائية لترحيل قاعدة بياناتك.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;التحكم-في-عفوية-sqlite-بموقف-صارم&#34;&gt;التحكم في عفوية SQLite بموقف صارم
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;تحكم في عفوية وسهولة &lt;code&gt;SQLite&lt;/code&gt; باستخدام &lt;strong&gt;بنية صارمة لطبقة التطبيق&lt;/strong&gt; للاستمتاع بميزة سرعة التطوير الفائقة مع تجنب الديون التقنية مستقبلاً.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;يعتبر نظام الأنواع في SQLite مرنًا وعفويًا للغاية، كما أن &lt;code&gt;ALTER TABLE&lt;/code&gt; لديه العديد من القيود.&lt;/p&gt;
&lt;p&gt;ولكن طالما أنك تقوم بتطبيق &lt;strong&gt;فحص أنواع TypeScript + تحقق Zod + تجريد الـ ORM&lt;/strong&gt; في جهة &lt;code&gt;Node.js&lt;/code&gt; بجدية، وتدمج ذلك مع استراتيجية الأمان المتمثلة في &lt;strong&gt;النسخ الاحتياطي المادي + المعاملات الصارمة&lt;/strong&gt;، فيمكنك الاستمتاع بكفاءة التطوير الرائعة التي توفرها &lt;code&gt;SQLite&lt;/code&gt; مع تمهيد الطريق للانتقال السلس إلى &lt;code&gt;PostgreSQL&lt;/code&gt; مستقبلاً.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/datatype3.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Datatypes In SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.runoob.com/sqlite/sqlite-data-types.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite 数据类型 | 菜鸟教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.sqlite.org/lang_transaction.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Transaction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/lang.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Query Language Understood by SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/SQLite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>لا تستخدم PostgreSQL لكل شيء! ما هي مزايا البنية المدمجة والتهيئة الصفرية لـ SQLite؟ أين تكمن حدود SQLite؟ متى يجب اختيار SQLite ومتى يجب اختيار PostgreSQL؟</title>
        <link>https://dev.tldrlss.com/ar/article/2026/05/sqlite-intro/</link>
        <pubDate>Tue, 19 May 2026 18:00:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ar/article/2026/05/sqlite-intro/</guid>
        <description>&lt;img src="https://dev.tldrlss.com/global-assets/images/database/sqlite-vs-postgresql-choice-2.jpg" alt="Featured image of post لا تستخدم PostgreSQL لكل شيء! ما هي مزايا البنية المدمجة والتهيئة الصفرية لـ SQLite؟ أين تكمن حدود SQLite؟ متى يجب اختيار SQLite ومتى يجب اختيار PostgreSQL؟" /&gt;&lt;p&gt;هل فكرت يوماً في حقيقة أن المتصفح الذي تفتحه يومياً، وتطبيق المراسلة على هاتفك، وحتى أداة تدوين الملاحظات على سطح مكتبك، كلها تخفي قاعدة البيانات الخفيفة نفسها؟&lt;/p&gt;
&lt;p&gt;إنها لا تتطلب منك تثبيت أي برنامج خادم، ولا تحتاج إلى إعدادات حساب أو كلمة مرور، بل ولا تحتاج حتى إلى اتصال بالإنترنت. إنها ببساطة &lt;strong&gt;ملف&lt;/strong&gt; واحد، يستقر بهدوء على القرص الصلب الخاص بك، وجاهز لخدمتك في أي وقت.&lt;/p&gt;
&lt;p&gt;هذا الوجود الهادئ هو &lt;code&gt;SQLite&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ما-هي-sqlite-قاعدة-البيانات-الأكثر-انتشارا-في-العالم&#34;&gt;ما هي SQLite؟ قاعدة البيانات الأكثر انتشاراً في العالم
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;SQLite&lt;/code&gt; هي &lt;strong&gt;محرك قاعدة بيانات علاقة مدمجة&lt;/strong&gt; مكتوبة بلغة C.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ليس لديها &lt;strong&gt;عملية خادم مستقلة&lt;/strong&gt;، بل يتم دمجها مباشرة داخل تطبيقك لتعمل.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;هذا يختلف تماماً عن &lt;code&gt;PostgreSQL&lt;/code&gt; أو &lt;code&gt;MySQL&lt;/code&gt; التي قد تكون معتاداً عليها. قواعد البيانات التقليدية هي &lt;strong&gt;خوادم مستقلة&lt;/strong&gt; تعمل بشكل منفصل، ويجب على برنامجك &amp;ldquo;التواصل&amp;rdquo; معها عبر &lt;strong&gt;بروتوكول شبكة (TCP/IP)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;SQLite&lt;/code&gt; مختلفة؛ فهي مجرد كتلة من الكود، تعمل مباشرة داخل تطبيقك، وتقوم بالقراءة والكتابة في ملف &lt;code&gt;.db&lt;/code&gt; هذا على القرص الصلب الخاص بك.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;وجه المقارنة&lt;/th&gt;
          &lt;th&gt;SQLite (مدمجة)&lt;/th&gt;
          &lt;th&gt;PostgreSQL (عميل-خادم)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;وضع التشغيل&lt;/td&gt;
          &lt;td&gt;مدمجة مباشرة في التطبيق، بدون خادم مستقل&lt;/td&gt;
          &lt;td&gt;عملية خادم مستقلة، عبر اتصال الشبكة&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;التهيئة والإعداد&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;تهيئة صفرية&lt;/strong&gt;، بدون تثبيت، بدون بيانات اعتماد&lt;/td&gt;
          &lt;td&gt;تتطلب تثبيتاً، وإعداد حساب/كلمة مرور وجدار حماية&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تخزين البيانات&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;ملف واحد متوافق مع جميع الأنظمة&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;ملفات متعددة تحت دليل الخادم&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;طريقة النسخ الاحتياطي&lt;/td&gt;
          &lt;td&gt;نسخ هذا الملف مباشرة&lt;/td&gt;
          &lt;td&gt;تتطلب أدوات مخصصة مثل pg_dump&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;وبسبب هذه الميزة المتمثلة في &lt;strong&gt;&amp;ldquo;التوصيل والتشغيل المباشر&amp;rdquo;&lt;/strong&gt;، أصبحت &lt;code&gt;SQLite&lt;/code&gt; محرك قاعدة البيانات الأكثر تثبيتاً واستخداماً في العالم.&lt;/p&gt;
&lt;p&gt;من أنظمة تشغيل Android و iOS، ومتصفحات Chrome و Firefox، إلى Adobe Lightroom و WhatsApp وحتى نظام الطيران في طائرات Airbus A350، فهي موجودة في كل مكان.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;استخدام-sqlite-في-nodejs&#34;&gt;استخدام SQLite في Node.js
&lt;/h2&gt;&lt;p&gt;إذا كنت مطور Node.js، فإن استخدام &lt;code&gt;SQLite&lt;/code&gt; سهل للغاية. لا تحتاج إلى تثبيت أي برنامج خادم لقاعدة البيانات على جهاز الكمبيوتر الخاص بك، بل تحتاج فقط إلى تثبيت حزمة npm للبدء.&lt;/p&gt;
&lt;p&gt;الخيارات الأكثر استخداماً في المجال اليوم:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;اسم الحزمة&lt;/th&gt;
          &lt;th&gt;الميزات&lt;/th&gt;
          &lt;th&gt;السيناريو الموصى به&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sqlite3&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;الأكثر عراقة، تدعم واجهات برمجة التطبيقات غير المتزامنة&lt;/td&gt;
          &lt;td&gt;عندما تحتاج إلى معالجة العديد من المهام غير المتزامنة معاً&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;better-sqlite3&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;أداء ممتاز&lt;/strong&gt;، تصميم بديهي لواجهة البرمجة، سريعة للغاية&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;التوصية الأولى&lt;/strong&gt;، لزيادة كفاءة التطوير وسرعة التنفيذ&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;إنشاء قاعدة بيانات والاستعلام عنها باستخدام &lt;code&gt;better-sqlite3&lt;/code&gt; يستغرق أقل من خمس دقائق:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;better-sqlite3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insert&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;INSERT INTO users (name, age) VALUES (?, ?)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;insert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;SELECT * FROM users WHERE name = ?&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// { name: &amp;#39;John&amp;#39;, age: 25 }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;إذا كان الملف غير موجود، ستقوم &lt;code&gt;better-sqlite3&lt;/code&gt; &lt;strong&gt;بإنشائه تلقائياً لك&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;تدعم-sqlite-قواعد-sql-أقوى-مما-تظن&#34;&gt;تدعم SQLite قواعد SQL أقوى مما تظن
&lt;/h2&gt;&lt;p&gt;يعتقد الكثير من الناس أن &lt;code&gt;SQLite&lt;/code&gt; بسيطة للغاية، ولكنها في الواقع تدعم معظم قواعد SQL القياسية، بما في ذلك العديد من الميزات المتقدمة:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;فئة القواعد&lt;/th&gt;
          &lt;th&gt;العناصر المدعومة&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;العمليات الأساسية&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;تعريف البيانات&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt;, &lt;code&gt;CREATE INDEX&lt;/code&gt;, &lt;code&gt;CREATE VIEW&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;الاستعلام المتقدم&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;WITH&lt;/code&gt; (الاستعلام التكراري CTEs)، وظائف النافذة (Window Functions)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;معالجة التعارض&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;UPSERT&lt;/code&gt; (&lt;code&gt;INSERT ... ON CONFLICT DO UPDATE&lt;/code&gt;)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;معالجة JSON&lt;/td&gt;
          &lt;td&gt;وظائف مدمجة مثل &lt;code&gt;json_extract&lt;/code&gt;, &lt;code&gt;json_array&lt;/code&gt;, &lt;code&gt;json_object&lt;/code&gt; وغيرها&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;التحكم في العمليات&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;COMMIT&lt;/code&gt;, &lt;code&gt;ROLLBACK&lt;/code&gt;, &lt;code&gt;SAVEPOINT&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;استعلام الربط&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;, &lt;code&gt;LEFT JOIN&lt;/code&gt;, &lt;code&gt;RIGHT JOIN&lt;/code&gt;, و &lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;الفلسفة الأساسية لـ SQLite هي &amp;ldquo;صغير وجميل&amp;rdquo;&lt;/strong&gt;، حيث تدعم معظم ميزات SQL التي تحتاجها يومياً مع الحفاظ على خفة وزنها الفائقة.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;أين-تكمن-حدود-sqlite&#34;&gt;أين تكمن حدود SQLite؟
&lt;/h2&gt;&lt;p&gt;خفة الوزن لها ثمنها. إذا قارنا &lt;code&gt;SQLite&lt;/code&gt; بـ &lt;strong&gt;متجر بقالة عصري يحتوي على ممر دفع واحد فقط&lt;/strong&gt;، فإن &lt;code&gt;PostgreSQL&lt;/code&gt; هي &lt;strong&gt;متجر Costco مجهز بـ 50 صندوق محاسبة&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;1-ازدحام-عمليات-الكتابة&#34;&gt;1. ازدحام عمليات الكتابة
&lt;/h3&gt;&lt;p&gt;عندما تقوم &lt;code&gt;SQLite&lt;/code&gt; بكتابة البيانات، فإنها &lt;strong&gt;تقفل&lt;/strong&gt; ملف قاعدة البيانات بأكمله.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;تخيل &lt;strong&gt;مطعم يحتوي على مرحاض واحد فقط&lt;/strong&gt;: يمكن لـ 100 شخص النظر إلى قائمة الطعام في الخارج (القراءة) في نفس الوقت، ولكن بمجرد أن يدخل شخص واحد ويغلق الباب (الكتابة)، لا يمكن للآخرين سوى الانتظار في الطابور.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;على الرغم من أن تفعيل &lt;strong&gt;وضع WAL (Write-Ahead Logging)&lt;/strong&gt; يمكن أن يحسن أداء القراءة/الكتابة المتزامنة، إلا أنه من الناحية الهيكلية لا يزال غير قادر على تحقيق كتابة متزامنة متعددة الخيوط على صفوف بيانات مختلفة.&lt;/p&gt;
&lt;h3 id=&#34;2-لا-يمكن-تشغيلها-عبر-خوادم-متعددة&#34;&gt;2. لا يمكن تشغيلها عبر خوادم متعددة
&lt;/h3&gt;&lt;p&gt;جوهر &lt;code&gt;SQLite&lt;/code&gt; هو ملف مادي. إذا تم نشر نظامك على خوادم متعددة (التوسع الأفقي)، فإن هذه الخوادم &lt;strong&gt;لا يمكنها مشاركة نفس الملف بأمان&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;3-غياب-الإدارة-الدقيقة-للصلاحيات&#34;&gt;3. غياب الإدارة الدقيقة للصلاحيات
&lt;/h3&gt;&lt;p&gt;لا يوجد في &lt;code&gt;SQLite&lt;/code&gt; مفهوم &amp;ldquo;حسابات المستخدمين&amp;rdquo;. أي شخص يمكنه قراءة ملف &lt;code&gt;.db&lt;/code&gt; على مستوى نظام التشغيل يمكنه عرض وتعديل جميع البيانات.&lt;/p&gt;
&lt;p&gt;بالنسبة لـ &lt;strong&gt;الأنظمة التجارية التي تتطلب عمليات تدقيق صارمة للبيانات الشخصية&lt;/strong&gt;، فإن هذا الأمر غير مقبول تماماً.&lt;/p&gt;
&lt;h2 id=&#34;sqlite-مقابل-postgresql-اتخاذ-قرار-اختيار-التكنولوجيا&#34;&gt;SQLite مقابل PostgreSQL: اتخاذ قرار اختيار التكنولوجيا
&lt;/h2&gt;&lt;p&gt;لا توجد أداة جيدة أو سيئة، بل هناك أداة مناسبة أو غير مناسبة. إليك قائمة المراجعة النهائية لمساعدتك في اتخاذ القرار:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;السؤال&lt;/th&gt;
          &lt;th&gt;الإجابة &amp;ldquo;نعم&amp;rdquo; ← اختر SQLite&lt;/th&gt;
          &lt;th&gt;الإجابة &amp;ldquo;لا&amp;rdquo; ← اختر PostgreSQL&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;هل يوجد خادم خلفي واحد فقط، أو يعمل النظام محلياً بالكامل؟&lt;/td&gt;
          &lt;td&gt;نعم&lt;/td&gt;
          &lt;td&gt;لا (يتطلب توسعاً أفقياً، خوادم متعددة)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;هل سلوك النظام يعتمد بشكل أساسي على القراءة، دون كتابة متزامنة عالية التردد؟&lt;/td&gt;
          &lt;td&gt;نعم&lt;/td&gt;
          &lt;td&gt;لا (سيتنافس المستخدمون على الكتابة المتزامنة)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;لا تحتاج لصلاحيات حساب قاعدة بيانات دقيقة أو فهارس متقدمة؟&lt;/td&gt;
          &lt;td&gt;نعم&lt;/td&gt;
          &lt;td&gt;لا (تعتمد بشكل كبير على الميزات المتقدمة)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;مقارنة سيناريوهات أكثر تحديداً:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;السيناريو&lt;/th&gt;
          &lt;th&gt;الخيار الموصى به&lt;/th&gt;
          &lt;th&gt;السبب&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;برامج سطح المكتب، تطبيقات الهاتف، أجهزة IoT&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;البيانات تنتقل مع الجهاز، بدون الحاجة لتثبيت&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;المدونات الشخصية، مواقع العرض التعريفية&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;قراءة كثيرة وكتابة قليلة، توفر تكاليف صيانة الخادم&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;التطوير السريع للنماذج الأولية، العروض التوضيحية&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;ما عليك سوى إنشاء ملف للبدء فوراً&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;المنتديات المجتمعية، منصات التجارة الإلكترونية&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;كتابة متزامنة عالية، تتطلب قفل على مستوى الصف&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;النشر الموزع على خوادم متعددة&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;الحاجة إلى مشاركة مصدر البيانات بين أجهزة مختلفة&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;الأنظمة الحساسة مثل الطبية والمالية&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;تتطلب تحكماً صارماً في الصلاحيات بناءً على الأدوار&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;هل-قاعدة-بياناتك-هي-مذكرة-جيب-أم-مقسم-هاتف-مركزي&#34;&gt;هل قاعدة بياناتك هي مذكرة جيب أم مقسم هاتف مركزي؟
&lt;/h2&gt;&lt;p&gt;إذا كانت البيانات &lt;strong&gt;&amp;ldquo;جهاز واحد، ثابتة، يملكها شخص واحد&amp;rdquo;&lt;/strong&gt;، فاختر &lt;code&gt;SQLite&lt;/code&gt; للاستمتاع بخفة الوزن والحرية القصوى؛&lt;/p&gt;
&lt;p&gt;إذا كانت البيانات &lt;strong&gt;&amp;ldquo;سحابية، ديناميكية، تفاعلية للغاية&amp;rdquo;&lt;/strong&gt;، فدع &lt;code&gt;PostgreSQL&lt;/code&gt; تتولى المهمة.&lt;/p&gt;
&lt;p&gt;الفلسفة الأساسية لـ &lt;code&gt;SQLite&lt;/code&gt; هي &lt;strong&gt;&amp;ldquo;مكون داخلي للتطبيق&amp;rdquo;&lt;/strong&gt;، بينما يتموضع &lt;code&gt;PostgreSQL&lt;/code&gt; كـ &lt;strong&gt;&amp;ldquo;مركز مستقل للبنية البرمجية للنظام&amp;rdquo;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;في المرة القادمة التي تتخذ فيها قراراً بشأن البنية الهيكلية، لا تتسرع في استخدام &lt;code&gt;PostgreSQL&lt;/code&gt;. اسأل نفسك أولاً:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;هل قاعدة بياناتي هي مذكرة جيب، أم مقسم هاتف مركزي؟&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;عندما تصبح الإجابة واضحة، سيظهر الخيار المناسب تلقائياً.&lt;/p&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/lang.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Query Language Understood by SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/docs.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.sqlitetutorial.net/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite Tutorial - An Easy Way to Master SQLite Fast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/SQLite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
