требования являетсяоракул Перед триггером на операции DML на одной таблице
- IF УДАЛЕНИЯ, любая запись создана в USER_INFO таблице не может быть удалена. Попытка удалить запись из этой таблицы будет захвачена, создайте запись в таблице AUDIT.
IF вставляя, обязательные поля ID, LOGIN_USER
• Перед установкой в таблицу, проверить есть не существующая запись с тем же LOGIN_USER и статус записи в True.
• Если это подтверждение не выполнено, введите код ошибки и сообщение об ошибке.
• Когда запись вставлена в таблицу, триггер после события будет срабатывать обновления следующих полей: ID с последовательностью, созданием текущей даты/время и действия «создание записи»
ЕСЛИ ОБНОВЛЕНИЕ, Обязательные для заполнения поля ID, LOGIN_USER
• при обновлении записи в таблице, триггер после события будет срабатывать выполнение следующих действий:
O Вставить запись в текущих значений осуществляется таблица копирования полей.
о следующих полей заполняются или переопределен со следующими значениями: Активного Ложными События «Аудит для обслуживания данных»
• Триггера до события будет срабатывать и предотвратить неактивную запись от обновления.
• Запись со статусом Active = False не может быть обновлена. Если это так, необходимо создать новую запись.
Я написал код, и он выполняет DELETE AND INSERT без каких-либо проблем.
Проблема с UPDATE, когда она попадает в блок UPDATING, INSERTS внутри блоков else; здесь запрос INSERT рекурсивно запускается блоком INSERTING. Это не должно выполняться, когда я хотел запустить только блок UPDATING.
Пожалуйста, предложите, есть ли другие способы следовать. Это первый раз, когда я использую триггерный код.
CREATE OR REPLACE TRIGGER BEFORE_DML
BEFORE DELETE OR INSERT OR UPDATE OF ID,LOGIN_USER ON USER_INFO
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
V_USER VARCHAR2 (30);
V_NODE VARCHAR2 (50);
V_CNT NUMBER := 0;
V_ACTIVE VARCHAR2 (10);
BEGIN
SELECT SYS_CONTEXT ('USERENV', 'IP_ADDRESS')
INTO V_NODE
FROM DUAL;
IF DELETING THEN
INSERT
INTO AUDIT (IDS,
ACTION,
IP_ADDRESS,
LOGIN,
CREATED
)
VALUES(AUDIT_SEQ.NEXTVAL,
'Deletion',
V_NODE,
SYS.LOGIN_USER,
SYSDATE
);
COMMIT;
RAISE_APPLICATION_ERROR (-20002, 'USER_INFO table data can not be deleted');
END IF; --Close IF for DELETING
IF INSERTING THEN
SELECT COUNT (1)
INTO V_CNT
FROM USER_INFO
WHERE LOGIN_USER = :NEW.LOGIN_USER
AND STATUS='TRUE';
IF (V_CNT >=1) THEN
RAISE_APPLICATION_ERROR (-20002, 'DATABASE LOGIN USER ALREADY EXISTS', TRUE);
END IF;
:NEW.ID := DBLOGIN_SEQ.NEXTVAL;
:NEW.CREATED := SYSDATE;
:NEW.ACTION := 'Record Creation' ;
END IF; --CLOSE IF FOR INSERTING
IF UPDATING THEN
IF :OLD.STATUS = 'INACTIVE'
THEN
RAISE_APPLICATION_ERROR (-20002, 'INACTIVE RECORDS CAN NOT BE UPDATED');
ELSE IF :OLD.STATUS = 'FALSE' THEN
INSERT INTO USER_INFO(ID,
STATUS,
LOGIN_USER,
CREATED,
ACTION
)
VALUES(DBLOGIN_SEQ.NEXTVAL,
'INVALID',
:OLD.LOGIN_USER,
SYSDATE,
'FALSE RECORD UPDATED '
);
COMMIT;
ELSE
INSERT INTO USER_INFO(ID,
STATUS,
LOGIN_USER,
CREATED,
ACTION
)
VALUES(DBLOGIN_SEQ.NEXTVAL,
'FALSE',
:OLD.LOGIN_USER, --NEW.LOGIN_USER
SYSDATE,
'Audit for data maintenance'
);
COMMIT;
END IF;
END IF;
END IF; --CLOSE IF FOR UPDATING
END BEFORE_DML;
/
Это домашнее задание или вы пытаетесь решить проблему реального мира? Вы могли бы сделать что-то взломанное, если у вас есть пакет с общедоступной глобальной переменной 'in_before_dml_trigger', которую вы установили в своем блоке' update' и проверите в верхней части вашего триггера. Это решило бы ближайшую проблему, но это была королевская боль с точки зрения обслуживания и поддержки. Вы делаете что-то в триггере, который будет работать только в однопользовательской системе - уникальный индекс фактически обеспечит наличие только одной строки для 'login_user' в многопользовательской системе. –
Спасибо. Этот подход правильный? – Hima