触发器和存储过程

存储过程是数据库编程里面最重要的表现方式了。 

  呵呵,这里我要提到上次说道的:我拒绝使用触发器。这里我要开始猛批一顿触发器了。

  在SQL 2000里,说实话,我实在找不出触发器可以存在的理由。回忆一下:触发器是一种特殊的存储过程。它在一定的事件(Insert,Update,Delete 等)里自动执行。我建议使用sp和级联来代替触发器。

  在SQL 7 里面,触发器通常用于更新、或删除相关表的数据,以维护数据的完整。SQL 7里面,没有级联删除和级联修改的功能。 只能建立起关系。既然SQL 2000里面提供了级联,那么触发器就没有很好的存在理由。更多的情况下是作为一个向下兼容的技术而存在。

  当然,也有人喜欢把触发器作为处理数据逻辑,甚至是业务逻辑的自动存储过程。 这种方法并不足取。这里列举以下使用触发器的一些坏处:

 a、“地下”运行 。
   触发器没有很好的调试、管理环境。调试一段触发器,要比调试一段sp更耗费时间与精力。

 b、类似于goto语句。(过分自由的另外一个说法是:无政府主义!)
   一个表,可以写入多个触发器,包括同样for Update的10个触发器!同样for Delete的10个触发器。也就是说,你每次要对这个表进行写操作的时候,你要一个一个检查你的触发器,看看他们是做什么的,有没有冲突。
   或许,你会很牛B的对我说:我不会做那么傻B的事情,我记得住我做了些什么!3个月以后呢?10个月以后呢?你还会对我说你记得住么?
 c、嵌套触发器、递归触发器
   你敢说你这么多的触发器中不会存在Table1更新了Table2表,从而触发Table2表更新TAble3,TAble3的触发器再次触发Table1更新Table2…… ??
   或许还会发生这种情况:你的程序更新了Table1.Fd1,触发器立马更新Table1.fd1,再次触发事件,触发器再次更新Table1.fd1……

   当然,SQL Server可以设置和避免应用程序进入死循环,可是,得到的结果,或许就不是你想要的。
 
 …… 
  我想不出触发器更多的坏处了,因为我早就抛弃了它。算了,不批它了,酸是各人爱好把!我建议使用完全存储过程来实现数据逻辑和事务逻辑!

  先讲讲sp的编写格式(我个人的编程习惯)。良好的习惯有助于日后的维护。


  Create Proc spBuyBook(           --@@存储过程头,包括名字、参数、说明文档
   @iBookID int,   --书的ID       --@@参数
   @iOperatorID int  --操作员ID
  )
  -------------------------------------------------------  @@说明文档
  --Name : spBuyBook                    @@名字   
  --func : 购买一本书的业务逻辑              @@存储过程的功能           
  --Return: 0,正确;-1,没找到该书;-2,更新Book表出错;-3..... @@返回值解释
  --Use  : spDoSomething,spDoSomething2....        @@引用了那些外部程序,比如sp,fn,vw等
  --User : 懒虫                      @@该存储过程的使用者
  --Author: 懒虫 # SapphireStudio (www.chair3.com)     @@作者
  --Date : 2003-5-4                    @@最后更新日期
  --Memo : 临时写写的,给大家作个Sample。没有调试阿。   @@备注
  -------------------------------------------------------
  As                            --@@程序开始
  begin
   
   Begin Tran                       --@@激活事务
    Exec spDoSomething                  --@@调用其他sp
    if @@Error<>0                    --@@判断是否错误
    begin
     Rollback Tran                   --@@回滚事务
     RaisError ('SQL SERVER,spBuyBook: 调用spDoSomeThing发生错误。', 16, 1) with Log --@@记录日志
     Return -1                     --@@返回错误号
    end 
  
   .... --更多其他代码

   Commit Tran                      --@@提交事务
  end
        
  妈 的我怎么这么背啊我??什么时候不死机,偏偏在这时!!丢了不少……:(:(
  下面默哀3分钟……

   1……
   2……
   3……
  
  好了,继续!回忆刚才写的内容ing ……

  AA、存储过程的几个要素: a. 参数 b.变量 c.语句 d.返回值 e.管理存储过程
  BB、更高级的编程要素:  a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令

  AA.a 参数: 知识要点包括:输入参数,输出参数,参数默认值

   Sample:

    Create Proc spTest(
     @i int =0 ,    --输入参数
     @o int output   --输出参数
    )
    As
     Set @o=@i*2    --对输出参数付值
     
   Use the Sample:

    Declare @o int
    Exec spTest 33,@o output
    Select @o          --此时@o应该等于33*2=66。

   ----------------------------------------------------------------------
   以上代码没有测试,顺手写写的。希望不会出错:) 
                          --懒虫 # SapphireStudio

         精彩世界,尽在3腿软件网(www.chair3.com)!!
   -----------------------------------------------------------------------                       
  AA.b 变量:AA.a中已经有声明变量的例子了,就是Declare @o int
  AA.c 语句:在Sql Server 中,如果仅仅使用标准SQL语句将是不可想象的,通常认为,标准的SQL 语句就那么几条,如:   
        Select, Update, Delete
       因此,我们需要引入更多更强大的功能,那就是T-SQL语句:
  
       赋值语句:Set     
       循环语句:While 
       分支语句:if , Case ( Case语句不能单独使用,与一般高级语言的不同)
       
       一起举个例子吧:
       Sample :
       
       Declare @i int
       Set @i=0

       While @i<100
       begin

        if @i<=20
        begin

         Select Case Cast(@i As Float)/2 When (@i/2) then Cast(@i As varchar(3)) + '是双数'
                         else       Cast(@i As varchar(3)) + '是单数'

             end

        end

        Set @i=@i+1
       end 
     
       ----------------------------------------------------------------------
       以上代码判断20之内的单数与双数。
                             --懒虫 # SapphireStudio
             精彩世界,尽在3腿软件网(www.chair3.com)!!
       -----------------------------------------------------------------------
  AA.d 返回值
    Sample:

     Create Proc spTest2
     As
      Return 22

    Use the Sample
     Declare @i int
     Exec @i=spTest2
     Select @i 

  AA.e 管理存储过程: 创建,修改,删除。
    分别为:
    Create Proc ... , Alter Proc ... , Drop Proc ...

 BB、更高级的编程要素:  a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令
<think>好的,我现在需要帮用户弄清楚MySQL触发器存储过程的用法以及它们的区别。首先,我得回忆一下自己对这两个概念的理解,并确认是否正确。 触发器,我记得是在特定数据库操作(比如INSERT、UPDATE、DELETE)发生时自动执行的存储程序。用户提到的引用[1]中也提到,触发器分为三种类型:INSERT、UPDATEDELETE触发器触发器的执行是自动的,不需要手动调用,所以可能用于数据验证、审计日志或是维护数据一致性等场景。比如,当插入一条新记录时,触发器可以自动更新某个统计表。 存储过程则不同,引用[3]提到,存储过程需要显式地通过CALL或EXECUTE来调用,可以包含复杂的逻辑,比如控制结构(if、while等),并且能返回结果。存储过程更像是一个预定义的函数,把一系列SQL语句封装起来,方便重用。例如,处理订单时可能需要多个步骤,用存储过程可以把这些步骤集中管理,提高效率并减少网络传输,因为应用程序只需调用一次存储过程而不是发送多个SQL语句。 接下来是区别部分。触发器存储过程的主要区别在于触发方式用途。触发器是事件驱动的,自动触发,而存储过程需要显式调用。触发器的应用场景更多是数据变动相关的自动处理,而存储过程用于封装复杂的业务逻辑。此外,触发器不能直接返回结果,而存储过程可以返回查询结果或输出参数。引用[3]还指出,存储过程可以包含控制结构,这可能比触发器更灵活。 还要考虑它们的创建管理方式。触发器的创建语法是CREATE TRIGGER,需要指定触发事件时机(BEFORE/AFTER)。而存储过程用CREATE PROCEDURE,可以定义参数返回类型。触发器可能对性能有影响,尤其是在处理大量数据时,因为每个相关操作都会触发执行。而存储过程的性能优势在于减少多次数据库交互,但设计不当也可能成为瓶颈。 用户可能还关心实际应用中的选择。比如,何时用触发器,何时用存储过程。例如,审计日志适合用触发器,因为需要在数据变动时自动记录;而复杂的业务逻辑如月度报表生成可能更适合存储过程,按需调用。 需要验证自己的理解是否正确,比如触发器的执行权限、存储过程能否处理事务等。根据引用[2],存储过程中的变量作用域在过程内部,类似Java的方法局部变量,而触发器中变量的使用可能受限,因为触发器通常特定的表事件绑定。 最后,用户可能希望知道使用它们的最佳实践潜在问题,比如触发器的递归触发风险,存储过程的调试维护难度。这些都是需要提及的。</think>### MySQL触发器存储过程的用法及区别解析 #### 一、触发器(Trigger)的用法 1. **定义与触发条件** 触发器是一种与表事件绑定的特殊存储程序,在特定操作($INSERT$、$UPDATE$、$DELETE$)执行时**自动触发**。例如: ```sql CREATE TRIGGER audit_log AFTER INSERT ON orders FOR EACH ROW BEGIN INSERT INTO log_table VALUES (NEW.order_id, NOW()); END; ``` 此触发器会在`orders`表插入数据后自动记录日志[^1]。 2. **类型与时机** - 支持`BEFORE`(操作前触发)`AFTER`(操作后触发)两种时机 - 分为三种类型:`INSERT`触发器、`UPDATE`触发器、`DELETE`触发器 3. **典型应用场景** - 数据审计(如记录修改痕迹) - 级联更新(如更新库存时自动调整统计表) - 约束补充(如实现复杂业务规则校验) --- #### 二、存储过程(Stored Procedure)的用法 1. **定义与调用方式** 存储过程是一组预编译的SQL语句集合,需通过`CALL`命令显式调用: ```sql CREATE PROCEDURE CalculateSales(IN year INT) BEGIN SELECT SUM(amount) FROM sales WHERE YEAR(order_date) = year; END; -- 调用示例 CALL CalculateSales(2023); ``` 支持输入/输出参数,可返回查询结果[^3]。 2. **功能特性** - 支持变量声明(如`DECLARE total INT DEFAULT 0;`) - 支持流程控制(如`IF...THEN`、`WHILE`循环) - 可嵌套调用其他存储过程[^2] 3. **典型应用场景** - 复杂业务逻辑封装(如订单结算流程) - 批量数据处理(如定期统计报表生成) - 权限控制(通过存储过程限制直接表访问) --- #### 三、核心区别对比 | **特性** | **触发器** | **存储过程** | |------------------------|-----------------------------------|---------------------------------| | 触发方式 | 自动由表事件触发 | 需显式调用`CALL`执行 | | 返回值 | 不能直接返回结果 | 可通过`OUT`参数或结果集返回数据 | | 事务控制 | 默认在触发语句的事务中执行 | 可独立声明事务(`BEGIN TRANSACTION`)| | 应用场景 | 数据变更的联动操作 | 复杂业务逻辑封装 | | 性能影响 | 高频操作可能引发级联性能问题 | 预编译减少解析开销,但需注意设计合理性 | --- #### 四、选择建议 1. **优先使用触发器** - 需要保证数据一致性的自动化操作(如审计日志) - 简单级联更新(如更新订单状态后同步库存) 2. **优先使用存储过程** - 多步骤复杂业务逻辑(如用户注册流程包含校验、插入、发邮件) - 需要复用或对外提供标准化接口的操作 3. **注意事项** - 避免在触发器中嵌套复杂逻辑,可能导致性能瓶颈 - 存储过程版本管理需谨慎,修改可能影响多个调用点 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值