CRUD Operations — SQL الأساسيات
عمليات CRUD
كل الأمثلة تفترض الجداول التالية (المثال الكامل ينشئها):
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
city TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
total REAL NOT NULL CHECK (total >= 0),
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'cancelled')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
INSERT INTO users (id, name, email, city) VALUES
(1, 'سارة', 'sara@example.com', 'بغداد'),
(2, 'عمر', 'omar@example.com', 'البصرة'),
(3, 'ليلى', 'layla@example.com', 'بغداد'),
(4, 'زيد', 'zaid@example.com', NULL);
INSERT INTO orders (user_id, total, status) VALUES
(1, 120.0, 'paid'), (1, 45.5, 'paid'), (2, 300.0, 'pending'),
(3, 80.0, 'paid'), (3, 15.0, 'cancelled'), (1, 60.0, 'pending');INSERT — إضافة
CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL NOT NULL);
INSERT INTO products (name, price) VALUES ('قلم', 1.5);
INSERT INTO products (name, price) VALUES ('دفتر', 3.0), ('ممحاة', 0.5); -- عدة صفوفاكتب أسماء الأعمدة دائماً: يحمي كودك إذا أُضيف عمود جديد للجدول لاحقاً.
SELECT — قراءة
CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL NOT NULL, category TEXT);
INSERT INTO products (name, price, category) VALUES ('قلم', 1.5, 'قرطاسية'), ('سماعة', 25, 'إلكترونيات'), ('دفتر', 3, 'قرطاسية');
SELECT name, price FROM products WHERE category = 'قرطاسية' AND price < 5 ORDER BY price DESC LIMIT 10;
SELECT * FROM products WHERE name LIKE '%ف%'; -- يحتوي "ف"
SELECT * FROM products WHERE price BETWEEN 2 AND 30;
SELECT * FROM products WHERE category IN ('قرطاسية', 'كتب');
SELECT DISTINCT category FROM products;- اطلب الأعمدة التي تحتاجها بدل * في كود الإنتاج.
- ORDER BY ضروري إن كان الترتيب يهمك؛ بدونه الترتيب غير مضمون.
NULL: ليس قيمة بل "غير معروف"
CREATE TABLE people (name TEXT, city TEXT);
INSERT INTO people VALUES ('سارة', 'بغداد'), ('زيد', NULL);
SELECT * FROM people WHERE city = NULL; -- لا يعيد شيئاً أبداً!
SELECT * FROM people WHERE city IS NULL; -- الصحيح
SELECT name, COALESCE(city, 'غير محدد') AS city FROM people;أي مقارنة مع NULL نتيجتها "غير معروف" (لا صحيح ولا خطأ). و city <> 'بغداد' لا تعيد صفوف NULL أيضاً.
UPDATE — تعديل
CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL);
INSERT INTO products VALUES (1, 'قلم', 1.5), (2, 'دفتر', 3);
UPDATE products SET price = price * 1.10 WHERE id = 2;DELETE — حذف
CREATE TABLE sessions (id INTEGER PRIMARY KEY, expires_at TEXT);
INSERT INTO sessions VALUES (1, '2020-01-01'), (2, '2999-01-01');
DELETE FROM sessions WHERE expires_at < date('now');⚠️ الخطأ الأخطر
UPDATE products SET price = 0; أو DELETE FROM users; بلا WHERE يعدّل/يحذف كل الصفوف. عادات تحميك:
1. اكتب الاستعلام كـ SELECT ... WHERE ... أولاً وتأكد من الصفوف، ثم حوّله.
2. نفّذ داخل معاملة (BEGIN ... ثم ROLLBACK إن أخطأت) — درس المعاملات.
3. نسخ احتياطية دائماً، وصلاحيات محدودة لمستخدم التطبيق.
الحذف الناعم
تطبيقات كثيرة لا تحذف فعلاً بل تضع deleted_at وتستبعد هذه الصفوف في الاستعلامات — للاستعادة والتدقيق.
تمرين
على جداول المثال: أضف مستخدماً، اعرض الطلبات المدفوعة بترتيب تنازلي للمبلغ، غيّر حالة الطلبات المعلقة الأقدم من 30 يوماً إلى cancelled (جرّبها كـ SELECT أولاً)، واعرض المستخدمين بلا مدينة.
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
city TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
total REAL NOT NULL CHECK (total >= 0),
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'cancelled')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
INSERT INTO users (id, name, email, city) VALUES
(1, 'سارة', 'sara@example.com', 'بغداد'),
(2, 'عمر', 'omar@example.com', 'البصرة'),
(3, 'ليلى', 'layla@example.com', 'بغداد'),
(4, 'زيد', 'zaid@example.com', NULL);
INSERT INTO orders (user_id, total, status) VALUES
(1, 120.0, 'paid'), (1, 45.5, 'paid'), (2, 300.0, 'pending'),
(3, 80.0, 'paid'), (3, 15.0, 'cancelled'), (1, 60.0, 'pending');
-- قراءة
SELECT id, name, city FROM users WHERE city = 'بغداد' ORDER BY name;
SELECT name, COALESCE(city, 'غير محدد') AS city FROM users WHERE city IS NULL;
-- تعديل: جرّب الشرط بـ SELECT أولاً
SELECT id, status FROM orders WHERE status = 'pending' AND user_id = 1;
UPDATE orders SET status = 'paid' WHERE status = 'pending' AND user_id = 1;
-- حذف بشرط
DELETE FROM orders WHERE status = 'cancelled';
SELECT status, COUNT(*) AS n FROM orders GROUP BY status;اختبر فهمك