我有一个复合触发器,用SELECT INTO检查条件。如果满足条件,则引发异常并且不插入值。为此我使用NO_DATA_FOUND异常,当一切正常时,意味着不满足提升我的自定义异常的条件并执行INSERT。
让我感到困扰的是,当我在SELECT INTO where子句中使用常量时,我正确地获得了NO_DATA_FOUND异常。当我使用与常量具有相同值的procedure参数时,不会引发NO_DATA_FOUND异常。
以下是进行检查的触发器内的程序:
PROCEDURE validate_system(
v_abgleich_id IN ctl_webadmin_abgleich.webadmin_abgleich_id%TYPE,
v_valid_from IN ctl_webadmin_abgleich.gueltig_von%TYPE,
v_valid_through IN ctl_webadmin_abgleich.gueltig_bis%TYPE,
v_source_system IN ctl_webadmin_abgleich.cldb_quellsystem_id%TYPE,
v_target_system IN ctl_webadmin_abgleich.cldb_zielsystem_id%TYPE,
v_table_id IN ctl_webadmin_abgleich.cldb_webadmin_table_id%TYPE)
IS
overlapping_abgleich EXCEPTION;
src_target_same EXCEPTION;
from_date_null EXCEPTION;
from_date_gt EXCEPTION;
dummy CHAR(1);
v_ss NUMBER(10,0);
BEGIN
v_ss := 4;
dbms_output.put_line('v_ss' || v_ss);
IF(validate_system.v_source_system = validate_system.v_target_system) THEN
dbms_output.put_line('Raising src_target_same.');
RAISE src_target_same;
END IF;
IF(validate_system.v_valid_from IS NULL) THEN
dbms_output.put_line('Raising from_date_null.');
RAISE from_date_null;
END IF;
IF(validate_system.v_valid_from > validate_system.v_valid_through) THEN
dbms_output.put_line('Raising from_date_gt.');
RAISE from_date_gt;
END IF;
BEGIN
SELECT 'X'
INTO dummy
FROM ctl_webadmin_abgleich ab
WHERE ab.cldb_quellsystem_id = 4 AND ROWNUM = 1; -- constant raises NO_DATA_FOUND
-- WHERE ab.cldb_quellsystem_id = validate_system.v_source_system AND ROWNUM = 1; -- variable with the same value doesn't raise NO_DATA_FOUND exception.
dbms_output.put_line('Conflicting recs foound: ' || v_ss);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('NO DATA FOUND:' || validate_system.v_source_system);
NULL;
END;
EXCEPTION
WHEN src_target_same THEN
RAISE_APPLICATION_ERROR(-20001, 'Quellsystem darf nicht gleich dem Zielsystem sein!');
WHEN from_date_null THEN
RAISE_APPLICATION_ERROR(-20002, 'VON Datum darf nicht NULL sein!');
WHEN from_date_gt THEN
RAISE_APPLICATION_ERROR(-20003, 'VON Datum liegt vor Datum BIS!');
WHEN overlapping_abgleich THEN
RAISE_APPLICATION_ERROR(-20004, 'Gültigkeitsbereiche mit schon existierenden Einträgen kollidieren!');
END validate_system;
在一个空表中,如果我将一个常量传递给SELECT INTO的WHERE子句,我得到NO_DATA_FOUND。但是当我使用变量时 - > validate_system.v_source_system,不引发异常。
我做错了什么?从另一个过程调用此过程,该过程又在触发器的AFTER STATEMENT块中调用。
INSERT如下:
Insert into CTL_WEBADMIN_ABGLEICH (webadmin_abgleich_id, gueltig_von, gueltig_bis, cldb_quellsystem_id, cldb_zielsystem_id, cldb_webadmin_table_id)
values (12, to_date('20.01.20', 'DD.MM.RR'), to_date('20.05.20', 'DD.MM.RR'), 4, 6, 813);
这是整个触发器:
create or replace
trigger abgleich_quellsystem_trg FOR INSERT OR
UPDATE ON ctl_webadmin_abgleich COMPOUND TRIGGER type abgleich_type IS record ( abgleich_id ctl_webadmin_abgleich.webadmin_abgleich_id%TYPE, valid_from ctl_webadmin_abgleich.gueltig_von%TYPE, valid_through ctl_webadmin_abgleich.gueltig_bis%TYPE, source_system ctl_webadmin_abgleich.cldb_quellsystem_id%TYPE, target_system ctl_webadmin_abgleich.cldb_zielsystem_id%TYPE, table_id ctl_webadmin_abgleich.cldb_webadmin_table_id%TYPE );
type abgleich_recs_type
IS
TABLE OF abgleich_type INDEX BY pls_integer;
abgleich_rec abgleich_recs_type;
PROCEDURE lock_system(
v_abgleich_id IN ctl_webadmin_abgleich.webadmin_abgleich_id%TYPE,
v_valid_from IN ctl_webadmin_abgleich.gueltig_von%TYPE,
v_valid_through IN ctl_webadmin_abgleich.gueltig_bis%TYPE,
v_source_system IN ctl_webadmin_abgleich.cldb_quellsystem_id%TYPE,
v_target_system IN ctl_webadmin_abgleich.cldb_zielsystem_id%TYPE,
v_table_id IN ctl_webadmin_abgleich.cldb_webadmin_table_id%TYPE)
IS
abgleich_id ctl_webadmin_abgleich.webadmin_abgleich_id%TYPE;
valid_from ctl_webadmin_abgleich.gueltig_von%TYPE;
valid_through ctl_webadmin_abgleich.gueltig_bis%TYPE;
source_system ctl_webadmin_abgleich.cldb_quellsystem_id%TYPE;
target_system ctl_webadmin_abgleich.cldb_zielsystem_id%TYPE;
table_id ctl_webadmin_abgleich.cldb_webadmin_table_id%TYPE;
BEGIN
dbms_output.put_line('Locking...' || lock_system.v_abgleich_id);
SELECT ab.webadmin_abgleich_id,
ab.gueltig_von,
ab.gueltig_bis,
ab.cldb_quellsystem_id,
ab.cldb_zielsystem_id,
ab.cldb_webadmin_table_id
INTO abgleich_id,
valid_from,
valid_through,
source_system,
target_system,
table_id
FROM ctl_webadmin_abgleich ab
WHERE ab.webadmin_abgleich_id = lock_system.v_abgleich_id FOR UPDATE;
END lock_system;
PROCEDURE validate_system(
v_abgleich_id IN ctl_webadmin_abgleich.webadmin_abgleich_id%TYPE,
v_valid_from IN ctl_webadmin_abgleich.gueltig_von%TYPE,
v_valid_through IN ctl_webadmin_abgleich.gueltig_bis%TYPE,
v_source_system IN ctl_webadmin_abgleich.cldb_quellsystem_id%TYPE,
v_target_system IN ctl_webadmin_abgleich.cldb_zielsystem_id%TYPE,
v_table_id IN ctl_webadmin_abgleich.cldb_webadmin_table_id%TYPE)
IS
overlapping_abgleich EXCEPTION;
src_target_same EXCEPTION;
from_date_null EXCEPTION;
from_date_gt EXCEPTION;
dummy CHAR(1);
BEGIN
IF(validate_system.v_source_system = validate_system.v_target_system) THEN
dbms_output.put_line('Raising src_target_same.');
RAISE src_target_same;
END IF;
IF(validate_system.v_valid_from IS NULL) THEN
dbms_output.put_line('Raising from_date_null.');
RAISE from_date_null;
END IF;
IF(validate_system.v_valid_from > validate_system.v_valid_through) THEN
dbms_output.put_line('Raising from_date_gt.');
RAISE from_date_gt;
END IF;
BEGIN
SELECT 'X'
INTO dummy
FROM ctl_webadmin_abgleich ab
WHERE ab.cldb_quellsystem_id = 5 AND ROWNUM = 1;
dbms_output.put_line('Conflicting recs foound: ' || validate_system.v_source_system);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('NO DATA FOUND:' || validate_system.v_source_system);
NULL;
END;
EXCEPTION
WHEN src_target_same THEN
RAISE_APPLICATION_ERROR(-20001, 'Quellsystem darf nicht gleich dem Zielsystem sein!');
WHEN from_date_null THEN
RAISE_APPLICATION_ERROR(-20002, 'VON Datum darf nicht NULL sein!');
WHEN from_date_gt THEN
RAISE_APPLICATION_ERROR(-20003, 'VON Datum liegt vor Datum BIS!');
WHEN overlapping_abgleich THEN
RAISE_APPLICATION_ERROR(-20004, 'Gültigkeitsbereiche mit schon existierenden Einträgen kollidieren!');
END validate_system;
PROCEDURE validate_systems
IS
sys_idx pls_integer;
BEGIN
dbms_output.put_line('Start validation...');
sys_idx := abgleich_rec.first;
LOOP
EXIT
WHEN sys_idx IS NULL;
validate_system(abgleich_rec(sys_idx).abgleich_id, abgleich_rec(sys_idx).valid_from, abgleich_rec(sys_idx).valid_through, abgleich_rec(sys_idx).source_system, abgleich_rec(sys_idx).target_system, abgleich_rec(sys_idx).table_id);
sys_idx := abgleich_rec.next(sys_idx);
END LOOP;
END validate_systems;
BEFORE EACH ROW
IS
BEGIN
abgleich_rec(:NEW.webadmin_abgleich_id).abgleich_id := :NEW.webadmin_abgleich_id;
abgleich_rec(:NEW.webadmin_abgleich_id).valid_from := :NEW.gueltig_von;
abgleich_rec(:NEW.webadmin_abgleich_id).valid_through := :NEW.gueltig_bis;
abgleich_rec(:NEW.webadmin_abgleich_id).source_system := :NEW.cldb_quellsystem_id;
abgleich_rec(:NEW.webadmin_abgleich_id).target_system := :NEW.cldb_zielsystem_id;
abgleich_rec(:NEW.webadmin_abgleich_id).table_id := :NEW.cldb_webadmin_table_id;
END BEFORE EACH ROW;
AFTER STATEMENT
IS
BEGIN
dbms_output.ENABLE (buffer_size => NULL);
dbms_output.put_line('Start validation...');
validate_systems;
dbms_output.put_line('Validation successful.');
END AFTER STATEMENT;
END abgleich_quellsystem_trg;
表格的DDL:
--------------------------------------------------------
-- DDL for Table CTL_WEBADMIN_ABGLEICH
--------------------------------------------------------
CREATE TABLE "CLDBDEF"."CTL_WEBADMIN_ABGLEICH"
( "WEBADMIN_ABGLEICH_ID" NUMBER(10,0),
"USERID_INS" NUMBER(10,0),
"TIMESTAMP_INS" TIMESTAMP (6),
"TIMESTAMP_UPD" TIMESTAMP (6),
"USERID_UPD" NUMBER(10,0),
"GUELTIG_VON" DATE,
"GUELTIG_BIS" DATE,
"CLDB_QUELLSYSTEM_ID" NUMBER(10,0),
"CLDB_WEBADMIN_TABLE_ID" NUMBER(10,0),
"CLDB_ZIELSYSTEM_ID" NUMBER(10,0)
);
--------------------------------------------------------
-- DDL for Index SYS_C0027983
--------------------------------------------------------
CREATE UNIQUE INDEX "CLDBDEF"."SYS_C0027983" ON "CLDBDEF"."CTL_WEBADMIN_ABGLEICH" ("WEBADMIN_ABGLEICH_ID") ;
--------------------------------------------------------
-- Constraints for Table CTL_WEBADMIN_ABGLEICH
--------------------------------------------------------
ALTER TABLE "CLDBDEF"."CTL_WEBADMIN_ABGLEICH" ADD PRIMARY KEY ("WEBADMIN_ABGLEICH_ID");
ALTER TABLE "CLDBDEF"."CTL_WEBADMIN_ABGLEICH" MODIFY ("WEBADMIN_ABGLEICH_ID" NOT NULL ENABLE);
谢谢大家的帮助! 人
更新:好的,我添加了
select count(*) into recnr from ctl_webadmin_abgleich ab;
dbms_output.put_line('Rec nr: ' || recnr);
在SELECT INTO之后,显然执行了INSERT并且count(*)返回1.这怎么可能?有人可以解释一下吗?谢谢!
答案 0 :(得分:0)
由于Boneist注意到您尝试插入的记录在您检查冲突时已存在于表中。更改您的select语句以排除您正在插入的记录的记录ID,它应按预期运行:
SELECT 'X'
INTO dummy
FROM ctl_webadmin_abgleich ab
WHERE ab.cldb_quellsystem_id = v_source_system
AND ab.WEBADMIN_ABGLEICH_ID != v_abgleich_id -- Add this condition
AND ROWNUM = 1;