SQL: إدراج واختيار البيانات
إدراج البيانات باستخدام INSERT
عبارة INSERT INTO تضيف صفوف (سجلات) جديدة إلى جدول.
الصيغة الأساسية
INSERT INTO table_name (column1, column2, column3) VALUES (value1, value2, value3);
مثال: إدراج مستخدم واحد
INSERT INTO users (username, email, password)
VALUES ('john_doe', 'john@example.com', 'hashed_password_here');
ملاحظات مهمة
- قيم النصوص يجب أن تكون محاطة بعلامات اقتباس مفردة:
'text' - الأرقام لا تحتاج إلى علامات اقتباس:
25,19.99 - أعمدة AUTO_INCREMENT (مثل
id) يتم إنشاؤها تلقائياً - لا تقم بتضمينها - الأعمدة ذات القيم الافتراضية (مثل
created_at) يمكن حذفها
الإدراج بدون أسماء الأعمدة
إذا قدمت قيماً لجميع الأعمدة بالترتيب الدقيق الذي تم تعريفها به:
INSERT INTO users VALUES (NULL, 'jane_doe', 'jane@example.com', 'hashed_password', NOW()); -- NULL لـ AUTO_INCREMENT id -- NOW() للطابع الزمني
أفضل ممارسة: حدد دائماً أسماء الأعمدة بشكل صريح. هذا يجعل كودك أكثر قابلية للقراءة ويمنع الأخطاء إذا تغير هيكل الجدول.
إدراج صفوف متعددة
أدرج سجلات متعددة في استعلام واحد لأداء أفضل:
INSERT INTO users (username, email, password)
VALUES
('alice', 'alice@example.com', 'password1'),
('bob', 'bob@example.com', 'password2'),
('charlie', 'charlie@example.com', 'password3');
مثال: إدراج المنتجات
INSERT INTO products (name, description, price, stock, category)
VALUES
('Laptop', 'High-performance laptop', 899.99, 15, 'Electronics'),
('Mouse', 'Wireless mouse', 19.99, 50, 'Electronics'),
('Desk Chair', 'Ergonomic office chair', 199.99, 8, 'Furniture');
الحصول على آخر معرف تم إدراجه
-- في MySQL، بعد INSERT: SELECT LAST_INSERT_ID(); -- في PHP (mysqli): $last_id = $mysqli->insert_id; -- في PHP (PDO): $last_id = $pdo->lastInsertId();
اختيار البيانات باستخدام SELECT
عبارة SELECT تسترجع البيانات من جدول واحد أو أكثر.
اختيار جميع الأعمدة
SELECT * FROM users;
* تعني "جميع الأعمدة". المخرجات:
+----+----------+-------------------+------------------+---------------------+ | id | username | email | password | created_at | +----+----------+-------------------+------------------+---------------------+ | 1 | john_doe | john@example.com | hashed_password | 2024-01-15 10:30:00 | | 2 | jane_doe | jane@example.com | hashed_password | 2024-01-15 11:45:00 | +----+----------+-------------------+------------------+---------------------+
اختيار أعمدة محددة
SELECT username, email FROM users;
المخرجات:
+----------+-------------------+ | username | email | +----------+-------------------+ | john_doe | john@example.com | | jane_doe | jane@example.com | +----------+-------------------+
نصيحة للأداء: اختر فقط الأعمدة التي تحتاجها بدلاً من استخدام SELECT *. هذا يقلل نقل البيانات ويحسن الأداء، خاصة مع الجداول الكبيرة.
التصفية باستخدام WHERE
شرط WHERE يرشح النتائج بناءً على الشروط.
صيغة WHERE الأساسية
SELECT columns FROM table WHERE condition;
عوامل المقارنة
-- يساوي SELECT * FROM products WHERE category = 'Electronics'; -- لا يساوي SELECT * FROM products WHERE category != 'Electronics'; -- أو SELECT * FROM products WHERE category <> 'Electronics'; -- أكبر من SELECT * FROM products WHERE price > 100; -- أصغر من SELECT * FROM products WHERE stock < 10; -- أكبر من أو يساوي SELECT * FROM products WHERE price >= 50; -- أصغر من أو يساوي SELECT * FROM products WHERE stock <= 20;
العوامل المنطقية (AND, OR, NOT)
-- AND: يجب أن يكون كلا الشرطين صحيحين SELECT * FROM products WHERE category = 'Electronics' AND price < 500; -- OR: يجب أن يكون شرط واحد على الأقل صحيحاً SELECT * FROM products WHERE category = 'Electronics' OR category = 'Furniture'; -- NOT: ينفي شرطاً SELECT * FROM products WHERE NOT category = 'Electronics'; -- دمج شروط متعددة SELECT * FROM products WHERE (category = 'Electronics' OR category = 'Furniture') AND price BETWEEN 50 AND 500;
عامل BETWEEN
-- اختيار المنتجات بسعر بين 50 و 200 SELECT * FROM products WHERE price BETWEEN 50 AND 200; -- يعادل: SELECT * FROM products WHERE price >= 50 AND price <= 200;
عامل IN
-- اختيار المنتجات في فئات محددة
SELECT * FROM products
WHERE category IN ('Electronics', 'Furniture', 'Books');
-- يعادل:
SELECT * FROM products
WHERE category = 'Electronics'
OR category = 'Furniture'
OR category = 'Books';
عامل LIKE (مطابقة الأنماط)
-- % يطابق أي تسلسل من الأحرف -- _ يطابق حرفاً واحداً بالضبط -- المنتجات التي تبدأ بـ 'Lap' SELECT * FROM products WHERE name LIKE 'Lap%'; -- المنتجات التي تنتهي بـ 'mouse' SELECT * FROM products WHERE name LIKE '%mouse'; -- المنتجات التي تحتوي على 'chair' SELECT * FROM products WHERE name LIKE '%chair%'; -- المنتجات التي تحتوي على 5 أحرف بالضبط SELECT * FROM products WHERE name LIKE '_____'; -- غير حساس لحالة الأحرف افتراضياً في MySQL SELECT * FROM users WHERE email LIKE '%@gmail.com';
قيم NULL
-- العثور على المنتجات بدون وصف SELECT * FROM products WHERE description IS NULL; -- العثور على المنتجات بوصف SELECT * FROM products WHERE description IS NOT NULL; -- ملاحظة: لا يمكنك استخدام = أو != مع NULL -- خطأ: WHERE description = NULL -- صحيح: WHERE description IS NULL
الترتيب باستخدام ORDER BY
شرط ORDER BY يرتب النتائج بترتيب تصاعدي (ASC) أو تنازلي (DESC).
الترتيب بعمود واحد
-- الترتيب حسب السعر (تصاعدي - الأقل أولاً) SELECT * FROM products ORDER BY price ASC; -- الترتيب حسب السعر (تنازلي - الأعلى أولاً) SELECT * FROM products ORDER BY price DESC; -- ASC افتراضي، لذا هذا يعادل: SELECT * FROM products ORDER BY price;
الترتيب بأعمدة متعددة
-- الترتيب حسب الفئة، ثم حسب السعر ضمن كل فئة SELECT * FROM products ORDER BY category ASC, price DESC;
دمج WHERE و ORDER BY
SELECT name, price, stock FROM products WHERE category = 'Electronics' AND stock > 0 ORDER BY price DESC;
تحديد النتائج باستخدام LIMIT
شرط LIMIT يقيد عدد الصفوف المرجعة.
LIMIT الأساسي
-- الحصول على أول 5 منتجات SELECT * FROM products LIMIT 5; -- الحصول على 5 منتجات الأغلى SELECT * FROM products ORDER BY price DESC LIMIT 5;
LIMIT مع OFFSET (الترقيم)
-- تخطي أول 10 صفوف، إرجاع التالية 5 SELECT * FROM products LIMIT 5 OFFSET 10; -- صيغة بديلة (أقدم) SELECT * FROM products LIMIT 10, 5; -- LIMIT offset, count -- مثال: الصفحة 1 (0-9) SELECT * FROM products LIMIT 10 OFFSET 0; -- الصفحة 2 (10-19) SELECT * FROM products LIMIT 10 OFFSET 10; -- الصفحة 3 (20-29) SELECT * FROM products LIMIT 10 OFFSET 20;
صيغة الترقيم
-- الصيغة: LIMIT items_per_page OFFSET (page - 1) * items_per_page -- الصفحة 1، 20 عنصر لكل صفحة: SELECT * FROM products LIMIT 20 OFFSET 0; -- الصفحة 3، 20 عنصر لكل صفحة: SELECT * FROM products LIMIT 20 OFFSET 40;
دوال SELECT المفيدة
COUNT - عد الصفوف
-- عد جميع المنتجات SELECT COUNT(*) FROM products; -- عد المنتجات في فئة الإلكترونيات SELECT COUNT(*) FROM products WHERE category = 'Electronics'; -- عد الأوصاف غير NULL SELECT COUNT(description) FROM products;
SUM - حساب المجموع
-- القيمة الإجمالية لجميع المنتجات في المخزون SELECT SUM(price * stock) AS total_inventory_value FROM products; -- كمية المخزون الإجمالية SELECT SUM(stock) FROM products;
AVG - حساب المتوسط
-- متوسط سعر المنتج SELECT AVG(price) FROM products; -- متوسط السعر في فئة الإلكترونيات SELECT AVG(price) FROM products WHERE category = 'Electronics';
MIN و MAX
-- أرخص سعر منتج SELECT MIN(price) FROM products; -- أغلى سعر منتج SELECT MAX(price) FROM products; -- المنتج بأعلى سعر SELECT * FROM products ORDER BY price DESC LIMIT 1;
DISTINCT - إزالة التكرارات
-- الحصول على الفئات الفريدة SELECT DISTINCT category FROM products; -- عد الفئات الفريدة SELECT COUNT(DISTINCT category) FROM products;
أسماء مستعارة للأعمدة باستخدام AS
-- إعادة تسمية الأعمدة في المخرجات
SELECT
name AS product_name,
price AS cost,
stock AS quantity_available
FROM products;
-- استخدام في الحسابات
SELECT
name,
price,
stock,
price * stock AS total_value
FROM products;
أمثلة عملية
مثال 1: بحث عن منتجات التجارة الإلكترونية
-- البحث عن أجهزة الكمبيوتر المحمولة بأقل من 1000 دولار، في المخزون، مرتبة حسب السعر SELECT name, price, stock FROM products WHERE name LIKE '%laptop%' AND price < 1000 AND stock > 0 ORDER BY price ASC;
مثال 2: تقرير تسجيل المستخدمين
-- الحصول على المستخدمين المسجلين في آخر 7 أيام SELECT username, email, created_at FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY created_at DESC;
مثال 3: تنبيه المخزون المنخفض
-- المنتجات بمخزون أقل من 10 وحدات SELECT name, stock, category FROM products WHERE stock < 10 AND stock > 0 ORDER BY stock ASC;
مثال 4: لوحة تحكم المبيعات
-- إحصائيات ملخصة
SELECT
COUNT(*) AS total_products,
SUM(stock) AS total_items_in_stock,
AVG(price) AS average_price,
MIN(price) AS cheapest_product,
MAX(price) AS most_expensive_product,
SUM(price * stock) AS total_inventory_value
FROM products
WHERE is_active = 1;
تمرين: استعلامات كتالوج المنتجات
باستخدام جدول المنتجات، اكتب استعلامات SQL لما يلي:
- أدرج 3 منتجات جديدة في فئات مختلفة
- اختر جميع المنتجات مرتبة حسب السعر (الأعلى إلى الأقل)
- ابحث عن جميع المنتجات في فئة "الإلكترونيات" بسعر بين 50 و 500 دولار
- احصل على أحدث 10 منتجات مضافة
- عد عدد المنتجات في كل فئة
- ابحث عن المنتجات التي تحتوي أسماؤها على "pro" (غير حساس لحالة الأحرف)
- احسب القيمة الإجمالية لكل المخزون
- احصل على أغلى 5 منتجات الموجودة في المخزون
أفضل الممارسات
- استخدم WHERE بحذر دائماً: الاستعلامات بدون WHERE يمكن أن تؤثر على جميع الصفوف عن طريق الخطأ
- استخدم LIMIT: عند اختبار الاستعلامات، أضف LIMIT لتجنب النتائج الطويلة
- فهرس الأعمدة المبحوث عنها بشكل متكرر: أضف فهارس على الأعمدة المستخدمة في WHERE و ORDER BY و JOIN
- استخدم أسماء أعمدة محددة: تجنب
SELECT *في كود الإنتاج - نظّف مدخلات المستخدم: لا تضع مدخلات المستخدم مباشرة في SQL (يمنع حقن SQL)
- استخدم العبارات المحضرة: في PHP، استخدم عبارات PDO أو mysqli المحضرة
تحذير حقن SQL
لا تقم أبداً ببناء استعلامات SQL عن طريق دمج مدخلات المستخدم:
// خطير - لا تفعل هذا أبداً!
$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";
// آمن - استخدم العبارات المحضرة (سنغطيها في دروس لاحقة)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_POST['username']]);
ترتيب تنفيذ الاستعلام
شروط SQL تُكتب بهذا الترتيب:
SELECT- الأعمدة المراد إرجاعهاFROM- الجدول المراد الاستعلام عنهWHERE- تصفية الصفوفGROUP BY- تجميع الصفوف (سنغطيه لاحقاً)HAVING- تصفية المجموعات (سنغطيه لاحقاً)ORDER BY- ترتيب النتائجLIMIT- تقييد عدد الصفوف
لكن MySQL ينفذها بترتيب مختلف: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
ما التالي؟
في الدرس التالي، ستتعلم كيفية تعديل البيانات الموجودة باستخدام UPDATE وإزالة البيانات باستخدام عبارات DELETE، إلى جانب ممارسات السلامة المهمة.