zoukankan      html  css  js  c++  java
  • 触发器

    一:什么是触发器
    触发器是一种响应特定事件的特殊类型的存储过程
    insert update... drop alter...等事件都有相应的触发器

    二:简单的触发器
    下面一个例子是在插入或者修改记录的时候的一个触发器
    其中inserted表是一个临时表
    存储的是将要插入的信息
    这个触发器的目的是检查将要插入的信息是否符合规定
    (在product表里没有特殊的记录)
    这个例子是check约束所不能解决的了的

    use AdventureWorks
    go
    create trigger orderDetailNotDiscontinued
        
    on Sales.SalesOrderDetail
        after 
    insertupdate
    as
        
    if exists
        (
            
    select 'true' from Inserted i
            
    join Production.Product p
            
    on i.ProductID = p.ProductID
            
    where p.DiscontinuedDate is not null
        )
        
    begin
            
    print('error appear.')
            
    rollback tran
        
    end
    为了验证这个触发器
    先给表加入一条不符合条件的记录
    use AdventureWorks
    go
    update Production.Product
    set DiscontinuedDate = getdate()
    where ProductID = 680
    好了现在来一条插入语句看看
    use AdventureWorks
    go
    insert Sales.SalesOrderDetail
    (SalesOrderID,OrderQty,ProductID,SpecialOfferID,UnitPrice,UnitPriceDiscount)
    values
    (
    43660,5,680,1,1431,0)
    得到的消息是:
    error appear.
    消息 3609,级别 16,状态 1,第 1 行
    事务在触发器中结束。批处理已中止。

    三:针对触发器的操作
    1.禁用触发器
    use AdventureWorks
    go
    alter table Sales.SalesOrderDetail
    disable 
    trigger all  --这里的all可以是具体的触发器名
    2.删除触发器
    use AdventureWorks
    go
    drop trigger orderDetailNotDiscontinued
    3.修改触发器
    use xland
    go 
    alter trigger tr_title
    on mytable
    for insertupdate
    as
    if update(title)
    begin
        
    print('title1')
    end 
    (这里的update()函数不懂没关系,下面会说到)

    四:使用触发器记录操作情况
    先看代码
    use AdventureWorks
    go
    create table Production.inventoryAudit
    (
        id 
    int identity primary key,
        productid   
    int   not null
        
    references Production.Product(ProductID),
        netadjustment  
    smallint not null,
        modifieddate  
    datetime default(current_timestamp)    
    )
    go
    create trigger ProductAudit
        
    on Production.ProductInventory
        
    for insert,update,delete
    as
    insert into Production.inventoryAudit
    (productid,netadjustment)
    select coalesce  --coalesce哪个不为空用哪个
    (i.ProductID,d.ProductID),
    isnull(i.Quantity,0- isnull(d.Quantity,0as netadjustmenu
    from Inserted i
    full join Deleted d
    on i.ProductID = d.ProductID
    and i.LocationID = d.LocationID
    where 
    isnull(i.Quantity,0- isnull(d.Quantity,0!=0
    --isnull(i.Quantity,0)如果i.Quantity为空返回0(这个函数比较有用)
    注意这里用了full  join
    其实如果不是高并发inserted和deleted中有一个表是不存在的
    下面来测试一下这个触发器
    use AdventureWorks
    go
    update Production.ProductInventory
    set Quantity = Quantity +7
    where ProductID = 1
    and LocationID = 50
    select * from Production.inventoryAudit
    来看看消息:
    (1 行受影响)     这是修改的一行
    (1 行受影响)     这是触发器执行的一行
    (1 行受影响)     这是select的一行
    五:视图上的触发器
    instead of触发器
    先创建一个视图
    use xland
    go
    create view UserArticle_vw
    with Schemabinding
    as
    select a.id,a.title,u.username
    from dbo.mytable a  --必须有架构名,可以用as
    join dbo.[user] u
    on u.id = a.uid
    检查该视图
    use xland
    go
    select * from UserArticle_vw where id = 2
    创建一个视图上的触发器
    use xland
    go
    create trigger TRMytableInsert on UserArticle_vw
    instead 
    of insert 
    as
    begin
    if (select count(*from inserted) >0
       
    begin
         
    insert into mytable
         
    select i.title,u.id from inserted i
         
    join [user] u
         
    on u.username = i.username
         
    if @@rowcount = 0 --返回受影响的行数
            print('error appear')  
       
    end 
    end
    对这个视图执行插入操作!(有了上面的触发器就可以插入了)
    use xland
    go
    insert into UserArticle_vw (title,username) values ('zhe shi title','xland')
    看下消息
    (1 行受影响)
    (1 行受影响)
    类似的还有
    insted of update触发器
    insted of delete触发器

    六:触发器的相关函数
    看这个触发器
    use xland
    go 
    alter trigger tr_title
    on mytable
    for insertupdate
    as
    if update(title)
    begin
        
    print('title1')
    end 
    update()函数意思是
    指定的列被更改时发生
    看下验证语句
    use xland
    go 
    update mytable set title = 'xland' where id = 7
    结果
    title1
    (1 行受影响)
    还有一个函数
    columns_updated()有检查多个列的能力
    比较高级,也比较少用  我在这里就不写了
  • 相关阅读:
    设计模式:面向对象设计的六大原则 (绝对详细)
    idea创建maven项目速度慢?别急,这有三种方案
    Spring Cloud开发人员如何解决服务冲突和实例乱窜?
    Spring Cloud Zuul的动态路由怎样做?集成Nacos实现很简单
    Spring Boot自定义配置实现IDE自动提示
    阿里注册中心Nacos生产部署方案
    日志排查问题困难?分布式日志链路跟踪来帮你
    zuul集成Sentinel最新的网关流控组件
    YAML中多行字符串的配置方法
    JetBrains 第二轮:再为免费全家桶续命三个月
  • 原文地址:https://www.cnblogs.com/liulun/p/1372964.html
Copyright © 2011-2022 走看看