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_name
为 NOT 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;
我正在研究 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_name
为 NOT 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;