• 数据库复习总结(22)-触发器和游标


    一、触发器

    (1)是什么:实现改变(增加、修改、删除)发生时引发代码执行的对象
    (2)根据触发时机不同,分类如下:
               after触发器
               instead of替换触发器
              (×)before触发器:sql server不支持
    (3)创建触发器
    CREATE TRIGGER 名称 ON 表名
    触发器类型(AFTER或Instead of)
    触发操作(INSERT或DELETE或UPDATE)
    AS
    BEGIN
    SET NOCOUNT ON;--不返回受影响行数,可以得到自定义的返回结果
    END
    (4)两个临时表:inserted、deleted
    更新的操作:先删除原数据,再插入新数据,这个过程既用到了inserted表又用到了deleted表
    (5)建议:性能影响太大,慎重使用

    触发器是一种用来保障参照完整性的特殊的存储过程,它维护不同表中数据间关系的有关规则。当对指定的表进行某种特定操作(如:Insert,Delete或Update)时,触发器产生作用。触发器可以调用存储过程。

    创建触发器的语法:

    Create Trigger[owner.]触发器名
     
    On [owner.]表名
     
    For {insert,update,delete}
     
    As
     
    Begin
     
    SQL语句(块)
     
    End
    View Code

    定义一个好的触发器对简化数据的管理,保证数据库的安全都有重要的影响。触发器是针对表一级的,这就意味着,只有表的所有者有权创建表的触发器。

    举例:

    /* 插入一个新行,必须保证外键与主键相匹配,触发器应该首先检查被插入行与主键表的连接。*/
     
    #以下的触发器对inserted表和titles表的title_id进行比较,这里假设正在给外键输入数据,没有插入空值,若连接失败,事务被回退。insert,update,delete
     
    Create trigger forinsertrigl
     
    On salesdetail
     
    For insert
     
    As
     
    If(select count(*)
     
    From title,inserted
     
    Where titles.title_id=inserted.title_id)!=@@rowcount
     
    Begin
     
    Rollback transaction
     
    Print “No,some title_id does not exist in titles.”
     
    End
     
    Else
     
    Print “Added! All the title_id is exist in titles.”
     
    /*
      在本例中,@@rowcount代表添加到salesdetail表的行数,这也是添加到inserted表中的行数。通过连接表titles和表inserted来检测所有添加到salesdetail的title_id是否在titles中存在。若所连接的行数(count(*))与@@rowcount不同,由有一个或多个插入不正确,整个事务被取消。*/
    View Code

    触发器的限制:

    ●一个表最多只能有三个触发器,insert,update,delete

    ●每个触发器只能用于一个表

    ●不能对视图、临时表创建触发器

    ●Truncate table能删除表,但不能触发触发器

    ●不能将触发器用于系统表

    合理地使用触发器对性能的影响是正面的。在设计和使用触发器时,经常地用sp_depends命令了解对象所关联的触发器是有好处的,该命令能列出触发器影响的所有对象、表和视等。

    在定义几类数据库对象的时候,对存储过程、索引和触发器要给予特别的注意,尤其存储过程,它设计的好坏对数据库性能的影响很大。

    说明:Sybase触发器使用的两个测试表:Deleted表和Inserted表,它们都是临时表,其结构与触发器的基表结构相同,用来存放与修改相关的数据行。

    常见的触发器有三种:分别应用于Insert,Update,Delete事件。

    使用触发器的优点

    触发器是自动的:它们在对表的数据作了任何修改(比如手工输入或者应用程序采取的操作)之后立即被激活。

    触发器可以通过数据库中的相关表进行层叠更改。例如,可以在 titles 表的 title_id 列上写入一个删除触发器,以使其它表中的各匹配行采取删除操作。该触发器用 title_id 列作为唯一键,在 titleauthor、sales 及 roysched 表中对各匹配行进行定位。

    触发器可以强制限制,这些限制比用 CHECK 约束所定义的更复杂。与 CHECK 约束不同的是,触发器可以引用其它表中的列。例如,触发器可以回滚试图对价格低于 10 美元的书(存储在 titles 表中)应用折扣。

    二、游标

    可以逐条操作表中的数据

    缺点:性能低,慎重使用

    语法

    declare @id int
    declare @salary money
    declare @bonus money
    declare s1 cursor for select eid,eSalary,eBonus from tblEmpSalary
    open s1
    fetch s1 into @id,@salary,@bonus
    while @@FETCH_STATUS=0
    begin
        update tblEmpSalary set eSalary=@salary+@bonus*0.1 where eid=@id
        --print @salary
        fetch s1 into @id,@salary,@bonus
    end
    close s1
    deallocate s1
    View Code

     一,游标是什么?

                     游标是一段私有的SQL工作区,也就是一段内存区域,用于暂时存放受SQL语句影响到的数据。通俗理解就是将受影响的数据暂时放到了一个内存区域的虚表中,而这个虚表就是游标。

     

            二,作用是什么?

                      1,大家都知道数据库中的事物可以回滚,而游标在其中起着非常重要的作用,由于对数据库的操作我们会暂时放在游标中,只要不提交,我们就可以根据游标中内容进行回滚,在一定意义有利于数据库的安全。

                     2,另外,在OraclePL/SQL只能返回单行数据,而游标弥补了这个不足。相当于ADO.NET中的Data table吧。

     

             三,类型:

                    1,隐式游标:增删改等操作Oracle都会自动创建游标,暂时保存操作结果,也就是能够回滚的操作都会引发游标的创建。

                    2,显示游标:由开发人员通过程序显式控制,用于从表中取出多行数据,并将多行数据一行一行的单独进行处理.

     

             四,属性:

    属性

    注释

    %rowcount 

     SQL影响的行数

    %found

     Boolean值,是否还有数据

    %notfound

    Boolean值,是否已无数据

    %isopen

    游标是否打开

        当然如果我们想获得隐式游标的属性,通过%前边加上SQL即可得到。例如SQL%rowcount.

     

            五,游标简单认识了,我们来看看游标的具体使用:

               1,先看一下简单的使用游标四步骤:

    步骤

    关键词

    说明

    1

    DECLAREcursor

    声明游标,创建一个命名的查询语句

    2

    Open

    打开游标

    3

    Fetch

    取出游标中的一条记录装入变量

    4

    Close

    释放游标

     

              2,当然游标中可以存放一条数据,也可以存放多条数据,后者是我们用游标,前者我们通过PL/SQL语句即可完成的,这样我们在这里就必须用到循环结构了,在Oracle数据库中我们可以使用while……loop……end loop , for…… loop……end looploop……end loop。在这里需要提出的是,for循环结构在Oracle中被简化了,我们只需要声明和使用即可。看下边这个例子吧:

      a,whlie循环结构的:

    declare  
      --定义记录类型的变量  
      v_user user%rowtype;  
      --1,利用cursor关键字声明游标  
      cursor user_cur is  
        select * from user;  
    begin  
      --2,打开游标  
      open user_cur;  
      --3,利用fetch读取数据  
      fetch user_cur  
        into v_user;  
      while user_cur%found loop  
        dbms_output.put_line(v_user.userName);  
        fetch user_cur  
          into v_user;  
      end loop;  
      --4,释放游标  
      close user_cur;  
    end;  
    View Code

          b,简化的for结构循环:

    declare  
      --1,利用cursor关键字声明游标  
      cursor user_cur is  
        select * from user;  
    begin  
      --2,直接使用,Oracle会自动打开和关闭等操作。  
       for v_user in user_cur loop  
           dbms_output.put_line(v_user.userName);  
        end loop  
    end;  
    View Code

     这里就介绍这两种的类型,loop的和这都差不多。

              3,最后在这里再学习一下带参数的游标,也是就和我们但参数的类是一样的,只不过一个用在了数据库中,一个用在了编程语言中。

    declare  
      --定义记录类型的变量  
      v_User user%rowtype;  
      --1,利用cursor关键字声明带参数的游标  
      cursor user_Cur(v_UserNo number) is  
        select * from user where  userNo=v_UserNo;  
    begin  
      --2,打开带参数的游标,使之更加灵活 。  
      open user_Cur(1012);  
      --3,利用fetch读取数据  
      loop  
           fetch user_Cur into v_User;  
           exit when user_Cur%notfound;  
           dbms_output.put_line(v_user.userName);  
      end loop;  
      --4,释放游标  
      close user_Cur;  
    end;  
    View Code

    综上为游标的简单学习,回想过去的学习,可以发现游标可以和datatable很相似,为了增加灵活性,它和类也有非常相似的功能。所以米老师曾经告诉我们的语言是相通的,每一种事也是相同的。就例如,JAVA.NET开发,SQL ServerOracle一样,学通了一门,其它的转向都是非常快的。

    注:本章部分引用 :数据库——游标

  • 相关阅读:
    测试sql语句性能,提高执行效率
    js积累
    如何提高AJAX客户端响应速度
    视频代码
    网页视频播放器收集
    WinForm软件开机自动启动详细方法
    JS时间格式化函数
    (转)CSS+DIV float 定位
    CSS+DIV 布局三种定位方式
    CSS+DIV布局初练—DIV元素必须成对出现?
  • 原文地址:https://www.cnblogs.com/mhq-martin/p/8184518.html
Copyright © 2020-2023  润新知