Моя домашняя работа требует, чтобы я создал единственный триггер, который при определенных обстоятельствах обновляет значение И вызывает ошибку. Я использую базу данных Oracle, к которой я обращаюсь через команду sqlplus на терминале.
- Я не могу использовать «: NEW.attributeName: = value», потому что появление ошибки препятствует обновлению.
- Я не могу использовать оператор обновления внутри триггера, потому что он вызовет ошибку изменяющейся таблицы.
- Согласно постановке проблемы, я должен уметь решить эту проблему с помощью одного триггера, и формулировка проблемы довольно расплывчата, но я думаю, что мне также не разрешено использовать процедуру.
- Мы не видели временных столов в классе, поэтому их нельзя использовать для выполнения домашних заданий. Однако мы видели взгляды.
CREATE OR REPLACE TRIGGER triggerName
INSTEAD OF UPDATE OF attributeName ON TableName
FOR EACH ROW
BEGIN
IF (:NEW.attributeName < 0) THEN
UPDATE TableName
SET attributeName = 0
WHERE attr0 = :NEW.attr0 AND
attr1 = :NEW.attr1
;
raise_application_error(-20101, 'You cannot update attributeName to a negative value.');
END;
/
Я попытался использовать представление, как описано в следующем примере (https://sgbd.developpez.com/oracle/ora-04091/#LI). Это на французском; он просто говорит, что создание представления должно позволить вам использовать триггер INSTEAD OF, но я сделал именно это, и теперь триггер больше не запускается, когда я обновляю таблицу.
CREATE TABLE CLIENT(
IDC INTEGER PRIMARY KEY ,
NOM VARCHAR2 (40));
CREATE TABLE VOYAGE(
IDV INTEGER PRIMARY KEY ,
DESTINATION VARCHAR2 (40),
MAXPLACE INTEGER ) -- nombre total de places
;
CREATE TABLE INSCRIPTION(
IDC INTEGER REFERENCES CLIENT(IDC),
IDV INTEGER REFERENCES VOYAGE(IDV),
DATERESERV DATE ,
CONSTRAINT INSCRIPTION_PK PRIMARY KEY (IDC, IDV));
INSERT INTO CLIENT(IDC, NOM) VALUES (1, 'DURAND');
INSERT INTO CLIENT(IDC, NOM) VALUES (2, 'DUBOIS');
INSERT INTO CLIENT(IDC, NOM) VALUES (3, 'DUGENOU');
COMMIT ;
INSERT INTO VOYAGE(IDV, DESTINATION, MAXPLACE) VALUES (10, 'VENISE', 25);
INSERT INTO VOYAGE(IDV, DESTINATION, MAXPLACE) VALUES (11, 'PRAGUE', 20);
COMMIT ;
-- Création d'une vue sur la table INSCRIPTION pour le support des déclencheurs INSTEAD OF
CREATE OR REPLACE VIEW V_INSCRIPTION AS SELECT * FROM INSCRIPTION;
CREATE OR REPLACE TRIGGER TRIG_V_INSCRIPTION INSTEAD OF INSERT ON V_INSCRIPTION FOR EACH ROW
DECLARE
NB_RESERVE INTEGER ; -- nombre de réservations déjà faites
NB_MAXPLACE INTEGER ; -- nombre de places total
BEGIN
SELECT COUNT (*) INTO NB_RESERVE FROM V_INSCRIPTION
WHERE IDC=:NEW.IDC
AND IDV=:NEW.IDV;
SELECT MAXPLACE INTO NB_MAXPLACE FROM VOYAGE
WHERE IDV=:NEW.IDV;
IF NB_MAXPLACE - NB_RESERVE < 1 THEN
DBMS_OUTPUT.PUT_LINE('Désolé, voyage complet');
ELSE
-- dans un déclencheur INSTEAD OF, l'instruction DML sous-jacente ne s'exécute pas. On traite donc l'insertion manuellement
INSERT INTO INSCRIPTION(IDC, IDV, DATERESERV) VALUES (:NEW.IDC, :NEW.IDV, :NEW.DATERESERV);
END IF ;
END ;
/
-- DUGENOU aimerait bien aller à Venise :
INSERT INTO INSCRIPTION(IDC, IDV, DATERESERV) SELECT 3, 10, TO_DATE(SYSDATE, 'DD/MM/YYYY') FROM DUAL ;
1 ligne créée.
Есть ли способ обновить значение attributeName И поднять ошибку ORA-20101 без использования процедуры? В противном случае, я полагаю, мне разрешено.
instead of update
, а второй -instead of insert
. Более того, похоже, что они делают совершенно разные вещи. Что именно нужно делать? обновить или вставить? Когда должна появиться ошибка? после вставки или после обновления? - person Kaushik Nayak   schedule 28.04.2019