Защита данных
Если ограничения, ранее заданные как DEFERRED, явно не задаются вами как IMMEDIATE, то, когда вы попытаетесь завершить свою транзакцию с помощью оператора COMMIT, SQL активизирует все задержанные ограничения. Если к этому моменту не все ограничения выполняются, транзакция будет отменена и SQL выдаст сообщение об ошибке.
Ограничения в SQL защищают от ввода неправильных данных (или, что так же важно, от недопустимого отсутствия данных), причем у вас есть возможность на время действия транзакции временно отменить имеющиеся ограничения.
Чтобы увидеть, насколько важна отсрочка применения ограничений, проанализируйте пример с платежными ведомостями.
Предположим, что в таблице EMPLOYEE (сотрудник) имеются столбцы EmpNo (номер сотрудника), EmpName (фамилия сотрудника), DeptNo (номер отдела) и Salary (оклад). DeptNo является внешним ключом, который ссылается на таблицу DEPT (отдел). Предположим также, что в таблице DEPT имеются столбцы DeptNo и DeptName (название отдела), причем DeptNo – это первичный ключ.
Представим, что, кроме этого, вы хотите иметь такую же таблицу, как и DEPT, но в которой еще есть столбец Payroll (платежная ведомость), и в нем для каждого отдела имеется сумма значений Salary сотрудников этого отдела.
Эквивалент этой таблицы можно создать с помощью следующего представления:
CREATE VIEW DEPT2 AS SELECT D.*, SUM(E.Salary) AS Payroll FROM DEPT D, EMPLOYEE E WHERE D.DeptNo = E.DeptNo GROUP BY D.DeptNo;
Точно такое же представление можно определить еще и другим способом:
CREATE VIEW DEPT3 AS SELECT D.*, (SELECT SUM(E.Salary) FROM EMPLOYEE E WHERE D.DeptNo = E.DeptNo) AS Payroll FROM DEPT D;
Но предположим, что для большей эффективности вы не собираетесь вычислять значение SUM каждый раз, когда ссылаетесь на столбец DEPT.Payroll. Вместо этого вы хотите, чтобы в таблице DEPT в действительности находился столбец Payroll. Значения в этом столбце вы будете обновлять каждый раз, когда будете вносить изменения в столбце Salary.
И, чтобы обеспечить правильность значений в столбце Salary, в определение таблицы можно вставить ограничение:
CREATE TABLE DEPT (DeptNo CHAR(5), DeptName CHAR(20), Payroll DECIMAL(15.2), CHECK (Payroll = (SELECT SUM(Salary) FROM EMPLOYEE E WHERE E.DeptNo = DEPT.DeptNo)));
Теперь предположим, что вам надо увеличить на 100 значение Salary сотрудника под номером 123. Это можно сделать с помощью следующего обновления:
UPDATE EMPLOYEE SET Salary = Salary + 100 WHERE EmpNo = '123';
Кроме того, следует обновить таблицу DEPT:
UPDATE DEPT D SET Payroll = Payroll + 100 WHERE D.DeptNo = (SELECT E.DeptNo FROM EMPLOYEE E WHERE E.EmpNo 423');
(Подзапрос используется для того, чтобы получить ссылку на значение DeptNo сотрудника с идентификационным номером 123.)
Но здесь имеется трудность: после каждого оператора ограничения проверяются. Теоретически должны проверяться все ограничения. Но на практике реализациями проверяются только те из них, которые относятся к значениям, измененным в ходе работы оператора.