0

由于表正在变异,因此以下触发器不起作用,因为我认为触发器中的 SQL 语句无法针对变异表执行,但是由于我不在 11g 上,因此我无法创建复合触发器。我已经尝试PRAGMA AUTONOMOUS TRANSACTION;在声明部分包含在内,但是这不会编译。谁能给我最好的解决方案?

create or replace 
trigger fb_pers_id_check2_tr
  --after insert on ifsapp.person_info_tab
  before insert on ifsapp.person_info_tab      
for each row
begin
  declare
--  pragma autonomous_transaction;
    v_pid_ person_info_tab.person_id%type;
    format_name_ person_info_tab.name%type;
  begin

  v_pid_ := :new.person_id;

  select regexp_replace(upper(:new.name), '\W')
    into format_name_
  from ifsapp.person_info_tab
  where person_id = v_pid_;

  if length(v_pid_) < 3 and (length(format_name_) < 21 and v_pid_ <> format_name_) then
    raise_application_error(-20001, 'Person ID: ' || v_pid_ || 'is not valid, please enter a valid     Person ID, e.g. "' || format_name_ || '".');
  end if;
end;
end fb_pers_id_check2_tr;

NB 简单来说,此触发器旨在阻止用户设置长度小于 3 个字符且不等于变量“format_name_”(如果长度小于 21 个字符)的用户 ID。

4

1 回答 1

2

Oracle 不允许行触发器读取或修改定义触发器的表。但是,如果 PERSON_ID 是 PERSON_INFO_TAB 上的 PRIMARY 或 UNIQUE 键(鉴于它在单例 SELECT 中使用,这似乎是这种情况),您实际上并不需要读取表 - 只需在适当的情况下使用 OLD 或 NEW 值:

create or replace trigger fb_pers_id_check2_tr
  before insert on ifsapp.person_info_tab
  for each row
declare
  v_pid_ person_info_tab.person_id%type;
  format_name_ person_info_tab.name%type;
begin
  v_pid_ := :new.person_id;

  format_name_ := REGEXP_REPLACE(UPPER(:new.name), '\W');    

  if length(v_pid_) < 3 and
     length(format_name_) < 21 and
     v_pid_ <> format_name_
  then
    raise_application_error(-20001, 'Person ID: ' || v_pid_ ||
                            ' is not valid, please enter a valid' ||
                            ' Person ID, e.g. "' || format_name_ || '".');
  end if;
end fb_pers_id_check2_tr;

这里的代码正在检查 NAME 的 NEW 值(我认为这是正确的,因为它似乎正在验证输入),但如果目的是检查 OLD 值,那么在 REGEXP_REPLACE 调用中将 :NEW 更改为 :OLD 很简单.

分享和享受。

于 2013-07-24T11:11:08.250 回答