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

أمر UPDATE في SQLite: تحديث الصفوف وتعديل الأعمدة

تعرّف على كيفية تعديل الصفوف الموجودة في SQLite باستخدام UPDATE، مع شرح جملة WHERE التي تحميك من الكوارث، وتحديث عدة أعمدة دفعة واحدة، واستخدام UPDATE ... FROM للتعديل بين الجداول.

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

أمر UPDATE لتعديل الصفوف الموجودة

بينما يضيف INSERT صفوفًا جديدة، يأتي دور UPDATE لتحديث بيانات جدول SQLite الموجودة فعلًا. صيغته قصيرة وتستحق الحفظ:

UPDATE table_name
SET column = value
WHERE condition;

مثال عملي مكتمل:

تحدد جملة SET التغييرات المطلوبة، بينما تحدد جملة WHERE الصفوف المستهدفة. أما باقي بيانات الجدول فتبقى كما هي دون أي تعديل.

جملة WHERE ليست اختيارية من الناحية العملية

من الناحية النظرية، تُعتبر جملة WHERE اختيارية. لكن من الناحية العملية، إهمالها هو السبب الأول الذي يجعل المطورين المبتدئين يقضون فترة ما بعد الظهر في إصلاح الكوارث:

UPDATE users SET status = 'inactive';
-- أصبح كل مستخدم الآن غير نشط

غياب الشرط يعني أنّ كل الصفوف ستُطابَق، وSQLite سينفّذ الأمر دون أي اعتراض. اعتد دائمًا على كتابة WHERE أولًا ثم SET بعدها — هذه العادة وحدها كفيلة بتجنّب كثير من الكوارث.

وإذا لم تكن متأكدًا من صحة شرط WHERE، فجرّب الشرط نفسه مع SELECT قبل تنفيذ التحديث:

نفس الشرط، لكن بأمرين. اعتبر الـ SELECT بمثابة بروفة قبل التنفيذ الفعلي.

تحديث عدة أعمدة في sqlite

تقدر تحدّث أكثر من عمود دفعة واحدة بفصل التعيينات بفواصل داخل SET واحدة. SET واحدة وعدة أعمدة:

رحلة واحدة فقط إلى قاعدة البيانات، صف واحد تم تعديله، وثلاثة أعمدة جرى تحديثها. لا داعي لكتابة ثلاث جمل UPDATE منفصلة طالما أن جملة واحدة تكفي.

التعابير بعد علامة =

القيمة التي تأتي بعد = ليست مقتصرة على القيم الحرفية، بل يمكن أن تكون أي تعبير برمجي — بما في ذلك تعبير يعتمد على القيمة الحالية للعمود نفسه:

price * 1.10 يقرأ السعر الحالي، يضربه، ثم يكتب الناتج مكانه. ينفّذ SQLite الطرف الأيمن اعتماداً على القيم الحالية للصف قبل تطبيق أي إسناد من إسنادات هذه الجملة، فبإمكانك الإشارة إلى أكثر من عمود دون قلق:

UPDATE products SET price = price * 1.10, stock = stock + price;
-- إن قيمة 'price' في الطرف الأيمن هنا هي السعر القديم، وليس السعر الذي تم تحديثه للتو.

UPDATE ... FROM: تحديث الأعمدة بقيم من جدول آخر

ابتداءً من الإصدار 3.33، أصبح UPDATE في SQLite يدعم جملة FROM، وهي أنظف طريقة لتحديث بيانات جدول اعتمادًا على جدول آخر ومزامنة القيم بينهما:

الاستعلام الفرعي يحسب الإجماليات لكل عميل، ثم تقوم جملة UPDATE الخارجية بربط هذه النتائج مع جدول customers عبر العمود id. لو لم تكن صيغة UPDATE ... FROM متاحة، لاضطررت إلى كتابة استعلام فرعي مرتبط لكل عمود على حدة، وهذا يجعل الكود أكثر فوضى.

إليك بعض القواعد التي يجب الانتباه لها:

  • اسم الجدول الهدف يُكتب بعد UPDATE مباشرةً، وليس ضمن قائمة FROM.
  • جملة WHERE هي التي تتولى عملية الربط (الـ join)، فلا توجد كلمة ON هنا.
  • إذا كان الربط يحتمل مطابقة أكثر من صف في FROM، فالنتيجة غير محددة. تأكد أن مفاتيح الربط تُنتج مطابقة واحدة على الأكثر لكل صف هدف.

استخدام RETURNING لمعرفة الصفوف المعدّلة

ابتداءً من الإصدار 3.35، يسمح لك SQLite بإرجاع الصفوف المُحدَّثة من جملة UPDATE نفسها. هذا مفيد جداً عندما يحتاج تطبيقك إلى القيم بعد التحديث دون الحاجة إلى تنفيذ SELECT إضافي بعدها:

ترجع لك الصفوف التي فعلاً تعدّلت بقيمها الجديدة. هذا يوفّر عليك رحلة ثانية للسيرفر، ويقضي على نوع كامل من مشاكل التعارض (race conditions) في الكود المتزامن. في فصل لاحق صفحة كاملة مخصصة لـ RETURNING.

UPDATE OR REPLACE: التعامل مع تعارضات القيود

لو كان التحديث الذي تنفّذه سيخالف قيد UNIQUE، فالسلوك الافتراضي هو إلغاء التنفيذ ورمي خطأ. لكن جملة OR تتيح لك اختيار سياسة مختلفة:

الخيارات المتاحة هي OR ABORT (وهو الافتراضي)، وOR REPLACE، وOR IGNORE، وOR FAIL، وOR ROLLBACK. الخيار الخطير منها هو REPLACE، لأنه يحذف الصف المتعارض، وقد يمتد هذا الحذف عبر المفاتيح الأجنبية ويُسبّب سلسلة من العمليات غير المرغوبة. لا تستخدمه إلا حين تقصد فعلاً: "لو وُجد صف بنفس القيمة الفريدة، تخلّص منه".

أما في معظم سيناريوهات الـ upsert، فإن صيغة INSERT ... ON CONFLICT المخصصة لذلك تكون أوضح بكثير، وهناك صفحة كاملة تشرحها.

تغليف عمليات التحديث الحساسة داخل معاملة (Transaction)

عندما تُعدّل عدداً كبيراً من الصفوف، أو تُنفّذ عدة جمل UPDATE يجب أن تنجح كلها معاً أو لا تنجح أصلاً، ضعها داخل معاملة. وهكذا، إذا حدث أي خطأ، يمكنك التراجع (rollback) والعودة إلى الحالة السابقة:

إذا فشلت الجملة الثانية (لنقل أن قيدًا ما تدخّل)، فإن ROLLBACK يتراجع عن الأولى. بدون استخدام المعاملات، ستجد نفسك أمام تحويل نصف مكتمل — حُسم من Ada مبلغ 25 ولم يتغير رصيد Boris. سنُفرد للمعاملات فصلًا خاصًا لاحقًا، يكفي الآن أن تعرف أنها موجودة، وأن عمليات التحديث المُجمَّعة يجب أن تكون داخلها في الغالب.

الأخطاء الشائعة في أمر update في sqlite

قائمة موجزة بأكثر الأمور التي يقع فيها المطورون:

  • نسيان WHERE — سيؤدي ذلك إلى تحديث جميع الصفوف. اقرأ الجملة بصوت مرتفع قبل تنفيذها.
  • استخدام معامل خاطئ داخل WHERE — الجملة WHERE status = NULL لن تطابق أي صف. استخدم IS NULL بدلًا منها. سنتناول هذه النقطة بالتفصيل في صفحة المعاملات.
  • التحديث باستعلام فرعي يُرجع أكثر من صف بينما كنت تتوقع صفًا واحدًا. أضف LIMIT 1 أو استخدم دالة تجميع داخل الاستعلام الفرعي، وإلا ستحصل على أخطاء أو نتائج غير متوقعة.
  • الخلط بين UPDATE OR REPLACE وبين UPSERT. OR REPLACE يحذف الصفوف المتعارضة، أما INSERT ... ON CONFLICT DO UPDATE فيُعدّلها في مكانها. عمليتان مختلفتان تمامًا.

الخطوة التالية: DELETE

UPDATE يُعدّل الصفوف، بينما DELETE يحذفها. ينطبق على الأمرين نفس الانضباط في استخدام WHERE، وكذلك العادة الذهبية بتشغيل SELECT أولًا، فهي ستُجنّبك الكوارث نفسها. هذا ما سنتناوله في الصفحة التالية.

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

ما هي الصيغة الأساسية لأمر UPDATE في SQLite؟

الصيغة هي: UPDATE table_name SET column = value WHERE condition;. جملة SET تُحدِّد الأعمدة التي تريد تغييرها وقيمها الجديدة، أما WHERE فهي التي تختار الصفوف المعنية بالتعديل — وإذا نسيتها، سيتم تحديث كل صف في الجدول دون استثناء، فانتبه.

كيف أُحدِّث عدة أعمدة في عبارة واحدة؟

افصل بين عمليات الإسناد بفاصلة داخل جملة SET نفسها، هكذا: UPDATE users SET name = 'Ada', email = 'ada@x.com' WHERE id = 1;. عبارة واحدة، استعلام واحد على قاعدة البيانات، وصف واحد يتم تحديثه. لا داعي لتكرار SET لكل عمود.

هل يمكن تحديث جدول من بيانات جدول آخر في SQLite؟

نعم، عبر UPDATE ... FROM المُضافة في الإصدار 3.33، التي تسمح لك بضمّ جدول آخر أو استعلام فرعي إلى عملية التحديث. الصيغة تكون: UPDATE target SET col = source.col FROM source WHERE target.id = source.id;. وهي الطريقة الأنظف لنقل القيم بين الجداول.

Coddy programming languages illustration

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

ابدأ الآن