Oracle触发器防止指定值写入列

Oracle trigger to prevent specified value wrote into column

我正在研究 Oracle 11g 64 位。 假设我有一个名为 "MyTable" 的 table,我正在尝试监视一个名为 "My_Name".

的列

当 "My_Name" 将更改为 ''(更新前)时,我想停止它并将 "My_Name" 更改回旧值。换句话说,'' 不是 "My_Name" 列的合法值。

这是我目前所做的,没有编译错误,但没有效果,我仍然可以将 '' 值写入 "My_Name" 列。

CREATE OR REPLACE TRIGGER MyTable_tracking
BEFORE INSERT OR UPDATE ON MyDB.MyTable REFERENCING NEW AS newValue OLD AS oldValue
FOR EACH ROW

DECLARE
v_old       VARCHAR(20);
v_new       VARCHAR(20);

BEGIN
  IF INSERTING THEN
    v_new:=:newValue.My_Name; --Trigger checks column 'My_Name' only
  ELSIF UPDATING THEN
    v_old:=:oldValue.My_Name; --Trigger checks column 'My_Name' only
    v_new:=:newValue.My_Name; --Trigger checks column 'My_Name' only
    --IF :newValue.My_Name='' THEN
    IF LENGTH(TRIM(:newValue.My_Name))=0 THEN
      :newValue.My_Name:=:oldValue.My_Name;
    END IF;
  END IF;
END;

我该怎么做?

不需要触发器。在 Oracle 中,空字符串 ''null 是同一回事。所以只要定义 my_nameNOT NULL 并且你不能把 null'' 放在里面。

SQL> create table my_table (id integer primary key, my_name varchar(20) not null);

Table created.

SQL> insert into my_table values (1, 'Arthur');

1 row created.

SQL> update my_table set my_name = '' where id = 1;
update my_table set my_name = '' where id = 1
                    *
ERROR at line 1:
ORA-01407: cannot update ("ARTHUR"."MY_TABLE"."MY_NAME") to NULL

SQL> insert into my_table values (2, '');
insert into my_table values (2, '')
                                *
ERROR at line 1:
ORA-01400: cannot insert NULL into ("ARTHUR"."MY_TABLE"."MY_NAME")

SQL>

如果你因为外部限制而不能使用最有效的解决方案(我发现高度有问题),你可以使用这样的东西:

create or replace trigger slow_not_null_check
   before insert or update on my_table
   for each row
begin
   if inserting and :new.my_name is null then 
      :new.my_name := 'No NULL allowed';
   end if;

   if updating and :new.my_name is null then 
      :new.my_name := :old.my_name;
   end if;
end;
/ 

插入时,'' 会自动转换为 'No NULL allowed',更新时会恢复之前的值:

insert into my_table values (1, '');
insert into my_table values (2, 'Arthur');

select * from my_table;

ID | MY_NAME        
---+----------------
 1 | No NULL allowed
 2 | Arthur         


update my_table
  set my_name = ''
where id = 2;

select * 
from my_table;


ID | MY_NAME        
---+----------------
 1 | No NULL allowed
 2 | Arthur         

我用下面的代码解决了我的问题

IF INSERTING THEN
  v_new:=:newValue.My_Name;
ELSIF UPDATING THEN
  v_old:=:oldValue.My_Name;
  v_new:=:newValue.My_Name;
  --IF :newValue.My_Name='some specified value' THEN --not allow some value
  --IF :newValue.My_Name='' --not working
  IF :newValue.My_Name='' OR :newValue.My_Name IS NULL THEN --not allow '' or null
    :newValue.My_Name:=v_old; --works
    --:newValue.My_Name:=:oldValue.My_Name; --not working, use variable instead
  END IF;
END IF;