数据库程序设计中的约束、触发器和存储过程

上篇博客中所说的对于表操作的几种限制少分析了触发器。这次从对表设计的角度来着重分析约束和触发器的关系,并进一步扩展比较触发器和存储过程。但在看该篇博客前强烈建议大家好好读下我的上一篇博客《约束与数据库对象规则、默认值的探究

  首先,从图上来比较三者的关系:

  触发器不仅能够保证数据的完整性,而且还可以封装复杂的T-SQL逻辑处理语句,在功能上类似于存储过程,所以触发器又是一种特殊的存储过程。但是存储过程的执行是我们使用Exec主观调用的,而触发器是经过一种事件操作后自动被调用的。

  在拆开分析约束和触发器、触发器和存储过程之前我们穿插点外话。在数据库程序设计中包含有多种数据模型:

  20世纪60年代后期,在文件系统基础上发展起来的层次模型、网状模型和关系模型等传统数据模型;20世纪70年代后期产生的E-R数据模型;20世纪80年代以来又相继推出面向对象数据模型、基于逻辑的数据模型等新的模型。下图关系数据库中的关键术语和语义对象模型及ER图中使用的术语之间的映射关系:

  上面的内容只存在了解而已,不用深究。

  数据完整性和业务规则

  在上篇博客我已经简单介绍了数据完整性,接下来我们详细说下数据完整性和业务规则。

  一、数据完整性

  数据完整性=可靠性+准确性,这里我们要清楚一下两点:

  ● 数据存放在表中

  ● 创建表的时候,就应当保证以后数据输入是正确的(错误的数据、不符合要求的数据不允许输入)

  为了保证数据的完整性我们经常使用完整性约束来确保数据的完整性。数据完整性,主要包括下面四部分:

接下来我们从代码中认识下几种触发器。

       --#Update型触发器
 If exits(select name from sysobjects where name=’tgr_update’)
 Drop trigger tgr_update
 Go
 Create trigger tgr_update on student
  for update
 As
  If (Update(student_ID))
   Print ‘更改成功!’
  Else
   Begin 
    Raiserror(‘系统提示:更新发生错误’,16,1)
    Rollback tran
   End
 Go
 --测试
 Update student set student_ID=10002 where student_ID=10001      

  注意:在创建触发器时,创建触发器必须是批处理的第一行,存储过程也是如此。

     --# instead of 触发器
          if (object_id('tgr_classes_inteadOf', 'TR') is not null)
           drop trigger tgr_classes_inteadOf
         go
         create trigger tgr_classes_intead Of
               on classes
         instead of delete/*, update, insert*/
         as
            declare @id int, @name varchar(20);
            --查询被删除的信息,病赋值
              select @id = id, @name = name from deleted;
            print 'id: ' + convert(varchar, @id) + ', name: ' + @name;
            --先删除student的信息
              delete student where cid = @id;
            --再删除classes的信息
              delete classes where id = @id;
            print '删除[ id: ' + convert(varchar, @id) + ', name: ' + @name + ' ] 的信息成功!';
         go
         --test
         select * from student order by id;
         select * from classes;
         delete classes where id = 7;
 

  # 启用、禁用触发器

     --禁用触发器
       disable trigger tgr_message on student;
     --启用触发器
       enable trigger tgr_message on student;
<P style="BACKGROUND: white"><SPAN style="COLOR: #4b4b4b">  # </SPAN><SPAN style="COLOR: #4b4b4b">显示自定义消息</SPAN><SPAN style="COLOR: #4b4b4b">raiserror</SPAN></P>
   if (object_id('tgr_message', 'TR') is not null)
        drop trigger tgr_message
   go
   create trigger tgr_message
        on student
      after insert, update
   as raisError('tgr_message触发器被触发', 16, 10);
   go
   --test
   insert into student values('lily', 22, 1, 7);
   update student set sex = 0 where name = 'lucy';
   select * from student order by id;
<SPAN style="BACKGROUND-COLOR: #ffffff; FONT-FAMILY: Arial"></SPAN>

  二、业务规则

  业务规则听起来很难理解,当然它也是值得我们深究东西,通俗的讲它其实是符合实际条件。如:某商店规定一个售货员在一个月内售出10个以上的热浴盆,那么奖励2000元;某公司的订单上必须含有客户的姓名和联系方式等等,这些都是简单的业务规则。从数据库的角度看,业务规则就是约束。

  约束和触发器

  MS SQL Server提供了两种主要的机制进行强制业务规则和数据的完整性:约束和触发器。在作用上约束支持的触发器都可以实现,它们两者是相容的关系,如下图。虽然两者在作用关系上有重合的地方,但是相较两者的执行效率和维护难易来说,触发器是远远不如约束的。所以约束能实现的情况下编程人员是不会选择触发器的。

  一、约束,上篇博客我已经着重讲解了约束的概念,这里不再深究。

  SQL Server中存在五种约束:

  ● 约束的目的:确保表中数据的完整型

  ● 常用的约束类型:

  – 主键约束(Primary Key Constraint):要求主键列数据唯一,并且不允许为空

  – 唯一约束(Unique Constraint):要求该列唯一,允许为空,但只能出现一个空值。

  – 检查约束(Check Constraint):某列取值范围限制、格式限制等,如有关年龄的约束

  – 默认约束(Default Constraint):某列的默认值,如我们的男性学员较多,性别默认为“男”

  – 外键约束(Foreign Key Constraint):用于两表间建立关系,需要指定引用主表的那列

  二、触发器,首先在下表中来看触发器的基本结构。

  触发器是一种对表进行插入、删除、更改的时候自动运行的特殊的存储过程。它一般用在比核查约束更为复杂的约束中。但能用约束实现的功能,一般不用触发器。

  触发器的应用种类繁多上面的几个示例都是比较常用的,当然最好的熟练方法就是多用,多练。

  触发器和存储过程

  触发器是一种特殊的存储过程,不是由用户直接调用。而存储过程是一组T-SQL语句,经过编译后可以被多次调用。类似于其它编程语言中的过程。它可以接收输入参数、输出参数、返回单个或多个结果集以及返回值。

  存储过程分为三类:

  1、系统存储过程:以sp_开头,用来进行系统的各项设定、取得信息。相关管理工作,如 sp_help就是取得指定对象的相关信息

  2、扩展存储过程  以XP_开头,用来调用操作系统提供的功能

  exec master..xp_cmdshell 'ping 10.8.16.1'

  3、用户自定义的存储过程,这是我们所指的存储过程

  常用格式

Create PRocedure procedue_name
   [@parameter data_type][output]
   [with]{recompile|encryption}
   as
        sql_statement
--解释:  
--output:表示此参数是可传回的
--with {recompile|encryption}
--recompile:表示每次执行此存储过程时都重新编译一次
--encryption:所创建的存储过程的内容会被加密

  举例:

  有如下表量表

  result_Info:

  Student_Info

  #创建返回参数的存储过程

If exists(select name from sysobjects where name=’proc_return’ and type=’P’)
 Drop proc proc_return
 Go
 Create proc proc_return  
@param1 int,
   @param2 char(10),
   @param3 char(10)
   @param4 int output
 With encryption    --加密
 As
  Insert into student_Info(student_ID,name,result) values(@param1,@param2,@param3)
  Select @param4=sum(result) from student_Info
  Print ‘总分为:’ & convert(char,@param)
 Go
 --调用测试
 Declare @sumresult int
 Exec proc_return 12,’王刚’,80,@sumresult
 Go

  存储过程的3种传回值:

  1、以Return传回整数

  2、以output格式传回参数

  3、Recordset

  传回值的区别:

  output和return都可在批次程式中用变量接收,而recordset则传回到执行批次的客户端中

  #创建一个存储过程,实现将表一和表二合并,该表只含Student_ID、Name、sex、result,将临时表存放在存储过程中。

If exists(select name from sysobjects where name=’proc_save’ and type=’P’)
 Drop proc proc_return
 Go
 Create proc proc_save
 As 
  Select r.student_ID,r.Name,r.result,s.sex into #temptable from result r inner join student s on                 r.student_ID=s.student_ID
 If @@error=0
  Print ‘Successed’
 Else
  Print ‘Failed’
 Go

  存储过程的应用类型还有很多,这里我只介绍了在编程时常用的两种。

  总结

  在进行数据库程序设计时,数据的完整性是编程人员必须要考虑的,但是有时候这些知识的细节却让我们纠结的很,搞不清改用哪个。总之吧:能用存储过程实现的不用触发器;能用约束实现的不用触发器,约束和存储过程用哪个都可以。

  有些不懂得地方在SQL Server中按F1,在SQL Server联机丛书的索引中查找可以解决我们的一切矛盾。

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-12-24 23:09:46

数据库程序设计中的约束、触发器和存储过程的相关文章

SQL触发器在保持数据库完整性中的实际应用

触发器是SQL Server数据库应用中一个重要工具,是一种特殊类型的存储过程,应用非常广泛.一般存储过程主要通过存储过程名而被直接调用,触发器则是通过事件触发执行.触发器基于一个表来创建并和一个或多个数据修改操作(插入.更新或删除)相关联,可视作表的一部分.触发器与数据库中的表紧密相关,比如当对表执行INSERT.UPDATE或DELETE操作时,触发器就会自动执行. SQL Server 包括两大类触发器:DML 触发器和 DDL 触发器.其中DDL 触发器是 SQL Server 2005

SQL Server 2005中使用DDL触发器监控数据库变化

添加,删除或修改数据库的对象,一旦误操作,可能会导致大麻烦,需要一个 数据库管理员或开发人员对相关可能受影响的实体进行代码的重写. 为了在数据库结构发生变动而出现问题时,能够跟踪问题,定位问题的根源, 我们可以利用DDL触发器来记录类似"用户建立表"这种变化的操作, 这样可以大大减轻跟踪和定位数据库模式的变化的繁琐程度. 1.DDL触发器介绍 DDL 触发器是一种特殊的触发器,它在响应数据定义语言 (DDL) 语句时触发 .它们可以用于在数据库中执行管理任务,例如,审核以及规范数据库操

在SQL触发器或存储过程中获取在程序登录的用户_MsSql

实现一个AuditLog的功能,是B/S结构专案. 每个用户可以登录系统,在程序中操作数据(添加,更新和删除)需要实现记录操作跟踪.是谁添加,更新和删除的,这些信息将会插入至AuditLog表中. 一般情况之下,在SQL的触发器中,只能取到(SQL验证sa:Windows验证Domain\xxx).这些用户名,达不到效果,不能真正反映到是谁操作的. 下面是让你清楚,怎样实现在SQL触发器或存储过程中获取在程序登录的用户,是在插入,更新或删除的存储过程,把登录程序当前用户传入进去.在存储过程中,再

在SQL触发器或存储过程中获取在程序登录的用户

实现一个AuditLog的功能,是B/S结构专案. 每个用户可以登录系统,在程序中操作数据(添加,更新和删除)需要实现记录操作跟踪.是谁添加,更新和删除的,这些信息将会插入至AuditLog表中. 一般情况之下,在SQL的触发器中,只能取到(SQL验证sa:Windows验证Domain\xxx).这些用户名,达不到效果,不能真正反映到是谁操作的. 下面是让你清楚,怎样实现在SQL触发器或存储过程中获取在程序登录的用户,是在插入,更新或删除的存储过程,把登录程序当前用户传入进去.在存储过程中,再

Java数据库程序中的存储过程设计

程序|存储过程|设计|数据|数据库 本文阐述了怎么使用DBMS存储过程.阐述了使用存储过程的基本的和高级特性,比如返回ResultSet.本文假设你对DBMS和JDBC已经非常熟悉,也假设你能够毫无障碍地阅读其它语言写成的代码(即不是Java的语言),但是,并不要求你有任何存储过程的编程经历. 存储过程是指保存在数据库并在数据库端执行的程序.你可以使用特殊的语法在Java类中调用存储过程.在调用时,存储过程的名称及指定的参数通过JDBC连接发送给DBMS,执行存储过程并通过连接(如果有)返回结果

浅谈ASP程序设计中数据库文件调用的捷径

程序|设计|数据|数据库 引言 本文针对ASP程序设计中最基础.也是最关键的部分"数据库文件的调用"进行说明,同时谈谈ASP程序设计中数据库文件调用的一些技巧. ASP简介 ASP(Active Server Pages)是微软于1996年推出的Web应用程序开发技术,它是一种脚本语言.ActiveX组件及HTML语言等的综合,微软把它描述为"一个服务器的脚本环境,在这里可以生成和运行动态的.交互的.高性能的Web服务器应用程序".其主要功能是为生成动态的.交互式的

数据库设计中的14个技巧

1. 原始单据与实体之间的关系  可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体.在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单据对应多个实体,或多张原始单据对应一个实体.这里的实体可以理解为基本表.明确这种对应关系后,对我们设计录入界面大有好处.  [例1]:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表.社会关系表.工作简历表.这就是"一张原始单据对应多个实体"的典型例子.  2. 主键

SQL Server数据库程序设计知识总结

SQL Server是由Microsoft开发和推广的关系数据库管理系统(DBMS),它最初是由Microsoft.Sybase和Ashton-Tate三家公司共同开发的,并于1988年推出了第一个OS/2版本.它只是众多关系数据库管理系统的一种,其它的关系数据库管理系统还有Server,Oracle,DB/2,Sybase,Informix:关系数据库:Access,FoxPro,Dbase等.如今,数据库已经变成学习软件开发的核心课程之一,几乎绝大部分软件都涉及到数据库,很多数据必须存在数据

数据库设计中的小经验

http://www.cnblogs.com/guojingyang/archive/2008/11/26/1341406.html   1. 原始单据与实体之间的关系 可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体.在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体.这里的实体可以理解为基本表.明确这种对应关系后,对我们设计录入界面大有好处.[例1]:一份员工履历资料,在人力资源信息系统