Создать триггер для вставки в другую таблицу
У меня есть некоторые проблемы с выполнением триггера ниже:
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varReadNo Int;
varMeterID Int;
varCustID Varchar(10);
BEGIN
SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;
Select MeterID INTO varMeterID
From Reading
Where ReadNo = varReadNo;
Select CustID INTO varCustID
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = varMeterID;
INSERT INTO BILL VALUES
(SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL);
END;
Сообщение об ошибке:
* Причина: триггер (или определенная пользователем функция plsql, на которую ссылается этот оператор) попытался просмотреть (или изменить) таблицу, которая была в середине процесса изменения оператором, который ее вызвал.
* Действие: переписать триггер (или функцию), чтобы он не читал эту таблицу.
Значит ли это, что я не собираюсь извлекать какие-либо подробности из таблицы Reading?
Я считаю, что проблема возникает, когда я получаю данные из чтения таблицы, когда он вставляет значение:
SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;
Select MeterID INTO varMeterID
From Reading
Where ReadNo = varReadNo;
Это в любом случае, чтобы решить это? Или есть лучший способ сделать это? Мне нужно вставить новую строку в таблицу BILL после входа в чтение таблицы, где ReadNo нужно ссылаться на ReadNo, который я просто вставляю.
4 ответа
Вы не можете получить записи из той же таблицы в триггере строки. Вы можете получить доступ к значениям из фактической записи, используя:new и:old (это ваш случай?). Затем триггер можно переписать в
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
Select CustID INTO varCustID
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = :new.MeterID;
INSERT INTO BILL VALUES
(SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL);
END;
Если вам нужно запросить другую запись из таблицы READING, вы должны использовать комбинацию триггеров операторов, триггеров строк и коллекции PLSQL. Хороший пример этого на AskTom.oracle.com
Мы можем объединить вставить и выбрать заявление
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
insert into bill
values
select SEQBILLNO.NEXTVAL,
SYSDATE,
'UNPAID' ,
100 ,
CustID,SEQREADNO.CURRVAL
From Address A
Join Meter M
on A.postCode = M.postCode
Where M.MeterID = :new.MeterID;
END;
попробуйте приведенный выше код.
Добавьте обработку исключений в свой триггер и посмотрите, что происходит, так как вам будет легко отслеживать исключения.
CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW
DECLARE
varCustID Varchar(10);
BEGIN
-- your code
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20299)));
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20298)));
END;
Убедитесь, что у вас есть необходимые разрешения на все таблицы и доступ к последовательностям, которые вы используете во вставке.
Я не делал Oracle некоторое время, но вы также можете попробовать запросить dba_errors (или all_errors), чтобы попытаться получить больше информации о том, почему ваш SP не компилируется.
Что-то под мелодию:
SELECT * FROM dba_errors WHERE owner = 'THEOWNER_OF_YOUR_SP';