Oracle中触发器有几种,用法与SQL Server一样吗?谢谢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle中触发器有几种,用法与SQL Server一样吗?谢谢相关的知识,希望对你有一定的参考价值。

参考技术A ORACLE触发器有以下两类:
1
语句级(Statement-level)触发器,在CREATE
TRIGGER语句中不包含FOR
EACH
ROW子句。语句级触发器对于触发事件只能触发一次,
而且不能访问受触发器影响的每一行的列值。一般用语句级触发器处理有关引起触发器触发的SQL语句的信息——例如,由谁来执行
2
行级(Row-level)触发器,在CREATE
TRIGGER语句中包含FOR
EACH
ROW子句。行级触发器可对受触发器影响的每一行触发,并且能
够访问原列值和通过SQL语句处理的新列值。行级触发器的典型应用是当需要知道行的列值时,执行一条事务规则。
SQL
Server支持两种类型的触发器:
AFTER
触发器和INSTEAD
OF
触发器。其中AFTER
类型触发器要求只有执行某一操作(INSERT
UPDATE
DELETE)
之后,触发器才被触发,且只能在表上定义。可以为针对表的同一操作定义多个触发器。对于AFTER
触发器,可以定义哪一个触发器被最先触发,哪一个被最后触发,通常使用系统过程sp_settriggerorder
来完成此任务。
INSTEAD
OF
触发器表示并不执行其所定义的操作(INSERT、
UPDATE、
DELETE),而仅是执行触发器本身。既可在表上定义INSTEAD
OF
触发器,也可以在视图上定义INSTEAD
OF
触发器,但对同一操作只能定义一个INSTEAD
OF
触发器。

SQL server与Oracle触发器的创建与使用

SQL Server

1创建触发器

GO
BEGIN
IF (object_id(‘WMY‘, ‘tr‘) is not null)
DROP trigger WMY
END;
GO
CREATE TRIGGER WMY
ON Student
Instead of INSERT
AS
BEGIN
    INSERT INTO Student (number,name) VALUES (1205,‘角色2‘);
END;
--Begin 与end相当于{},是一个语句块,可有可无此处为演示所用
--ON 后面跟表明,表示作用于那个表
--ON Student下面(Instead of INSERT)可有改为(Instead of,after,for)(update,delete,Insert)

解析(已上列Insert触发器为例其他雷同)(以下先后顺序以插入表中数据的排序为例)

  • 当为Instead of 时,在触发器中的SQL语句代替你文中执行的插入语句,即当你在任何地方执行一个插入语句,这条语句实际没有执行而触发器里面的语句则执行
  • 当为for 时,在触发器中的SQL语句与你文中执行的插入语句都执行只是触发器中先于文中的执行
  • 当为 After时 在触发器中的SQL语句与你文中执行的插入语句都执行只是触发器中晚于文中的执行(网上都这样说可简单测试时与for效果一样)

摘自网上:

1 “Instead of”触发器

  • “Instead of”触发器在执行真正“插入”之前被执行。除表之外,“Instead of” 触发器也可以用于视图,用来扩展视图可以支持的更新操作。
  • “Instead of”触发器会替代所要执行的SQL语句,言下之意就是所要执行SQL并不会“真正执行”

2 “After”触发器

  • “After”触发器在Insert、Update或Deleted语句执行之后被触发。“After”触发器只能用于表。
  • “After”触发器主要用于表在修改后(insert、update或delete操作之后),来修改其他表

SQL Server为每个触发器都创建了两个专用表:Inserted表和Deleted表

  • 这两个表由系统来维护,它们存在于内存中而不是在数据库中,可以理解为一个虚拟的表。
  • 这两个表的结构总是与被该触发器作用的表的结构相同。
  • 触发器执行完成后,与该触发器相关的这两个表也被删除。
  • Deleted表存放由于执行Delete或Update语句而要从表中删除的所有行。
  • Inserted表存放由于执行Insert或Update语句而要向表中插入的所有行。
GO
INSERT INTO Student (number,name) VALUES (1807,‘角色‘);

深度解析使用序列以及Inserted表

USE [OSMP]
BEGIN
IF EXISTS (SELECT * FROM sysobjects WHERE name = ‘Person‘)
AND NOT EXISTS (select * from Person) 
DROP table Person
END
GO
CREATE TABLE Person
(
    num,int
    S_score,int
    S_name,NVARCHAR(64),
    primary key (num)
)
BEGIN
IF EXISTS (SELECT * FROM sysobjects WHERE name = ‘Student‘)
AND NOT EXISTS (select * from Student) 
DROP table Student
END
GO
CREATE TABLE Student
(
    score,int
    name,NVARCHAR(64),
    primary key (name)
)
--创建序列
BEGIN
IF EXISTS (SELECT * FROM sysobjects WHERE name = ‘Student_SEQ‘)
DROP SEQUENCE Student_SEQ
END
CREATE SEQUENCE Student_SEQ
MINVALUE 1
MAXVALUE 999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 20;

GO
BEGIN
IF (object_id(‘WMY‘, ‘tr‘) is not null)
DROP trigger WMY
END;
GO
CREATE TRIGGER WMY
ON Student
instead of INSERT
AS
BEGIN
    Insert into Person (num,S_score,S_name)select next value for Student_SEQ,score,name from Inserted 
--此处并无意思主要用于理解,执行下面的Student插入语句是,数据库维护了一个与Student数据结构一样的表Inserted,
--这里利用这个表和序列值来为Person做插入,而实际上没有执行Student插入,如果想要Student也执行把Instead of 改为for或after END; GO Insert into Student(score,name) values(‘1‘,‘m‘);

插曲获取序列的当前值

GO
SELECT current_value FROM sys.sequences WHERE name = ‘Student_SEQ‘

Oracle 触发器与SQL server类似,在此只显示代码

BEGIN
    EXECUTE IMMEDIATE ‘DROP TABLE Person‘;
    EXCEPTION WHEN OTHERS THEN NULL;
END;

CREATE TABLE Person
(
    num        INTEGER,
    S_score   INTEGER,
    S_name     NVARCHAR2(64),
    primary key (num)
)
BEGIN
    EXECUTE IMMEDIATE ‘DROP TABLE Student‘;
    EXCEPTION WHEN OTHERS THEN NULL;
END;

CREATE TABLE Student
(
    score   INTEGER,
    name     NVARCHAR2(64),
    primary key (name)
)
--创建序列
BEGIN
    EXECUTE IMMEDIATE ‘DROP SEQUENCE Student_SEQ‘;
    EXCEPTION WHEN OTHERS THEN NULL;
END;
CREATE SEQUENCE Student_SEQ
MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 20;
CREATE OR REPLACE TRIGGER TR_INST_DEVICE
BEFORE INSERT ON M_DEVICEENTITY
FOR EACH ROW

BEGIN
    select Student_SEQ.NEXTVAL into :new.num from dual;
    --select ‘A‘ || trim(to_char(:new.num, ‘00000000‘)) into :new.score from dual;
    --这个两语句作用并无练习,第一个取出序列的下一个值插入new表中(new表类似SQL server 中的Inserted)
    --更改score的标示发以A_0000001为样式,这个语句只做参考在此处无用也运行不了(因为表的字段类型)
END;
GO
Insert into Student(score,name) values(‘1‘,‘m‘)

 记录集中值与表组合的表示方法

Insert into Person(n, num, name) select next value for ENTITY_SEQ,number,name from Student where number=114;
--next value for ENTITY_SEQ序列与select字段组合添加
Insert into Person(n, num, name) select cast(100 as int),number,name from Student where number=114;
--cast(100 as int)值与字段组合添加

  

 

 

以上是关于Oracle中触发器有几种,用法与SQL Server一样吗?谢谢的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 中的触发器有几种?

SqlServer里设置主键自增长有几种方式?

Oracle 存储过程中OUT参数的用法

SqlServer里设置主键自增长有几种方式?

Oracle实现主键自增的几种方式

mysqldump有几种自动执行的方法