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 错误并加快触发速度。
我正在尝试创建一个触发器来自动生成带有年份和月份 (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 错误并加快触发速度。