plsql 触发器生成和插入值

plsql Trigger to generate and insert values

我正在尝试创建一个触发器来自动生成带有年份和月份 (YYYYMM) 的值并将其插入到 table 中,因为插入是在另一个 table.

中进行的

示例: 由于插入 table 'original_table'

create table original_table 
(opt_value char(2),
 low_value varchar2(24),
 high_value varchar2(24));
 
 create table new_values
 (id_values varchar2(24),   
  yr_month number(6));

Insert into original_table(opt_value,low_value,high_value) values ('EQ', '1111111111', '1111111111');
Insert into original_table(opt_value,low_value,high_value) values ('BT', '2222222000', '2222222999');
Insert into original_table(opt_value,low_value,high_value) values ('BT', '3333333350', '3333333399');

original_table

opt_value low_value high_value
EQ 1111111111 1111111111
BT 2222222000 2222222999
BT 3333333350 3333333399

Obs:其中 EQ 代表 'equal' 和 BT 'between'。当 'EQ' 只需要插入其中一个值 low 或 high 无关紧要,当 'BT' 需要生成两个值之间的所有数字然后插入 'new_values' table.

table 'new_values' 应该得到:

new_values

id_values yr_month
1111111111 202111
2222222000 202111
2222222001 202111
2222222002 202111
... ...
2222222999 202111
3333333350 202111
3333333351 202111
... ...
3333333399 202111

我创建了一个有效的触发器,但我发现它有点慢,而且我不喜欢使用 BEFORE INSERT 语句,但不能在不发生变异 table 错误的情况下使用 AFTER INSERT。

create or replace TRIGGER TRG_NAME
    BEFORE INSERT 
    ON original_table
    FOR EACH ROW
BEGIN

    IF :NEW.opt_value = 'BT' THEN
        INSERT INTO new_values (id_values, yr_month) 
        with tab123 (h_value, l_value, y_month)
                  as (select :NEW.high_value, cast(:NEW.low_value as number) , to_char(trunc(sysdate), 'YYYYMM')
                     from original_table 
                     union all
                     select h_value, l_value +1, y_month
                        from tab123
                       where l_value < h_value)
            select distinct  l_value, y_month
              from tab123;

    ELSIF :NEW.opt_value = 'EQ' THEN
         INSERT INTO new_values (id_values, yr_month) values
             ( :NEW.high_value, to_char(add_months(trunc(sysdate), -1), 'YYYYMM'));    
    END IF;
END;

任何有关如何改进此代码的提示都将不胜感激。

当您从正在更改的 table 中读取时,您会收到一个变异 table 错误。

奇怪的是,您是在 AFTER INSERT 触发器中而不是在 BEFORE INSERT 触发器中获取它。我会假设它们都会导致相同的错误,因为在这两种情况下,您都从触发器中的触发 table 中读取。嗯,这可能与只插入一行有关。如果您一次插入更多行,您可能会遇到两种触发器变体的错误。

在你的例子中,从你的触发器中读取 original_table 中的所有行无论如何只会产生重复,你用 DISTINCT 来抵挡。相反,不要从 table 中读取。没有必要。改为从 DUAL 读取,以获得包含所需值的一行:

with tab123 (h_value, l_value, y_month) as 
(
  select :new.high_value, cast(:new.low_value as number), to_char(sysdate, 'yyyymm')
  from dual
  union all
  select h_value, l_value + 1, y_month
  from tab123
  where l_value < h_value
)
select l_value, y_month
from tab123;

这将使您摆脱变异 table 错误并加快触发速度。