Вероятно, самым быстрым способом для этого является использование тщательно сконструированного триггера оператора вместо триггера строки. Триггеры строки имеют в них фразу FOR EACH ROW
, вызывается для каждой строки, которая модифицирована (на основе ограничений BEFORE/AFTER INSERT
, BEFORE/AFTER UPDATE
и BEFORE/AFTER DELETE
на триггере), можно увидеть соответствующие: NEW и: OLD значения и подчиняются «не могут смотреть на таблицу, на которой определяется триггер». Триггеры выписки вызываются в соответствующее время для каждого выполняемого оператора , не могут видеть значения строк, но не подпадают под ограничения при просмотре конкретной таблицы, на которой они определены. Итак, для частей вашей логики, которые не нужно работать с: NEW или: OLD значения, такой триггер, такой как это может оказаться полезным:
CREATE OR REPLACE TRIGGER EMPLOYEE_S_BU
BEFORE UPDATE ON EMPLOYEE
-- Note: no BEFORE EACH ROW phrase, so this is a statement trigger
BEGIN
-- The following FOR loop should insert rows into BLOCKED_MANAGER for all
-- supervisors which have four or more employees under them and who are not
-- already in BLOCKED_MANAGER.
FOR aRow IN (SELECT e.SUPERSSN, COUNT(e.SUPERSSN) AS EMP_COUNT
FROM EMPLOYEE e
LEFT OUTER JOIN BLOCKED_MANAGER b
ON b.SSN = e.SUPERSSN
WHERE b.SSN IS NULL
GROUP BY e.SUPERSSN
HAVING COUNT(e.SUPERSSN) >= 4)
LOOP
INSERT INTO BLOCKED_MANAGER
(SSN, EMPLOYEE_COUNT)
VALUES
(aRow.SUPERSSN, aRow.EMP_COUNT);
END LOOP;
-- Remove rows from BLOCKED_MANAGER for managers who supervise fewer
-- than four employees.
FOR aRow IN (SELECT e.SUPERSSN, COUNT(e.SUPERSSN) AS EMP_COUNT
FROM EMPLOYEE e
INNER JOIN BLOCKED_MANAGER b
ON b.SSN = e.SUPERSSN
GROUP BY e.SUPERSSN
HAVING COUNT(e.SUPERSSN) <= 3)
LOOP
DELETE FROM BLOCKED_MANAGER
WHERE SSN = aRow.SUPERSSN;
END LOOP;
-- Finally, if any supervisor has five or more employees under them,
-- raise an exception. Note that we go directly to EMPLOYEE to determine
-- the number of employees supervised.
FOR aRow IN (SELECT SUPERSSN, COUNT(*) AS EMP_COUNT
FROM EMPLOYEE
GROUP BY SUPERSSN
HAVING COUNT(*) >= 5)
LOOP
-- If we get here we've found a supervisor with 5 (or more) employees.
-- Raise an exception
RAISE_APPLICATION_ERROR(-20000, 'Found supervisor ' || aRow.SUPERSSN ||
' supervising ' || aRow.EMP_COUNT ||
' employees');
END LOOP;
END EMPLOYEE_S_BU;
Обратите внимание, что если вы избавитесь от таблицы BLOCKED_MANAGER (который этот триггер все еще поддерживает, хотя я не знаю, действительно ли это необходимо), логика значительно сокращается.
Вам все равно потребуется триггер строки для обработки журнала, но поскольку это всего лишь вопрос о сокращении существующего триггера я оставлю это вам. : -)
Поделитесь и наслаждайтесь.