الاستعلامات الفرعية والإجراءات في SQL
يا هلا بالجميع! اليوم راح نتكلم عن أدوات قوية جداً في SQL: الاستعلامات الفرعية (Subqueries) والإجراءات المخزنة (Stored Procedures). هذي الأدوات بتخلي شغلك أنظف، أسرع، وأكثر احترافية. يلا نبدأ!
1. الاستعلامات الفرعية (Subqueries)
ببساطة، الاستعلام الفرعي هو استعلام SQL داخل استعلام SQL آخر. كأنك تسأل سؤال عشان تقدر تجاوب على سؤال أكبر. الاستعلام الداخلي يتنفذ أولاً، ونتيجته تستخدمها في الاستعلام الخارجي.
ملاحظة سريعة: الاستعلامات الفرعية تقدر تستخدمها في جمل
SELECT,FROM,WHERE,HAVING. الأكثر شيوعاً هو استخدامها في جملةWHERE.
أمثلة على الاستعلامات الفرعية:
أ. في جملة WHERE (الأكثر استخداماً)
هنا نبغى نطلع كل الموظفين اللي راتبهم أعلى من متوسط رواتب كل الموظفين.
SELECT EmployeeName, Salary
FROM Employees
WHERE Salary > (SELECT AVG(Salary) FROM Employees);
شوف كيف (SELECT AVG(Salary) FROM Employees) هذا هو الاستعلام الفرعي. جاب متوسط الرواتب أول، وبعدين الاستعلام الخارجي استخدم هذي القيمة.
ب. مع عامل IN
نبي نطلع أسماء المنتجات اللي تم طلبها من قبل عملاء من مدينة "الرياض".
SELECT ProductName
FROM Products
WHERE ProductID IN (
SELECT ProductID
FROM OrderDetails
WHERE OrderID IN (
SELECT OrderID
FROM Orders
WHERE CustomerID IN (
SELECT CustomerID
FROM Customers
WHERE City = 'الرياض'
)
)
);
هنا عندنا استعلامات فرعية متداخلة (Nested Subqueries).
ج. في جملة FROM (الجدول المشتق - Derived Table)
هنا الاستعلام الفرعي يعتبر كأنه جدول مؤقت تقدر تسوي عليه استعلام ثاني. مثلاً، نبي نطلع أعلى راتب في كل قسم.
SELECT d.DepartmentName, MaxSalaryPerDepartment.MaxSalary
FROM Departments d
JOIN (
SELECT DepartmentID, MAX(Salary) AS MaxSalary
FROM Employees
GROUP BY DepartmentID
) AS MaxSalaryPerDepartment
ON d.DepartmentID = MaxSalaryPerDepartment.DepartmentID;
الجدول MaxSalaryPerDepartment هو ناتج الاستعلام الفرعي.
د. في جملة SELECT (استعلام فرعي Scalar)
هنا الاستعلام الفرعي لازم يرجع قيمة واحدة فقط (عمود واحد وصف واحد). نبي نطلع اسم الموظف وراتبه، ومعاه متوسط رواتب كل الموظفين في نفس الصف.
SELECT
EmployeeName,
Salary,
(SELECT AVG(Salary) FROM Employees) AS AverageOverallSalary
FROM Employees;
2. الإجراءات المخزنة (Stored Procedures)
الإجراء المخزن هو مجموعة من أوامر SQL المترجمة والمخزنة في قاعدة البيانات. تخيل إنك عندك مهمة تسويها كثير (مثلاً، إضافة عميل جديد مع كل بياناته). بدل ما تكتب الأوامر كل مرة، تسويها مرة وحدة كإجراء وتستدعيه وقت ما تبغى.
ليه نستخدمها؟
- الأداء: تتنفذ أسرع لأنها مترجمة مسبقاً.
- إعادة الاستخدام: تكتب الكود مرة وحدة وتستدعيه عدة مرات.
- الأمان: تقدر تعطي صلاحية تنفيذ الإجراء بدون ما تعطي صلاحية مباشرة على الجداول.
- البرمجة المعيارية (Modularity): تقسيم المهام الكبيرة لمهام أصغر وأسهل للإدارة.
أمثلة على الإجراءات المخزنة:
أ. إنشاء إجراء بسيط بدون بارامترات
هذا الإجراء بيجيب كل الموظفين.
CREATE PROCEDURE GetAllEmployees
AS
BEGIN
SELECT EmployeeID, EmployeeName, Salary, DepartmentID
FROM Employees;
END;
ولتنفيذه، فقط تكتب:
EXEC GetAllEmployees;
-- أو
EXECUTE GetAllEmployees;
ب. إنشاء إجراء ببارامترات (Parameters)
هذا الإجراء بيجيب الموظفين حسب القسم.
CREATE PROCEDURE GetEmployeesByDepartment
@DepartmentID INT
AS
BEGIN
SELECT EmployeeID, EmployeeName, Salary
FROM Employees
WHERE DepartmentID = @DepartmentID;
END;
لتنفيذه (مثلاً، قسم رقم 3):
EXEC GetEmployeesByDepartment @DepartmentID = 3;
ج. تعديل إجراء
لو احتجت تعدل على إجراء موجود (مثلاً، تضيف عمود جديد في الـ SELECT).
ALTER PROCEDURE GetAllEmployees
AS
BEGIN
SELECT EmployeeID, EmployeeName, Salary, DepartmentID, HireDate
FROM Employees;
END;
د. حذف إجراء
لإزالة إجراء لم تعد بحاجة إليه.
DROP PROCEDURE GetAllEmployees;
خاتمة
الاستعلامات الفرعية والإجراءات المخزنة أدوات أساسية لأي مطور قواعد بيانات. تعلم استخدامها بفعالية بيطور من مهاراتك بشكل كبير وبيخلي كودك أفضل وأكثر كفاءة. تدرب عليها كثير وراح تشوف الفرق! بالتوفيق!