Oracleの原則:DMLトリガーとデータベーストリガー

1つ、DMLトリガー

トリガーの機能は、イベントが発生したときに実行ブロック内のコンテンツを自動的に実行することです。

トリガーは、テーブルまたはビューに作用し、挿入、更新、または削除操作の前、最中、または後に実行される特定のプログラムセグメントを指定できます。

CREATE [OR REPLACE] TRIGGER triggername 
  BEFORE/INSTEAD OF/AFTER           ---选择事件触发(前,时,后)执行 PL/SQL代码块
  [INSERT [OR] UPDATE [OR] DELETE]  ---当执行 插入 、更新、删除前触发
  ON tblname_or_viewname            ---确认作用的表或者视图
  [Referencing {OLD [AS] old / NEW [AS] new }] 
  [FOR EACH ROW]           --指定行级触发器,不指定就是表级触发器
  [WHEN (condition)]       --当符合condition的条件满足时触发
DECLARE
  -- local variables here
BEGIN
  ;--PL/SQL block

END triggername ;

sqlserverで削除されたのは、Oracle:oldに対応する、更新および削除される古い情報を格納するための一時テーブルです。Insertedは、Oracle:newに対応する、挿入および更新されようとしている新しい情報を格納するための一時テーブルです。:newと:oldは、データセット全体を表すのではなく、操作対象のデータの行を表すため、通常、[FOR EACH ROW]は、これら2つを使用する場合の行トリガーを示すために追加されます。その中で、更新の操作は、実際には、データを最初に古いものに入れ、次に削除してから新しいデータを新しいものに入れてデータベースに挿入することです。

古いデータが保存されているため、古いデータが削除または変更されようとしているため、古いデータを更新しても意味がありません。操作が完了した後にトリガーされた後は、この時点で新しいデータを操作しても意味がありません。後の場合、:newのレコードは変更できません。

マルチテーブルビューの場合テーブルの内容を保持するようにキーを変更することができます単一テーブルビューjでDML操作を実行することもできます。

テーブルレベルのトリガーは、テーブルまたはビューイベントがトリガーされたときに1回だけ実行されます。テーブルまたはビューイベントで行レベルのトリガーがトリガーされると、データの行が影響を受けるたびにプログラムブロックのコンテンツが1回実行されます。

ロールバック、コミット、およびDDLステートメントはDMLトリガーでは使用できません。

新しい練習テーブルdepartment_tblを作成します。

次のトリガーを作成して、効果を比較します

create view VW_department_tbl as select * from department_tbl;
--------insert视图VW_department_tbl时,给每行数据Leaders 默认值'BOSS'----
create or replace trigger departInsertDefault2
  Instead of insert   --替换原有的insert语句,且Instead Of 只能作用于视图, WHEN不能用于 INSTEAD OF
  on VW_department_tbl
  FOR EACH ROW
declare
begin
  if  :new.leaders is null then
    insert into department_tbl values(:new.department,:new.all_salary,'BOSS');
  else 
     insert into department_tbl values(:new.department,:new.all_salary,:new.leaders);
  end if;
end departInsertDefault2 ;
drop trigger departInsertDefault2;
-----------------------------------
--------insert表department_tbl时,给每行数据Leaders 默认值'BOSS'----
create or replace trigger departInsertDefault1
  before insert 
  on department_tbl 
  FOR EACH ROW
  WHEN (new.leaders is null
)declare
  
begin 
  :new.leaders :='BOSS';
end departInsertDefault1 ;
drop trigger departInsertDefault1;

トリガー2で実行

トリガー1で実行

新しいトリガー3、

create or replace procedure dep_insert(dep in department_tbl.department%type ,sal in department_tbl.all_salary%type) 
is  PRAGMA AUTONOMOUS_TRANSACTION;  --自主事物处理
begin
 insert into department_tbl values(dep,sal,'BOSS');
  --update department_tbl set leaders='BOSS' where leaders is null and department = dep;  --取不到还未提交的数据
commit;
end dep_insert;
/
create or replace trigger departInsertDefault3
  after insert        --after 无法修改基表的数据,需要自主事物处理的存储过程配合,且新数据属于未提交状态
  on department_tbl
  FOR EACH ROW
  WHEN (new.leaders is null)
  
declare
  v_data department_tbl%rowtype;
begin  
 --update department_tbl set leaders='BOSS' where leaders is null and department = :new.department;  --无法执行
  dep_insert( :new.department,:new.all_salary);
  
end departInsertDefault3 ;
drop trigger departInsertDefault3;

実施した

つまり、データを変更する場合は、データ検証に適した前、後を使用することをお勧めします。代わりに、ビューにのみ使用できます。

更新例:

create or replace trigger departInsertDefault4
  before update        
  on department_tbl
  FOR EACH ROW
  when (old.department = new.department)
declare
begin  
    :new.all_salary := :new.all_salary+:old.all_salary;
end departInsertDefault4 ;
/
--drop trigger departInsertDefault4;

truncate table department_tbl;
insert into department_tbl(department,all_salary) values('部门1',2000);
insert into department_tbl(department,all_salary,leaders) values('部门1',2000,'BOSS');
insert into department_tbl(department,all_salary,leaders) values('部门2',3000,'雇佣者1');
update department_tbl set department = '部门999' where Leaders is not null;
update department_tbl set Leaders = 'boss' where Leaders is not null;
commit;
select * from department_tbl;

最終的な実行結果:

2、モード(DDL)トリガー


Create table obj_tbl(
obj_name varchar2(30),
obj_type varchar2(20),
obj_date Date
)

create or replace trigger obj_trigger 
 after Create --alter drop
on SCHEMA
BEGIN
  insert into  obj_tbl values( ora_dict_obj_name,ora_dict_obj_type,SYSDATE);
END;
/

ora_client_ip_address クライアントのIPアドレスを返すために使用されます
ora_database_name 現在のデータベース名を返すために使用されます
ora_des_encrypted_pa​​ssword DES暗号化ユーザーパスワードを返すために使用されます
ora_dict_obj_name DDL操作に対応するデータベースオブジェクト名を返すために使用されます
ora_dict_obj_name_list(name_list_ OUT ora_name_list_t) ワードイベントで変更されたオブジェクト名のリストを返すために使用されます
ora_dict_obj_owner DDL操作に対応するオブジェクトの所有者名を返すために使用されます。
ora_dict_obj_ower_list(ower_list OUT ora_name_list_t) イベントで変更されたオブジェクトの所有者のリストを返すために使用されます
ora_dict_obj_type DDL操作に対応するデータベースオブジェクトのタイプを返すために使用されます。
ora_grantee(user_list OUT ora_name_list_t) 承認中にイベント承認者を返すために使用されます。
ora_instance_num コース番号を返すために使用されます。
ora_is_alter_column(column_name IN VARCHAR2) 特定の列が変更されたかどうかを検出するために使用されます
ora_is_creating_nested_table ネストされたテーブルが作成されているかどうかを検出するために使用されます
ora_is_drop_column(column_name IN VARCHAR2) 特定の列が削除されたかどうかを検出するために使用されます
ora_is_servererror(error_number) 特定のOracleエラーが返されたかどうかを検出するために使用されます。
ora_login_user ログインユーザー名を返すために使用されます
ora_sysevent  トリガーをトリガーしたシステム時刻の名前を返すために使用されます。

 

 

3つのデータベースレベルのトリガー

 

----数据库启动触发器-----
create or replace trigger db_trigger 
after startup on database
begin 
  insert into  obj_tbl values( ora_sysevent,null,SYSDATE);
end;
/
----数据库用户登录触发器-----
create or replace trigger user_trigger 
after logon on database
begin 
  insert into  obj_tbl values( ora_login_user,ora_client_ip_address,SYSDATE);
end;
/ 

第四に、トリガーの操作

alter tigger tiggername ENABLE / DISABLEトリガーを開閉します 

select * from dba_triggers / user_triggersクエリトリガー情報

おすすめ

転載: blog.csdn.net/superSmart_Dong/article/details/107093957