📌 ما هي قيمة NULL؟
NULL تعني "لا قيمة" أو "قيمة غير معروفة". ليست صفرًا ولا مسافة فارغة.
🎯 تفسيرات NULL
- قيمة غير معروفة: مثل تاريخ ميلاد شخص غير مدخل.
- قيمة غير متوفرة: مثل رقم هاتف شخص لا يملك هاتفًا.
- غير منطبق: مثل حقل "المرتبة" لموظف ليس في نظام المراتب.
⚡ المنطق ثلاثي القيم في SQL
SQL لا تستخدم منطق TRUE/FALSE فقط، بل منطق ثلاثي القيم:
- TRUE: الشرط صحيح.
- FALSE: الشرط خطأ.
- UNKNOWN: لا يمكن تحديد الصحة (عند وجود NULL).
جداول الحقيقة للمنطق ثلاثي القيم
| AND |
TRUE |
FALSE |
UNKNOWN |
| TRUE |
TRUE |
FALSE |
UNKNOWN |
| FALSE |
FALSE |
FALSE |
FALSE |
| UNKNOWN |
UNKNOWN |
FALSE |
UNKNOWN |
| OR |
TRUE |
FALSE |
UNKNOWN |
| TRUE |
TRUE |
TRUE |
TRUE |
| FALSE |
TRUE |
FALSE |
UNKNOWN |
| UNKNOWN |
TRUE |
UNKNOWN |
UNKNOWN |
💡 التعامل مع NULL
مهم جدًا: لا نستخدم = NULL أبدًا، بل IS NULL أو IS NOT NULL.
SELECT Fname, Lname
FROM EMPLOYEE
WHERE Super_ssn IS NULL;
SELECT Fname, Lname
FROM EMPLOYEE
WHERE Super_ssn IS NOT NULL;
⚠️ حقائق عن NULL
- NULL = NULL يُنتج UNKNOWN، وليس TRUE.
- كل NULL يُعامل كقيمة فريدة ومختلفة عن أي NULL آخر (لأغراض المقارنة).
- عند GROUP BY، كل قيم NULL تجتمع في مجموعة واحدة.
- دوال التجميع مثل SUM و AVG تتجاهل قيم NULL.
📌 تعريف
الاستعلام المتداخل هو استعلام SELECT ... FROM ... WHERE كامل داخل استعلام SQL آخر. يُستخدم لجلب بيانات تعتمد على نتيجة استعلام آخر.
مثال أساسي: خطوتين مقابل خطوة واحدة
💡 مثال: ورش العمل
المطلوب: إيجاد جميع ورش العمل التي يقدمها نفس مقدم ورشة "Robot Operating System".
الطريقة 1: استعلامان منفصلان
SELECT Presenter
FROM Workshop
WHERE Title = 'Robot Operating System';
SELECT *
FROM Workshop
WHERE Presenter = 'Dr. Maram';
الطريقة 2: استعلام واحد متداخل
SELECT *
FROM Workshop
WHERE Presenter = (SELECT Presenter
FROM Workshop
WHERE Title = 'Robot Operating System');
استخدام IN
IN يتحقق إذا كانت القيمة موجودة ضمن مجموعة القيم الناتجة من الاستعلام الداخلي.
💡 IN مع عدة أعمدة
SELECT DISTINCT Essn
FROM WORKS_ON
WHERE (Pno, Hours) IN (SELECT Pno, Hours
FROM WORKS_ON
WHERE Essn = '123456789');
استخدام SOME / ANY و ALL
= SOME أو = ANY يُعادل IN.
> SOME يعني أكبر من عنصر واحد على الأقل في القائمة.
> ALL يعني أكبر من جميع العناصر في القائمة.
💡 ALL
SELECT Lname, Fname
FROM EMPLOYEE
WHERE Salary > ALL (SELECT Salary
FROM EMPLOYEE
WHERE Dno = 5);
مجموعات صريحة (Explicit Sets)
💡 IN مع مجموعة صريحة
SELECT DISTINCT Essn
FROM WORKS_ON
WHERE Pno IN (1, 2, 3);
📌 EXISTS
EXISTS يُرجع TRUE إذا كان الاستعلام الداخلي يُرجع صفًا واحدًا على الأقل.
NOT EXISTS يُرجع TRUE إذا كان الاستعلام الداخلي لا يُرجع أي صفوف.
💡 EXISTS
SELECT E.Fname, E.Lname
FROM EMPLOYEE E
WHERE EXISTS (SELECT *
FROM DEPENDENT D
WHERE E.Ssn = D.Essn
AND E.Sex = D.Sex
AND E.Fname = D.Dependent_name);
💡 NOT EXISTS
SELECT Fname, Lname
FROM EMPLOYEE
WHERE NOT EXISTS (SELECT *
FROM DEPENDENT
WHERE Ssn = Essn);
📌 UNIQUE
UNIQUE يُرجع TRUE إذا لم يكن هناك صفوف مكررة في نتيجة الاستعلام الداخلي. (نادر الاستخدام).
🎯 متى نستخدم EXISTS؟
- لاختبار وجود علاقة بين الجداول.
- أداؤه أفضل من
IN في بعض قواعد البيانات.
- مع الاستعلامات المرتبطة، هو الخيار المنطقي.
📌 صيغة JOIN الصريحة
SQL تقدم صيغة JOIN في جملة FROM بدلاً من كتابة الشروط في WHERE.
1. INNER JOIN
INNER JOIN = JOIN الافتراضي. يُرجع الصفوف المتطابقة في كلا الجدولين فقط.
SELECT name, First_name, Last_name
FROM Course JOIN Faculty
ON Course.Lecturer_id = Faculty.id;
2. LEFT OUTER JOIN
LEFT OUTER JOIN (أو LEFT JOIN) يُرجع كل الصفوف من الجدول الأيسر، مع بيانات الجدول الأيمن إن وُجدت، أو NULL إن لم توجد.
SELECT name, First_name, Last_name
FROM Course LEFT OUTER JOIN Faculty
ON Course.Lecturer_id = Faculty.id;
3. RIGHT OUTER JOIN
RIGHT OUTER JOIN يُرجع كل الصفوف من الجدول الأيمن.
SELECT name, First_name, Last_name
FROM Course RIGHT OUTER JOIN Faculty
ON Course.Lecturer_id = Faculty.id;
4. FULL OUTER JOIN
FULL OUTER JOIN يُرجع كل الصفوف من كلا الجدولين، مع NULL في الجانب الآخر إن لم يوجد تطابق.
SELECT name, First_name, Last_name
FROM Course FULL OUTER JOIN Faculty
ON Course.Lecturer_id = Faculty.id;
5. NATURAL JOIN
NATURAL JOIN يربط الجداول بناءً على الأعمدة التي تحمل نفس الاسم تلقائيًا. كل عمود مشترك يظهر مرة واحدة فقط في النتيجة.
SELECT Fname, Lname, Address
FROM (EMPLOYEE NATURAL JOIN
(DEPARTMENT AS DEPT (Dname, Dno, Mssn, Msdate)))
WHERE Dname = 'Research';
6. CROSS JOIN
⚠️ الجداء الديكارتي
CROSS JOIN يُرجع كل التركيبات الممكنة من الصفوف من كلا الجدولين. استخدمه بحذر شديد لأنه قد يُنتج كميات هائلة من البيانات.
SELECT *
FROM Table1 CROSS JOIN Table2;
ربط أكثر من جدولين
💡 مثال ربط 3 جداول
SELECT Pnumber, Dnum, Lname, Address, Bdate
FROM ((PROJECT JOIN DEPARTMENT ON Dnum = Dnumber)
JOIN EMPLOYEE ON Mgr_ssn = Ssn)
WHERE Plocation = 'Stafford';
📌 GROUP BY
يقسم الصفوف إلى مجموعات بناءً على قيم عمود أو أكثر، ثم يطبق دوال التجميع على كل مجموعة.
⚠️ قاعدة مهمة
في SELECT، يمكننا فقط اختيار الأعمدة الموجودة في GROUP BY أو دوال التجميع.
💡 تجميع حسب قسم
SELECT Dno, COUNT(*), AVG(Salary)
FROM EMPLOYEE
GROUP BY Dno;
SELECT major, standing, COUNT(*), AVG(age)
FROM Student
GROUP BY major, standing;
💡 GROUP BY مع JOIN
SELECT Pnumber, Pname, COUNT(*)
FROM PROJECT, WORKS_ON
WHERE Pnumber = Pno
GROUP BY Pnumber, Pname;
HAVING: فلترة المجموعات
WHERE يُطبق قبل التجميع، ويفلتر الصفوف.
HAVING يُطبق بعد التجميع، ويفلتر المجموعات (باستخدام دوال التجميع).
💡 مثال HAVING
SELECT Pnumber, Pname, COUNT(*)
FROM PROJECT, WORKS_ON
WHERE Pnumber = Pno
GROUP BY Pnumber, Pname
HAVING COUNT(*) > 2;
📌 تعريف
طريقة العرض (View) هي جدول افتراضي يمثل نتيجة استعلام مخزّن. لا تحتوي على بيانات حقيقية (في الغالب) بل تُنشئ البيانات عند الاستعلام.
🎯 فوائد الـ Views
- تبسيط الاستعلامات: إخفاء التعقيد عن المستخدمين.
- الأمان: عرض جزء من البيانات فقط، وإخفاء الأعمدة الحساسة (مثل الراتب).
- اتساق البيانات: توفير واجهة موحدة للبيانات.
إنشاء واستخدام View
💡 View بسيط
CREATE VIEW EmployeePublic AS
SELECT Ssn, Fname, Lname, Address, Sex
FROM EMPLOYEE;
SELECT * FROM EmployeePublic;
💡 View مع JOIN
CREATE VIEW DeptInfo AS
SELECT Dname, COUNT(*) AS EmpCount, AVG(Salary) AS AvgSalary
FROM DEPARTMENT, EMPLOYEE
WHERE Dnumber = Dno
GROUP BY Dname;
الـ Views المادية وغير المادية
| الخاصية |
غير مادية (Virtual) |
مادية (Materialized) |
| التخزين |
لا تخزن بيانات، فقط الاستعلام. |
تخزن البيانات فعليًا على القرص. |
| السرعة |
أبطأ (يُنفذ الاستعلام كل مرة). |
سريع جدًا (بيانات جاهزة). |
| حداثة البيانات |
دائمًا محدثة. |
تحتاج تحديثًا دوريًا. |
| الاستخدام |
الـ Views العادية في SQL. |
تُستخدم في مستودعات البيانات (Data Warehouses). |
⚠️ تحديث Views
ليس كل View قابل للتحديث (INSERT/UPDATE/DELETE). الشروط عادة:
- يجب أن يكون مأخوذًا من جدول واحد.
- يجب أن يحتوي على المفتاح الرئيسي للجدول.
- يجب ألا يحتوي على دوال تجميع أو DISTINCT أو GROUP BY.
DROP: الحذف النهائي
⚠️ DROP نهائي ولا يمكن التراجع عنه
يُستخدم لحذف كائنات قاعدة البيانات بشكل كامل.
DROP TABLE Student;
DROP DATABASE UniversityDB;
DROP VIEW EmployeePublic;
ALTER: تعديل الهيكل
📌 ALTER TABLE
يُستخدم لإضافة أو تعديل أو حذف أعمدة أو قيود في جدول موجود.
ALTER TABLE Student
ADD phoneNumber VARCHAR(15);
ALTER TABLE Student
MODIFY COLUMN phoneNumber VARCHAR(20);
ALTER TABLE Student
DROP COLUMN phoneNumber;
ALTER TABLE Student
ADD CONSTRAINT fk_department
FOREIGN KEY (dept_id) REFERENCES Department(id);
📌 ما هي JDBC؟
JDBC (Java Database Connectivity) هي واجهة برمجة تطبيقات (API) تسمح لتطبيقات Java بالاتصال بقواعد البيانات وتنفيذ استعلامات SQL.
💡 مثال JDBC
import java.sql.*;
public class DBExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/myDB";
String user = "root";
String password = "pass";
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "SELECT id, name FROM students";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id + ": " + name);
}
rs.close(); stmt.close(); conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
🎯 خطوات JDBC الأساسية
- تحميل الـ Driver المناسب.
- فتح اتصال (Connection).
- إنشاء كائن Statement.
- تنفيذ الاستعلام (executeQuery أو executeUpdate).
- معالجة ResultSet (إذا كان استعلام SELECT).
- إغلاق الاتصال والموارد.