تحديث البيانات: UPDATE والمعاملات
نعدّل البيانات بدقة، ونجمع العمليات المترابطة في معاملة آمنة. ⏱ نحو 30 دقيقة.
- تعدّل قيم صف أو صفوف بـ
UPDATE…SET…WHERE. - تحسب القيمة الجديدة من القديمة، وتعدّل بشرط من جدول آخر.
- تتجنب كارثة
UPDATEبلاWHERE. - تستخدم المعاملات
BEGINوCOMMITوROLLBACKوتشرحACID.
١تعديل القيم: UPDATE
UPDATE يغيّر قيمًا في صفوف موجودة: الجدول، ثم SET العمود = القيمة الجديدة، ثم WHERE لتحديد الصفوف:
UPDATE productsSET price = 40WHERE id = 1; SELECT id, name, price FROM products WHERE id = 1;
| id | name | price |
|---|---|---|
| 1 | قهوة عربية 250غ | 40 |
عدة أعمدة معًا، وقيمة محسوبة من القيمة القديمة:
-- رفع أسعار العسل 10% وإضافة 5 قطع للمخزونUPDATE productsSET price = ROUND(price * 1.10, 2), stock = stock + 5WHERE category = 'عسل'; SELECT name, price, stock FROM products WHERE category = 'عسل';
| name | price | stock |
|---|---|---|
| عسل سدر 500غ | 165 | 17 |
| عسل زهور 500غ | 66 | 35 |
٢أخطر سطر في SQL
نسيان WHERE يعدّل كل صفوف الجدول، بلا تحذير:
UPDATE customers SET city = 'جدة'; -- نسينا WHERE! SELECT name, city FROM customers;
| name | city |
|---|---|
| سعود العتيبي | جدة |
| نورة القحطاني | جدة |
| خالد الحربي | جدة |
| ريم الشهري | جدة |
| فهد الدوسري | جدة |
| سارة المطيري | جدة |
| عبدالله الزهراني | جدة |
| هند السبيعي | جدة |
| ماجد الغامدي | جدة |
| لمى العنزي | جدة |
UPDATE orders SET status = 'مُسلَّم';SELECT id, status FROM orders WHERE id = 7; -- تأكد أولًاUPDATE orders SET status = 'مُسلَّم' WHERE id = 7;
| id | status |
|---|---|
| 7 | قيد الشحن |
٣التحديث بشرط من جدول آخر
«سلّموا كل طلبات العملاء في الرياض». الشرط في جدول العملاء، والتعديل في جدول الطلبات، فنستخدم استعلامًا فرعيًّا:
UPDATE ordersSET status = 'مُسلَّم'WHERE customer_id IN (SELECT id FROM customers WHERE city = 'الرياض'); SELECT id, customer_id, status FROM orders WHERE customer_id IN (2, 5);
| id | customer_id | status |
|---|---|---|
| 2 | 2 | مُسلَّم |
| 6 | 5 | مُسلَّم |
| 7 | 2 | مُسلَّم |
٤المعاملة: كل شيء أو لا شيء
تحويل 500 ريال من نواف إلى عزام عمليتان: خصم من الأول، وإضافة للثاني. لو انقطع التيار بينهما ضاعت 500 ريال! المعاملة Transaction تجمع عدة أوامر في وحدة واحدة: إما تُنفَّذ كلها، وإما لا يُنفَّذ منها شيء:
| الأمر | الوظيفة |
|---|---|
BEGIN (في MySQL أيضًا START TRANSACTION) | بداية المعاملة |
COMMIT | اعتماد كل التغييرات نهائيًّا |
ROLLBACK | إلغاء كل التغييرات منذ BEGIN |
CREATE TABLE accounts ( id INTEGER PRIMARY KEY, owner TEXT, balance REAL CHECK (balance >= 0));INSERT INTO accounts VALUES (1, 'نواف', 1000), (2, 'عزام', 300); BEGIN;UPDATE accounts SET balance = balance - 500 WHERE id = 1;UPDATE accounts SET balance = balance + 500 WHERE id = 2;COMMIT; SELECT * FROM accounts;
| id | owner | balance |
|---|---|---|
| 1 | نواف | 500 |
| 2 | عزام | 800 |
والآن تراجعنا قبل الاعتماد:
CREATE TABLE accounts ( id INTEGER PRIMARY KEY, owner TEXT, balance REAL CHECK (balance >= 0));INSERT INTO accounts VALUES (1, 'نواف', 1000), (2, 'عزام', 300); BEGIN;UPDATE accounts SET balance = 0; -- خطأ كارثي!SELECT * FROM accounts; -- داخل المعاملة: صفرROLLBACK; SELECT * FROM accounts; -- بعد التراجع: كما كانت
| id | owner | balance |
|---|---|---|
| 1 | نواف | 0 |
| 2 | عزام | 0 |
(ROLLBACK)| id | owner | balance |
|---|---|---|
| 1 | نواف | 1000 |
| 2 | عزام | 300 |
٥خصائص ACID
أنظمة قواعد البيانات العلائقية تضمن للمعاملة أربع خصائص، تُختصر ACID:
| الخاصية | معناها | في مثال التحويل |
|---|---|---|
| Atomicity الذرية | كلها أو لا شيء. | لا خصم بلا إضافة. |
| Consistency الاتساق | تنقل القاعدة من حالة صحيحة إلى حالة صحيحة، والقيود محترمة. | CHECK يمنع رصيدًا سالبًا. |
| Isolation العزل | المعاملات المتزامنة لا يرى بعضها نصف عمل بعض. | لا يرى أحد الرصيدين في منتصف التحويل. |
| Durability الديمومة | بعد COMMIT تبقى التغييرات حتى لو انقطع التيار. | التحويل محفوظ. |
CREATE TABLE accounts ( id INTEGER PRIMARY KEY, owner TEXT, balance REAL CHECK (balance >= 0));INSERT INTO accounts VALUES (1, 'نواف', 1000), (2, 'عزام', 300); BEGIN;UPDATE accounts SET balance = balance - 800 WHERE id = 2;
عزام لديه 300 فقط، فرفض قيد CHECK الخصم. وفي التطبيق الحقيقي يلتقط البرنامج هذا الخطأ وينفّذ ROLLBACK للمعاملة كلها.
توقّع وتحقّق
تعديل القيم يكون بالأمر:
DML.UPDATE بلا WHERE:
لإلغاء تغييرات المعاملة:
COMMIT.حرف A في ACID:
الخلاصة
UPDATE t SETعمود = قيمة, …WHEREشرط;- بلا
WHEREيتعدّل كل الجدول: اختبر الشرط بـSELECTأولًا. - المعاملة:
BEGINثم الأوامر ثمCOMMITللاعتماد أوROLLBACKللإلغاء. ACID: الذرية والاتساق والعزل والديمومة.
تحدٍّ برمجي: تحديث المخزون والأسعار
متوسطوصلت شحنة جديدة وتغيرت الأسعار. نفّذ التعديلات داخل معاملة واحدة واعتمدها.
- ابدأ معاملة.
- التمر السكري (رقم 4) وصلت منه 30 قطعة، وكان مخزونه صفرًا: اجعل مخزونه 30.
- خفّض سعر كل منتجات «أدوات» 5 ريالات.
- اعتمد المعاملة.
👀 اعرض النتيجة المطلوبة
| stock |
|---|
| 30 |
| id | price |
|---|---|
| 7 | 70 |
| 8 | 35 |
| 12 | 115 |
| id | price | stock |
|---|---|---|
| 1 | 35 | 40 |
| 2 | 18 | 65 |
| 3 | 90 | 25 |
| 5 | 150 | 12 |
| 6 | 60 | 30 |
| 9 | 28 | 50 |
| 10 | 55 | 15 |
| 11 | 12 | 100 |
- الكود يعمل بلا أخطاء
- مخزون التمر السكري 30
- أسعار الأدوات انخفضت 5 ريالات
- بقية المنتجات لم تتغير
- تبدأ معاملة
- تعتمدها بـ COMMIT
💡 تلميح 1
UPDATE products SET stock = 30 WHERE id = 4;💡 تلميح 2
price = price - 5 مع WHERE category = 'أدوات'حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
BEGIN; UPDATE products SET stock = 30 WHERE id = 4; UPDATE products SET price = price - 5 WHERE category = 'أدوات'; COMMIT;