【问题标题】:SQL TRIGGER: How do you restrict something from being changed?SQL TRIGGER:你如何限制某些东西被改变?
【发布时间】:2019-12-04 18:28:21
【问题描述】:

在我的触发器中,如果列 Z 的值为 W,我必须限制列 X 更改为值 Y。IF 语句的外观如何?谢谢!

这是Class 表:

class         type  tara            nr_arme diametru_tun    deplasament
Ticonderoga   cr    Norvegia        16      23              4500
Maryland      vl    SUA             10      12              10000
Foxtrot       vl    Russia          20      45              5800
Buyan         cr    Russia          15      20              15000
Amphion       cr    Marea Britanie  13      14              12000

那些是ships

name    class        anul_lansarii
Nava1   Ticonderoga  1995
Nava2   Amphion      1980
Nava3   Foxtrot      2005
Nava4   Buyan        1960
Nava5   Maryland     1970

这是Consequences 表。

name    batalie                 result
Nava1   Battle of Chemulpo Bay  scufundat
Nava3   Battle of Chemulpo Bay  avariat
Nava2   Battle of Hudson Bay    nevatamat
Nava4   Battle of Bengal Bay    nevatamat
Nava5   Battle of Bengal Bay    avariat

因此,如果船 (nava) 的类型为“cr”,则结果不能为“nevatamat”。它忽略更新。

【问题讨论】:

  • 如果有人试图将 X 列更改为 Y 值,如果 Z 列的值是 W,你想得到什么?出现异常还是默默忽略更新?
  • 忽略更新
  • 尝试用英文写出逻辑......甚至用plsql,然后我们可以更好地回答你的问题。如果您想在表定义中包含一些示例数据,那就更好了
  • 忽略整个更新语句还是只忽略 X 列的更新?
  • 您有三个表完全不同于“限制列 X 更改为值 Y,如果列 Z 的值是 W”而且“限制列 X 更改”与“结果不能是“nevatamat””请说明您的要求。

标签: sql oracle plsql oracle-apex database-trigger


【解决方案1】:

测试用例:

SQL> create table class
  2    (class   varchar2(20),
  3     type    varchar2(2));

Table created.

SQL> create table ships
  2    (name    varchar2(5),
  3     class   varchar2(20));

Table created.

SQL> create table consequences
  2    (name    varchar2(5),
  3     result  varchar2(10));

Table created.

SQL> insert all
  2    into class values ('Ticonderoga' , 'cr')
  3    into class values ('Maryland'    , 'vl')
  4    --
  5    into ships values ('Nava1'       , 'Ticonderoga')
  6    into ships values ('Nava5'       , 'Maryland')
  7    --
  8    into consequences values ('Nava1', 'scufundat')
  9    into consequences values ('Nava5', 'avariat')
 10  select * from dual;

6 rows created.

SQL>

触发器:

SQL> create or replace trigger trg_biu_cons
  2    before insert or update on consequences
  3    for each row
  4  declare
  5    l_type class.type%type;
  6  begin
  7    if :new.result = 'nevatamat' then
  8       select c.type
  9         into l_type
 10         from class c
 11         where c.class = (select s.class
 12                          from ships s
 13                          where s.name = :new.name
 14                         );
 15       if l_type = 'cr' then
 16          raise_application_error(-20000, 'Ship''s type is CR; result can''t be NEVATAMAT');
 17       end if;
 18    end if;
 19  end;
 20  /

Trigger created.

SQL>

测试:

SQL> update consequences set result = 'nevatamat' where name = 'Nava1';
update consequences set result = 'nevatamat' where name = 'Nava1'
       *
ERROR at line 1:
ORA-20000: Ship's type is CR; result can't be NEVATAMAT
ORA-06512: at "SCOTT.TRG_BIU_CONS", line 13
ORA-04088: error during execution of trigger 'SCOTT.TRG_BIU_CONS'


SQL> update consequences set result = 'avariat'   where name = 'Nava1';

1 row updated.

SQL> update consequences set result = 'nevatamat' where name = 'Nava5';

1 row updated.

SQL>

【讨论】:

  • 你在这里声明什么:l_type class.type%type;我不明白
  • 这是一个局部变量,用于接受船的类型(“cr”或“vl”或您可能拥有的任何类型)。这就是语法 - table_name.column_name%type。你的表名是class,列名是type,所以它变成了class.type%type。我本可以使用例如l_type varchar2(2),但是 - 如果你决定修改它,你将不得不在你的代码周围修改它。因此,引用列的类型是更好的选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多