数据库存储过程实例分析

发布时间:2011-10-03 01:27:26  浏览次数:3760
 

数据库存储过程

  数据库存储过程的实质就是部署在数据库端的一组定义代码以及SQL。将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。   利用SQL的语言可以编写对于数据库访问的存储过程,其语法如下:   CREATE PROC[EDURE] procedure_name [;number]   [   {@parameter data_type} ][VARYING] [= default] [OUTPUT]   ]   [,...n]   [WITH    {   RECOMPILE    | ENCRYPTION    | RECOMPILE, ENCRYPTION   }   ]   [FOR REPLICATION]   AS   sql_statement [...n]   [ ]内的内容是可选项,而()内的内容是必选项,   例:若用户想建立一个删除表tmp中的记录的存储过程Select_delete可写为:   Create Proc select_del As    Delete tmp    例:用户想查询tmp表中某年的数据的存储过程   create proc select_query @year int as   select * from tmp where year=@year   在这里@year是存储过程的参数   例:该存储过程是从某结点n开始找到上层的父亲结点,这种经常用到的过程可以由存储过程来担当,在网页中重复使用达到共享。   空:表示该结点为顶层结点   fjdid(父结点编号)    结点n 非空:表示该结点的父亲结点号   dwmc(单位名称)   CREATE proc search_dwmc @dwidold int,@dwmcresult varchar(100) output   as    declare @stop int   declare @result varchar(80)   declare @dwmc varchar(80)   declare @dwid int   set nocount on   set @stop=1   set @dwmc=""   select @dwmc=dwmc,@dwid=convert(int,fjdid) from jtdw where id=@dwidold    set @result=rtrim(@dwmc)   if @dwid=0    set @stop=0   while (@stop=1) and (@dwid<>0)   begin   set @dwidold=@dwid   select @dwmc=dwmc,@dwid=convert(int,fjdid) from jtdw where id=@dwidold   if @@rowcount=0    set @dwmc=""   else   set @result=@dwmc+@result   if (@dwid=0) or (@@rowcount=0)    set @stop=0   else   continue   end   set @dwmcresult=rtrim(@result)   使用exec pro-name [pram1 pram2.....]

SQL Server中执行存储过程

  sql语句执行的时候要先编译,然后执行。存储过程就是编译好了的一些sql语句。用的时候直接就可以用了。   在SQL Server的查询分析器中,输入以下代码:   declare @tot_amt int   execute order_tot_amt 1,@tot_amt output   select @tot_amt   以上代码是执行order_tot_amt这一存储过程,以计算出定单编号为1的定单销售金额,我们定义@tot_amt为输出参数,用来承接我们所要的结果。

Oracle中的存储过程

  1.创建过程   与其它的数据库系统一样,Oracle的存储过程是用PL/SQL语言编写的能完成一定处理功能的存储在数据库字典中的程序。   语法:   create [or replace] procedure procedure_name   [ (argment [ { in| in out }] type,   argment [ { in | out | in out } ] type   { is | as }   <类型.变量的说明>   ( 注: 不用 declare 语句 )   Begin   <执行部分>   exception   <可选的异常处理说明>   end;   1.1 这里的IN表示向存储过程传递参数,OUT表示从存储过程返回参数。而IN OUT 表示传递参数和返回参数;   1.2 在存储过程内的参数只能指定参数类型;不能指定长度;   1.3 在AS或IS 后声明要用到的变量名称和变量类型及长度;   1.4 在AS或IS 后声明变量不要加declare 语句。   2.使用过程   存储过程建立完成后,只要通过授权,用户就可以在SQLPLUS 、Oracle开发工具或第三方开发工具来调用运行。Oracle 使用EXECUTE 语句来实现对存储过程的调用。   语法:   EXEC[UTE] procedure_name( parameter1, parameter2…);   3.开发过程   目前的几大数据库厂商提供的编写存储过程的工具都没有统一,虽然它们的编写风格有些相似,但由于没有标准,所以各家的开发调试过程也不一样。下面编写PL/SQL存储过程、函数、包及触发器的步骤如下:   3.1 编辑存储过程源码使用文字编辑处理软件编辑存储过程源码,要用类似WORD 文字处理软件进行编辑时,要将源码存为文本格式。   3.2 对存储过程程序进行解释在SQLPLUS或用调试工具将 存储过程程序进行解释;   在SQL>下调试,可用start 或get 等Oracle命令来启动解释。如:   SQL>start c:\stat1.sql   如果使用调试工具,可直接编辑和点击相应的按钮即可生成存储过程。[1]   3.3 调试源码直到正确我们不能保证所写的存储过程达到一次就正确。所以这里的调试是每个程序员必须进行的工作之一。在SQLPLUS下来调试主要用的方法是:   1.使用 SHOW ERROR命令来提示源码的错误位置;   2.使用 USER_ERRORS 数据字典来查看各存储过程的错误位置。   3.4 授权执行权给相关的用户或角色如果调试正确的存储过程没有进行授权,那就只有建立者本人才可以运行。所以作为应用系统的一部分的存储过程也必须进行授权才能达到要求。 在SQLPLUS下可以用GRANT命令来进行存储过程的运行授权。   语法:   GRANT system_privilege | role TO user | role | PUBLIC   [WITH ADMIN OPTION]      GRANT object_privilege | ALL column ON schema.object   TO user | role | PUBLIC WITH GRANT OPTION   其中:   system_privilege: 系统权限   role: 角色名   user: 被授权的用户名   object_privilege: 所授予的权限名字,可以是   ALTER   DELETE   EXECUTE   INDEX   INSERT   REFERENCES   SELECT   UPDATE   Column: 列名   schema: 模式名   object: 对象名   4.数据字典   USER_SOURCE 用户的存储过程、函数的源代码字典   DBA_SOURCE 整个系统所有用户的存储过程、函数的源代码字典   ALL_SOURCE 当前用户能使用的存储过程(包括其她用户授权)、函数的源代码字典   USER_ERRORS 用户的存储过程、函数的源代码存在错误的信息字典   

临时表

  (针对SQL2000/2005)   可以创建本地和全局临时表。本地临时表仅在当前会话中可见;全局临时表在所有会话中都可见。   本地临时表的名称前面有一个编号符 (#table_name),而全局临时表的名称前面有两个编号符 (##table_name)。   SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的名称引用临时表:   CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)   INSERT INTO #MyTempTable VALUES (1)   如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则 SQL Server 必须能够区分由不同用户创建的表。为此,SQL Server 在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdb 数据库的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的表名 table_name 不能超过 116 个字符。   除非使用 DROP TABLE 语句显式除去临时表,否则临时表将在退出其作用域时由系统自动除去:   当存储过程完成时,将自动除去在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。   所有其它本地临时表在当前会话结束时自动除去。   全局临时表在创建此表的会话结束且其它任务停止对其引用时自动除去。任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。换言之,当创建全局临时表的会话结束时,后一条引用此表的 Transact-SQL 语句完成后,将自动除去此表。

触发器

  1.触发器的概念及作用   触发器是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。当对某一表进行诸如Update、 Insert、 Delete 这些操作时,SQL Server 就会自动执行触发器所定义的SQL 语句,从而确保对数据的处理必须符合由这些SQL 语句所定义的规则。   触发器的主要作用就是其能够实现由主键和外键所不能保证的复杂的参照完整性和数据的一致性。除此之外,触发器还有其它许多不同的功能:   (1) 强化约束(Enforce restriction)   触发器能够实现比CHECK 语句更为复杂的约束。   (2) 跟踪变化Auditing changes   触发器可以侦测数据库内的操作,从而不允许数据库中未经许可的指定更新和变化。   (3) 级联运行(Cascaded operation)。   触发器可以侦测数据库内的操作,并自动地级联影响整个数据库的各项内容。例如,某个表上的触发器中包含有对另外一个表的数据操作(如删除,更新,插入)而该操作又导致该表上触发器被触发。   (4) 存储过程的调用(Stored procedure invocation)。   为了响应数据库更新,触发器可以调用一个或多个存储过程,甚至可以通过外部过程的调用而在DBMS( 数据库管理系统)本身之外进行操作。   由此可见,触发器可以解决高级形式的业务规则或复杂行为限制以及实现定制记录等一些方面的问题。例如,触发器能够找出某一表在数据修改前后状态发生的差异,并根据这种差异执行一定的处理。此外一个表的同一类型(Insert、 Update、 Delete)的多个触发器能够对同一种数据操作采取多种不同的处理。   总体而言,触发器性能通常比较低。当运行触发器时,系统处理的大部分时间花费在参照其它表的这一处理上,因为这些表既不在内存中也不在数据库设备上,而删除表和插入表总是位于内存中。可见触发器所参照的其它表的位置决定了操作要花费的时间长短。   2.触发器的种类   SQL Server 2000 支持两种类型的触发器:AFTER 触发器和INSTEAD OF 触发器。其中AFTER 触发器即为SQL Server 2000 版本以前所介绍的触发器。该类型触发器要求只有执行某一操作(Insert Update Delete) 之后,触发器才被触发,且只能在表上定义。可以为针对表的同一操作定义多个触发器。对于AFTER 触发器,可以定义哪一个触发器被先触发,哪一个被后触发,通常使用系统过程sp_settriggerorder 来完成此任务。   INSTEAD OF 触发器表示并不执行其所定义的操作(Insert、 Update、 Delete),而仅是执行触发器本身。既可在表上定义INSTEAD OF 触发器,也可以在视图上定义INSTEAD OF 触发器,但对同一操作只能定义一个INSTEAD OF 触发器。

常用格式

  Create procedure procedue_name   [@parameter data_type][output]   [with]{recompile|encryption}   as   sql_statement   解释:   output:表示此参数是可传回的   with {recompile|encryption}   recompile:表示每次执行此存储过程时都重新编译一次   encryption:所创建的存储过程的内容会被加密   如:   表book的内容如下   编号 书名 价格   001 C语言入门 $30   002 PowerBuilder报表开发 $52   实例1:查询表Book的内容的存储过程   create proc query_book   as   select * from book   go   exec query_book   实例2:   加入一笔记录到表book,并查询此表中所有书籍的总金额   Create proc insert_book   @param1 char(10),@param2 varchar(20),@param3 money,@param4 money output   with encryption ---------加密   as   insert into book(编号,书名,价格) Values(@param1,@param2,@param3)   select @param4=sum(价格) from book   go   执行例子:   declare @total_price money   exec insert_book '003','Delphi 控件开发指南',$100,@total_price   print '总金额为'+convert(varchar,@total_price)   go   存储过程的3种传回值:   1)、以Return传回整数   2)、以output格式传回参数   3)、Recordset   传回值的区别:   output和return都可在批次程式中用变量接收,而recordset则传回到执行批次的客户端中。   实例3:   设有两个表为Product,Order_,其表内容如下:   Product   产品编号 产品名称 客户订数   001 钢笔 30   002 毛笔 50   003 铅笔 100   Order_   产品编号 客户名 客户订金   001 南山区 $30   002 罗湖区 $50   003 宝安区 $4   请实现按编号为连接条件,将两个表连接成一个临时表,该表只含编号.产品名.客户名.订金.总金额,   总金额=订金*订数,临时表放在存储过程中   代码如下:   Create proc temp_sale   as   select a.产品编号,a.产品名称,b.客户名,b.客户订金,a.客户订数* b.客户订金 as总金额   into #temptable from Product a inner join Order_ b on a.产品编号=b.产品编号-----此处要用别名   if @@error=0   print 'Good'   else   print 'Fail'   go