معالجة الأخطاء والتعديل على قواعد البيانات في SQL


أهلاً بك! اليوم راح نتكلم عن شيئين أساسيين في شغلنا مع SQL: كيف نتعامل مع الأخطاء اللي ممكن تصير، وكيف نعدل على البيانات وهيكل قاعدة البيانات نفسها. يلا بينا!

1. معالجة الأخطاء (Error Handling)

يا صاحبي، الأخطاء جزء طبيعي من أي شغل برمجي. في SQL، لازم تكون مستعد لها عشان تطبيقك ما يخرب وبياناتك ما تتلخبط. الهدف هو إنك تمسك الخطأ، تتعامل معاه، وتضمن إن قاعدة البيانات ترجع لحالة صحيحة لو صار شي غلط.

كتل TRY...CATCH (في SQL Server مثلاً)

هذي زي الدرع الواقي. أي كود ممكن يسوي مشكلة تحطه جوا TRY، ولو صار خطأ، الكود اللي جوا CATCH بيشتغل.

BEGIN TRY
    -- هنا تحط الكود اللي ممكن يسوي مشكلة
    INSERT INTO Products (ProductID, ProductName, Price) VALUES (1, 'Test', 'NotANumber'); -- هذا بيسوي خطأ لأن Price نص
END TRY
BEGIN CATCH
    -- هنا تتعامل مع الخطأ
    SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;

ملاحظة: الدوال زي ERROR_NUMBER() و ERROR_MESSAGE() تعطيك تفاصيل الخطأ. مفيدة جداً للتتبع!

التعامل مع العمليات (Transactions)

الـ TRANSACTION هي مجموعة عمليات SQL تتنفذ كوحدة واحدة. يا كلها تنجح (ونقول COMMIT)، يا كلها تفشل وتتراجع (ونقول ROLLBACK). هذا أهم شي في معالجة الأخطاء عشان بياناتك ما تتخربط.

BEGIN TRANSACTION;
BEGIN TRY
    -- عملية أولى
    INSERT INTO Orders (OrderID, CustomerID, OrderDate) VALUES (101, 5, GETDATE());

    -- عملية ثانية ممكن تفشل
    UPDATE Products SET StockQuantity = StockQuantity - 1 WHERE ProductID = 99999; -- لو المنتج مش موجود، ممكن ما يأثر أو يسوي خطأ حسب الإعداد

    -- لو وصلنا لهنا، يعني كل شي تمام
    COMMIT TRANSACTION;
    SELECT 'Transaction committed successfully.';
END TRY
BEGIN CATCH
    -- لو صار أي خطأ، تراجع عن كل شي
    ROLLBACK TRANSACTION;
    SELECT 'Transaction rolled back due to error: ' + ERROR_MESSAGE();
END CATCH;

تذكر: دايماً استخدم BEGIN TRANSACTION مع COMMIT و ROLLBACK لما يكون عندك أكثر من عملية تعتمد على بعضها.

رمي الأخطاء (RAISERROR / THROW)

أحياناً تحتاج أنت بنفسك ترمي خطأ مخصص، مثلاً لو شرط معين ما تحقق. في SQL Server عندك RAISERROR أو THROW (الأحدث والأفضل).

-- استخدام THROW
IF NOT EXISTS (SELECT 1 FROM Customers WHERE CustomerID = @CustomerID)
BEGIN
    THROW 50001, 'العميل غير موجود في قاعدة البيانات.', 1;
END;

2. التعديل على قواعد البيانات (Database Modification)

هنا نجي للشغل اليومي: كيف نضيف، نعدل، ونحذف بيانات، وحتى نغير هيكل قاعدة البيانات.

إضافة بيانات (INSERT)

هذا أمر عشان تدخل صفوف جديدة في جدول. تقدر تحدد الأعمدة أو تخلي SQL يحط القيم الافتراضية.

-- تحديد الأعمدة والقيم
INSERT INTO Employees (EmployeeID, FirstName, LastName, DepartmentID)
VALUES (1, 'أحمد', 'محمد', 101);

-- لو بتدخل كل الأعمدة بنفس الترتيب
INSERT INTO Employees VALUES (2, 'فاطمة', 'علي', 102);

-- إضافة بيانات من استعلام آخر
INSERT INTO ArchiveEmployees SELECT * FROM Employees WHERE HireDate < '2020-01-01';

تحديث بيانات (UPDATE)

لتغيير قيم في صفوف موجودة. الأهم هنا هو جملة WHERE عشان ما تحدث كل الجدول بالغلط!

-- تحديث راتب موظف معين
UPDATE Employees
SET Salary = 60000, DepartmentID = 103
WHERE EmployeeID = 1;

-- تحديث رواتب كل الموظفين في قسم معين
UPDATE Employees
SET Salary = Salary * 1.10
WHERE DepartmentID = 101;

تحذير: دايماً تأكد إنك حاط WHERE مع UPDATE و DELETE، وإلا ممكن تحذف أو تعدل بيانات ما كنت ناوي عليها!

حذف بيانات (DELETE)

لإزالة صفوف من جدول. وبرضو، WHERE هو صديقك المفضل هنا.

-- حذف موظف معين
DELETE FROM Employees
WHERE EmployeeID = 2;

-- حذف كل الموظفين في قسم معين
DELETE FROM Employees
WHERE DepartmentID = 102;

مسح الجدول بالكامل (TRUNCATE TABLE)

هذا الأمر أسرع من DELETE لما تبغى تمسح كل البيانات من جدول، بس ما يرجع لك عدد الصفوف اللي انمسحت وما تقدر تسوي له ROLLBACK (غالباً، حسب نوع قاعدة البيانات).

TRUNCATE TABLE TempLog;

الفرق بين DELETE و TRUNCATE: DELETE يحذف صف صف وتقدر ترجع عنه بـ ROLLBACK، ويسجل كل عملية حذف. TRUNCATE يمسح كل البيانات بسرعة كأنه يفرغ الجدول، ولا يمكن التراجع عنه بسهولة، وأقل استهلاكاً للموارد.

تعديل هيكل الجدول (ALTER TABLE)

هذا عشان تغير تصميم الجدول نفسه: تضيف عمود، تحذف عمود، تغير نوع بيانات عمود، إلخ.

-- إضافة عمود جديد
ALTER TABLE Employees
ADD Email VARCHAR(100);

-- حذف عمود
ALTER TABLE Employees
DROP COLUMN Email;

-- تعديل نوع بيانات عمود (في SQL Server)
ALTER TABLE Employees
ALTER COLUMN Salary DECIMAL(10, 2);

-- إضافة قيد (Constraint)
ALTER TABLE Products
ADD CONSTRAINT CK_ProductPrice CHECK (Price > 0);

التعامل مع الكائنات الأخرى (Views, Indexes, Procedures, Functions)

مو بس الجداول اللي تتعدل، أي كائن في قاعدة البيانات تقدر تعدل عليه أو تحذفه.

-- إنشاء/تعديل/حذف View
CREATE VIEW ActiveEmployees AS SELECT EmployeeID, FirstName FROM Employees WHERE Status = 'Active';
ALTER VIEW ActiveEmployees AS SELECT EmployeeID, FirstName, LastName FROM Employees WHERE Status = 'Active';
DROP VIEW ActiveEmployees;

-- إنشاء/حذف Index
CREATE INDEX IX_EmployeeLastName ON Employees (LastName);
DROP INDEX IX_EmployeeLastName ON Employees; -- في بعض قواعد البيانات، تحتاج تحدد اسم الجدول: DROP INDEX Employees.IX_EmployeeLastName;

-- إنشاء/تعديل/حذف Stored Procedure
CREATE PROCEDURE GetEmployeeByID @ID INT AS SELECT * FROM Employees WHERE EmployeeID = @ID;
ALTER PROCEDURE GetEmployeeByID @ID INT AS SELECT EmployeeID, FirstName, LastName FROM Employees WHERE EmployeeID = @ID;
DROP PROCEDURE GetEmployeeByID;

-- إنشاء/تعديل/حذف Function
CREATE FUNCTION GetTotalSalary () RETURNS DECIMAL(18,2) AS BEGIN RETURN (SELECT SUM(Salary) FROM Employees); END;
ALTER FUNCTION GetTotalSalary () RETURNS DECIMAL(18,2) AS BEGIN RETURN (SELECT SUM(Salary) + 1000 FROM Employees); END;
DROP FUNCTION GetTotalSalary;

أفضل الممارسات (Best Practices)

  • استخدم الـ TRANSACTION دائماً: خاصة لما تكون بتسوي أكثر من عملية تعديل على البيانات.
  • التحقق من المدخلات: قبل ما تدخل أي بيانات، تأكد إنها صحيحة ومطابقة للشروط.
  • النسخ الاحتياطي (Backup): قبل أي تعديلات كبيرة على هيكل قاعدة البيانات، خذ نسخة احتياطية.
  • الاختبار (Test): جرب أوامرك على بيئة تطوير أو اختبار قبل ما تطبقها على قاعدة بيانات الإنتاج.
  • استخدم WHERE بحذر: دايماً دقق في جملة WHERE مع UPDATE و DELETE.
  • التعامل مع الأخطاء بصمت: لا تخلي الأخطاء تطلع لليوزر مباشرة، امسكها وسجلها وتعامل معاها بشكل لطيف.

أتمنى إن هذا الدرس كان مفيداً لك. مع الممارسة، بتصير محترف في التعامل مع الأخطاء والتعديل على قواعد البيانات.