zoukankan      html  css  js  c++  java
  • SQL_Server_2008完全学习之第十章触发器

    -

    1、什么时触发器?

    1)触发器是一个在修改指定表中的数据时执行的存储过程。经常通过创建触发器来强制实现不同表中的逻辑相关数据的引用完整性或一致性。由于用户不能绕过触发器,所以可以用它来强制实施复杂的业务规则,以此确保数据的完整性。

    2)触发器不同于存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。当对某一表进行诸如:UDPATE、INSERT、DELETE这些操作时,SQL Server就会自动执行触发器所定义的SQL语句,从而确保对数据的处理必须符合由这些SQL语句所定义的规则。

    为什么要使用触发器?

    1)触发器自动执行,它们在表的数据作了任何修改(比如手工输入或者使用程序采集的操作)之后立即激活。

    2)触发器可以通过数据库中的相关表进行层叠更改。这比直接把代码写在前台的做法更完全合理。

    3)触发器可以强制限制,这些限制比用CHECK约束所定义的更复杂。与CHECK约束不同的是,触发器可以引用其他表中的列。

    触发器的种类

    1)DDL触发器

    DDL触发器当服务器或者数据库中发生数据定义语言(DDL)事件时被调用。如果要执行以下操作,可以使用DDL触发器:

    a)要防止对数据库架构进行某些更改

    b)希望数据库中发生某种情总以响应数据库架构中的更改

    c)要记录数据库架构中的更改或者事件

    2)DML触发器

    DML触发器是当数据库服务器发生数据操作语言(DML)事件时要执行的操作。通常所说的DML触发器主要包括三种:INSERT触发器、UPDATE触发器、DELETE触发器。DML触发器可以查询其他表,还可以包含复杂的T-SQL语句。将触发器和触发它的语句做为可在触发器内回滚的单个事务对待。如果检测到错误,则整个事务自动回滚。

    2、创建INSERT触发器

    语法格式

    CREATE TRIGGER trigger_name

    ON {table|view}

    {

    {{FOR | AFTER | INSTEAD OF}

    {[DELETE][,][INSERT][,][UPDATE]}

    AS

    sql _statement

    }

    }

    --创建订单时,减少相应产品的库存数量
    CREATE TRIGGER t_AddOrder
    on [ORDER]
    for insert
    as 
    declare @pid int@sale int
    select @pid=pid,@sale=[count] from inserted
    update product set proCount=proCount-@sale where PID = @pid

    3、创建DELETE触发器

    --删除订单时,减少相应产品的库存数量
    ALTER TRIGGER t_RemoveOrder
    on [ORDER]
    for delete
    as 
    DECLARE cur_deleted scroll CURSOR 
    FOR select pid,[count] from deleted
    FOR read only
    OPEN cur_deleted
    declare @pid int@sale int
    FETCH NEXT FROM cur_deleted into @pid,@sale
    while @@fetch_status=0
    BEGIN
        update product set proCount=proCount+@sale where PID = @pid
        FETCH NEXT FROM cur_deleted into @pid,@sale
    End

    CLOSE cur_deleted
    DEALLOCATE cur_deleted

    insert into [Order] (pid,[count]values (1,2)
    insert into [Order] (pid,[count]values (2,3)

    delete [Order]

    select * from [Order]
    select * from [Product]

    4、创建UPDATE触发器

    注:可以把UPDATE动作看作DELETE + INSERT 动作的组合,既先删除旧的这些记录,再插入一条新的记录,此时在数据库中存在了两个临时表,既是DELETED和INSERTD。

    --使用UPDATE触发器给列加上修改权限

    CREATE TRIGGER t_EditProduct
    ON [Product] For Update
    as
    if update(proName)
    BEGIN
        print '产品名称为基础数据,不能被修改!'
        --回滚事务
        ROLLBACK Transaction
    END
    else
    BEGIN
        print '修改成功!';
    END

    --执行失败
    UPDATE Product set proName='IPhone 4' where pid = 1
    --执行成功
    UPDATE Product set proCount=10 where pid = 1

    5、创建DDL触发器

    语法格式

    CREATE TRIGGER trigger_name

    ON {ALL SERVER|DATABASE}

    WITH ENCRYPTIION

    FOR|AFTER|{event_type}

    AS

    sql_statement

    --使用DDL触发器禁止删除或修改表
    CREATE trigger t_DontDeleteTables
    ON Database
    For Drop_table,Alter_table
    AS
    Begin
        print '系统禁止删除或修改表!';
        Rollback Transaction
    End

    DROP table [Order]

    6、管理触发器

    --删除触发器
    drop trigger trigger_name

    --禁用触发器
    disable trigger trigger_name

    --启用触发器
    enable trigger trigger_name

    --示例
    ALTER table [Order] add status int not null default 0
    --禁用指定触发器
    disable trigger t_DontDeleteTables

    7、嵌套触发器(最多32层)

    --嵌套触发器完整示例
    CREATE TABLE Department(
    departmentId int not null identity(1,1primary key,
    departmentName nvarchar(20not null,
    departmentCount int not null default 0
    )

    CREATE TABLE Personnel(
    personnelId int not null identity(1,1primary key,
    departmentId int not null,
    personnelName nvarchar(10not null
    )

    CREATE TABLE NewPersonnel
    (
    personnelId int not null identity(1,1primary key,
    departmentId int not null,
    personnelName nvarchar(10not null
    )

    insert into Department (departmentName) values ('总经办'),('财务部'),('行政人事部'),('信息技术部'),('市场研发部'),('售后客服部')

    CREATE TRIGGER t_Delete 
    ON NewPersonnel
    FOR DELETE
    as
    BEGIN
        insert into Personnel select departmentId,personnelName from deleted
    END

    CREATE TRIGGER t_Insert
    ON Personnel
    FOR INSERT
    as
    BEGIN
        declare @departmentId int
        select @departmentId = departmentId from insertd
        update department set departmentCount=(select count(1from Personnel where departmentId=@departmentIdwhere departmentId=@departmentId
    END

    select * from department

    insert into NewPersonnel(departmentId,personnelName) values (1,'王**'),(1,'毛*'),(1,'张**')
    insert into NewPersonnel(departmentId,personnelName) values (2,'宋**'),(2,'高**'),(2,'殷**')
    insert into NewPersonnel(departmentId,personnelName) values (3,'庄**'),(3,'施**'),(3,'胡*'),(3,'刘**')
    insert into NewPersonnel(departmentId,personnelName) values (4,'张*'),(4,'宋**'),(4,'陈**')

    DELETE [NewPersonnel] where departmentId = 4

    8、递归触发器

    任何触发器都可以包含影响同一个表或另一个表的UPDATE/INSERT或DELETE语句。如果启用递归触发器选项,那么改变表中数据的触发器,通过递归执行就可以再次触发自己。在数据库创建时,默认情况下递归触发器选项是禁用的,但可以使用ALTER DATABASE语句来启用它。

    递归触发器具有复杂特性,可以用它来解决诸如自引用关系这样的复杂关系。使用递归触发器时,需要考虑以下的事项和原则:

    1)递归触发器很复杂,必须经过有条理的设计和全面的测试。

    2)在任意点的数据修改会触发一系列触发器。尽管提供处理复杂关系的能力,但是如果表要求以特定的顺序更新用户的表时,使用递归触发器就会产生问题

    3)所有触发器一起构成一个大事务。任何触发器中的任何位置上的ROLLBACK命令都将取消所有数据输入。所有数据均为擦除,并且无任何数据被放到表中

    4)触发器最多只能递归16层。换句话说,如果递归链中的第16个触发器激活了第17个触发器,则结果与发布ROLLBACK命令一样,所有数据将被擦除。

  • 相关阅读:
    近来几个有用的网站
    军事视频网站
    美军武器命名
    区块链的五个关键要素
    处理多媒体的两个重要工具
    Python re模块将字符串分割为列表
    Python 自动刷新网页
    selenium:chromedriver与chrome版本的对应关系
    怎么批量删除QQ空间说说?
    ssm获取数据库名称
  • 原文地址:https://www.cnblogs.com/cxmsky/p/3289116.html
Copyright © 2011-2022 走看看