`
starbhhc
  • 浏览: 658527 次
  • 性别: Icon_minigender_2
  • 来自: 深圳
社区版块
存档分类
最新评论

SQL学习之存储过程

阅读更多
1 存储过程的概念
    通常情况下,在客户-服务器体系结构中,运行在客户端的应用程序通过SQL对服务器端的数据库进行访问时,每一条SQL语句是分别地、一句一句地从客户端向服务器发出请求,然后数据库服务器再将结果一个一个地返回给应用程序。但是,有一些应用程序,涉及的服务器端数据库处理活动很多,而与用户的交互活动较少,在这种情况下,将有关数据库的处理活动以储存过程的形式放在数据库服务器上完成,则可以大大减轻网上传输流量,提高应用程序性能。储存过程的概念如下图所示。
    使用储存过程的应用程序具有以下优点:
A:减少网上传输流量;
B:改善服务器处理密集型应用的性能;
C:以访问数据库服务器特有的功能特性;
D:易于维护;
2 存储过程的程序结构
    一个完整的使用储存过程的应用程序由两部分组成:一是储存过程本身,它被存放在数据库服务器端并数据库服务器上运行;二是对存储过程进行调用的客户端应用程序,它在客户端上运行。客户端应用程序与服务器端储存过程分别运行在两个不同的进程空间中,并且有不同的功能划分。
    客户端应用程序的主要功能是:
    A:关数据结构和主变量定义、分配并初始化存储空间;
    B:与数据库进行连接;
    C:通过SQL CALL语句调用存储过程
    D:完成事务的提交(COMMIT)和回滚(ROLLBACK)(注:除非采用分布式工作单元,服务器端的存储过程也可以完成事务的提交和回滚);
    E:执行CONNECT RESET语句;
    服务器端储存过程的主要功能是:
    A:接收客户端应用程序传送的SQLCA和SQLDA等数据库结构;
    B:作为与客户端应用程序相同的事务在数据库服务器上运行;
    C:向客户端应用程序返回SQLCA和其它输出数据;
3 客户端应用程序
    客户端应用程序在使用CALL语句调用存储过程之前必须先执行几个步骤。首先,必须连接数据库,声明、分配并初始化SQLDA结构或宿主变量。
    提示:不要在数据库服务器上分配这些变量结构。数据库管理系统将根据客户端应用程序中的结构在服务器端自动分配所需的存储。
    客户端应用程序必须保证在调用存储过程之前已建立了数据库连接,否则,将会产生错误。
3.1 CALL 语句
     客户端应用程序可通过CALL语句向服务器发出存储过程调用请求。CALL的语法格式如下所示:
     CALL {(主变量1,…,主变量N)|USING DESCRIPTION 描述符名}
     CALL语句的作用是将调用参数通过一个SQLDA数据结构从客户端传送给服务器端的存储过程,存储过程执行后再将输出结果通过同一个SQLDA返回给客户端应用程序。
1.有关被调用存储过程的名称的规定
1)在客户端应用程序中,被调用的存储过程的名称既可以直接给出,也可以通过一个主变量给出。
2)如果被调用的存储过程的名称是直接给出的,则它必须是一个通常的标识符(identifier)并且长度不能超过254个字节。由于通常的标识符中不能含有空格或其它特殊字符,所以,如果被调用的存储过程的名称中必须包含有空格或其它特殊字符时,则只能使用主变量来给出其名称。
3)如果是通过主变量给出被调用的存储过程的名称,则使用的主变量必须是一个具有长度属性的字符串型的变量,并且其长度不能超过254个字节。
4)被调用的存储过程的名称可以采用下列几种格式:
    proname:表示要装入名为proname 的存储过程函数库并执行其中名为proname的函数;
    proname!funcname:表示要装入名为proname 的存储过程函数库并执行其中名为funcname的函数;
注:按照缺省方式,在基于UNIX的平台上,数据库管理系统将在INSTHOME/sqllib/function目录中查找被隔离的(fenced)存储过程函数库。而在Intel平台上,存储过程函数库的搜索位置则由操作系统环境变量LIBPATH说明。对于不加隔离的(unfenced)存储过程函数库,其搜索位置分别是INSTHOME/sqllib/ unfenced(基于UNIX的系统)或sqllibdllunfenced(基于Intel的系统)。
    绝对路径:如/home/user1/procname!funcname即表示要装入/home/user1目录下的名为proname 的存储过程函数库并执行其中名为funcname的函数;
2.通过宿主变量传递过程调用参数
以下是一段通过宿主变量传递过程调用参数的程序例子:
EXEC SQL BEGIN DECLARE SECTION;
char host_var1[15];
float host_var2;
short ind_var2;
long host_var3;
short ind_var3;
char procname[254] = “myproc”;
EXEC SQL END DECALRE SECTION;

strcopy(host_var1,”new data”);
host_var2 = 17.6;
ind_var2 = 0;
ind_var3 = -1;
EXEC SQL CALL :procname
(:host_var1,:host_var2 :ind_var2,:host_var3 :ind_var3);

    如上面的程序段所示,在调用存储过程时,可以通过宿主变量向存储过程传递调用参数。存储过程的调用参数可分为只输入的(input only)、只输出的(output only)和既输入又输出的(both input and output)。如果调用参数没有明确被说明为只输入的(input only)或只输出的(output only),则CALL语句将其缺省处理为既输入又输出的(both input and output)的调用参数。调用参数的输入输出类型由相应的指示符变量确定。对于只输入的(input only)的调用参数其相应指示符变量的值应为0(例如,上面程序段中的host_var2);对于只输出的(output only)的调用参数其相应指示符变量的值应为-1( 例如,上面程序段中的host_var3);

3.通过SQLDA传递过程调用参数
以下是一段通过SQLDA传递过程调用参数的程序例子:
struct sqlda *inout_sqlda = (struct sqlda *)malloc(SQLDASIZE(3));
long host_var3;
short ind_var3 = -1;
short ind_var2 = 0;

inout_sqlda->sqln = 3;
inout_sqlda->sqld = 3;

inout_sqlda->sqlvar[0].sqltype = SQL_TYPE_CSTR;
inout_sqlda->sqlvar[0].sqllen = 16;
inout_sqlda->sqlvar[0].sqldata = (char *)malloc(inout_sqlda->sqlvar[0].sqllen);
strcpy(inout_sqlda->sqlvar[0].sqldata,”new data”);

inout_sqlda->sqlvar[1].sqltype = SQL_TYPE_NFLOAT;
inout_sqlda->sqlvar[1].sqllen = sizeof(float);
inout_sqlda->sqlvar[1].sqldata = (char *)malloc(inout_sqlda->sqlvar[1].sqllen);
*(float *) inout_sqlda->sqlvar[1].sqldata = 17.6;
inout_sqlda->sqlvar[1].sqlind = &ind_var2;

inout_sqlda->sqlvar[2].sqltype = SQL_TYPE_NINTEGER;
inout_sqlda->sqlvar[2].sqllen = sizeof(long);
inout_sqlda->sqlvar[2].sqldata = (char *)&host_var3;
inout_sqlda->sqlvar[1].sqlind = &ind_var3;

EXEC SQL CALL myproc USING DESCRIPTOR :*inout_sqlda;

如上面的程序段所示,在调用存储过程时,也可以通过SQLDA向存储过程传递调用参数。
3.2 创建存储过程
以下是通过CREATE PROCEDURE语句创建存储过程的例子:
CREATE PROCEDURE MYPROC(INOUT HOST1 CHAR(15),
IN HOST2 DOUBLE, OUT HOST3 INTEGER)
EXTERNAL NAME ‘/home/user1/myfn!fn1’
LANGUAGE C
PARAMETER STYLE DB2DARI

1)CREATE PROCEDURE语句的作用是向数据库服务器注册一个新的存储过程;
2)MYPROC为存储过程的指定名。客户端应用程序可以在CALL语句使用这一名字调用相应的存储过程;
3)INOUT HOST1 CHAR(15)表示存储过程中所需的一个调用参数。其中,参数输入输出类型INOUT表明该参数既可向存储过程提供输入信息,也可接收从存储过程返回的信息。参数输入输出类型IN表示相应的参数只用于输入(input only);参数输入输出类型OUT表示相应的参数只用于输出(output only);
4)在同一个模式下,不允许定义名称、参数个数和数据类型都完全相同的存储过程;
5)EXTERNAL NAME(外部名)表示用户为实现所定义的存储过程而编写的程序代码段的名称;
6)LANGUAGE C 在CREATE PROCEDURE语句中是必不可少的,其作用是指明存储过程体的语言接口约定。该子句的另一个选项是LANGUAGE JAVA;
7)PARAMETER STYLE 的作用是说明向存储过程传递参数以及从存储过程接收返回结果的有关约定。DB2DARI表明存储过程使用的参数传递约定将与C语言的函数调用和连接约定相兼容;PARAMETER STYLE DB2DARI必须与LANGUAGE C一起使用。DB2GENERAL表明存储过程使用的参数传递约定将与JAVA语言的函数调用和连接约定相兼容;PARAMETER STYLE DB2GENERAL必须与LANGUAGE JAVA一起使用;

4 服务器端存储过程的实现
4.1实现存储过程的函数定义
在UDB中,存储过程的实现代码一般可应用某种编程语言(如C、C++或JAVA等)来编写。下面以C语言为例,说明在编写存储过程的实现代码时应注意的事项。
SQL_API_RC SQL_API_FN
myproc(void *reserved1,
void *reserved2,
struct sqlda * inout_sqlda,
struct sqlca *ca)
{
/* no connecttion related statements */
/* runs in background */
/* no command to terminate current process *./
/* (no exit, _exit, or at exit) */
/* if DUOW no COMMIT or ROLLBACK */
return(ret_value);
}
1)上面程序段开头的SQL_API_RC和SQL_API_FN为2个预定义的宏,目的是程序的可移植性;
2)在实现存储过程的函数体中不能出现与数据库连接相关的语句,即不能出现CONNECT,CONNECT RESET,CREATE DATABASE,DROP DATABASE,ALTER DATABASE,BACKUP,RESTORE,ROLLFORWORD等语句;
3)由于存储过程只在后台运行,所以不允许有写屏幕(如,printf)的动作,但允许写文件(fprintf);
4)存储过程的函数体只是一个被数据库管理系统调用的程序例程,所以当执行结束时总是应当将控制交还该调用它的函数,而不应终止当前进程,即在其函数体中不应出现exit(),_exit()这样的函数调用;
5)如果调用存储过程的客户端应用程序的数据库连接类型(CONNECT TYPE)为DUOW,则存储过程中不能发出终止事务的语句,即无论动态或静态的COMMIT、ROLLBACK都不允许出现。

4.2 存储过程的参数传递
SQL_API_RC SQL_API_FN
myproc(void *reserved1,void *reserved2,
struct sqlda *inout_sqlda, struct sqlca *ca)
{
struct sqlca sqlca; /*for local use */
/* use input data in SQLDA */
/* do not change SQLD,SQLTYPE, or SQLLEN */
/* do not change pointer for SQLDATA or SQLIND */
/* return data in SQLDATA(and SQLIND) */
memcpy(ca,&sqlca,sizeof(struct sqlca));


1) 存储过程将通过SQLDA中的输入变量得到客户端应用程序传来的输入参数,然后再通过SQLDA中的输出变量将输出结果返回给客户端应用程序。由于SQLDA各个域的原始值都是由客户端应用程序在过程调用前设置的,因此,存储过程的函数体不应改变SQLDA中的SQLD,SQLTYPE,SQLLEN等域的值。此外,虽然存储过程的函数体可以改变SQLDATA及SQLIND中所含指针指向的变量的值,但却不应改变SQLDATA及SQLIND中所含的指针。
注:SQLDA中的变量可以同时既是输入变量又是输出变量。
2) 在存储过程的函数体返回之前,应当显式地将本地SQLCA中的信息拷贝到存储过程的SQLCA参数之中。

4.3存储过程的返回值
SQL_API_RC SQL_API_FN
myproc(void *reserved1,void *reserved2,
struct sqlda *inout_sqlda, struct sqlca *ca)
{
/* processing */
/* in this application,the second SQLVAR field
is used to determine if the client intends to
call the server procedure again, A value of 0
means no further calls. */
if((*float *)inout_sqlda->sqlvar[1].sqlda != 0)
return(SQLZ_HOLD_PROC)
else
return(SQL_DISCONNECT_PROC);
}
1) 应当特别注意的是,存储过程的返回值根本不会返回给客户端应用程序。这里所说的返回值的作用是使数据库管理系统能够确定当存储过程执行终止时是否将存储过程从内存中释放掉。
2) 存储过程可以向数据库管理系统返回下列2个值:
—SQL_DISCONNECT_PROC:其含义是告诉数据库管理系统当所有信息都传递给客户端后,即可释放(或卸载)存储过程及其数据存储;
—SQL_HOLD_PROC:其含义是告诉数据库管理系统将存储过程库函数仍然保持在内存当中,这样将可以保证当客户端下一次发出对该存储过程的DARI调用时被调用的库函数已经在内存当中了,从而提高系统性能。
3) 如果客户端只对存储过程调用一次,则应返回SQL_DISCONNECT_PROC;
4) 如果客户端需要对存储过程调用多次,则应返回SQL_HOLD_PROC,从而保证存储过程不会被卸载;
5) 如果存储过程以SQL_HOLD_PROC作为返回值,则当其被最后一次调用时则应以SQL_DISCONNECT_PROC作为返回值,从而保证最后一次调用后将存储过程从内存中释放掉。否则该存储过程将被一直保存在主存中,直到数据库管理系统停止运行;
客户端应用程序在对存储过程进行最后一次调用时,应将这一信息通知被调用的存储过程。
分享到:
评论

相关推荐

    学习sql存储过程的心得

    学习SQL存储过程是提升数据库管理和应用开发效率的关键步骤,它可以帮助我们更好地组织和优化数据操作。 在SQL存储过程中,有以下几个重要的知识点: 1. **定义与创建**:存储过程可以通过`CREATE PROCEDURE`语句...

    SQL server存储过程习题,SQL触发器习题.rar

    在SQL Server数据库管理系统中,存储过程和触发器是两种非常重要的数据库编程元素,它们对于数据库设计和数据管理具有深远的影响。下面将详细讲解这两个概念及其相关的知识点。 **SQL存储过程**: 1. **定义**:SQL...

    sql server 2008 存储过程与储发器 详解 书籍

    在SQL Server 2008中,存储过程和触发器是数据库管理中不可或缺的重要组成部分,它们...通过深入学习《SQL Server 2008 存储过程与触发器详解》这本书,读者将能全面理解和掌握这两个概念,从而在实际项目中得心应手。

    SQL SERVER数据库开发之存储过程应用.rar

    总而言之,"SQL SERVER数据库开发之存储过程应用"教程会涵盖以上这些核心概念,并可能深入到高级主题,如动态SQL、游标、异常处理、临时表和变量的使用等。通过学习和实践,开发者可以提升在SQL Server环境下的...

    SQL Server存储过程

    在本实验中,我们将深入理解存储过程的工作机制,并通过实际操作学习如何编写和调用存储过程。 1. **无参存储过程** 无参存储过程通常用于执行固定的操作,例如查询所有数据或执行某些常规任务。在实验中,我们...

    C# winform调用SQL存储过程-菜鸟入门 详细注释

    内容概要:简单的C# winform调用存储过程实例,创建存储过程入参,通过SqlConnection对象和SqlCommand对象调用存储过程,获取存储过程的出参并显示出来,详细代码注释,希望对用到C#调用存储过程的小伙伴有帮助 ...

    SQL SERVER 存储过程学习笔记

    这篇学习笔记将深入探讨SQL Server存储过程的基本概念、创建、执行以及其在数据库开发中的应用。 一、存储过程的基本概念 存储过程是数据库中的一个对象,由一系列的SQL语句、控制流语句(如IF-ELSE,WHILE)和变量...

    最新最全SQL2008存储过程解密

    SQL2008存储过程是数据库管理中一个关键...通过深入学习和实践“最新最全SQL2008存储过程解密”的教程,用户可以提升数据库操作的效率,增强系统的安全性和稳定性,同时也为更复杂的数据处理和业务逻辑打下坚实的基础。

    SQLServer 2000存储过程手册

    SQL Server 2000是微软推出的一款关系型数据库管理系统,其存储过程是数据库管理员和开发者常用的功能之一,用于封装复杂的SQL查询、业务逻辑和数据处理。存储过程能够提高数据库性能,减少网络流量,增强安全性,并...

    sql Server 2005 存储过程视频

    学习存储过程,你需要掌握以下几个关键点: 1. **创建存储过程**:使用CREATE PROCEDURE语句创建自定义存储过程,包括指定输入参数、输出参数以及返回值。 2. **调用存储过程**:通过EXEC或EXECUTE语句来执行存储...

    如何编写SQL Server存储过程的详尽学习资料

    以下是对"如何编写SQL Server存储过程的详尽学习资料"的详细解析。 首先,我们要了解存储过程的基本概念。存储过程是数据库中的一个对象,由一组T-SQL语句组成,用于完成特定的数据库操作。它们可以被多次调用,...

    sql存储过程学习,详细的解说存储过程的语法,结构和用法。

    SQL存储过程是数据库管理系统中的一种重要工具...学习和掌握存储过程的创建、调用以及优化技巧对于任何数据库开发者都至关重要。通过实践和深入理解,您可以充分利用存储过程的优势,创建高效、安全的数据库应用程序。

    SQL SERVER 存储过程学习笔记(摘自网络)

    SQL Server 存储过程是数据库管理中的一个重要概念,它是一组预先定义并编译好的T-SQL语句,可以通过指定的名称进行调用执行。存储过程的使用极大地提高了数据库操作的效率和安全性,同时降低了开发人员的工作负担。...

    SQLSERVER存储过程例子

    在SQL Server中,存储过程是一种预编译的SQL语句集合,它...了解了这些基础知识后,你可以根据具体的存储过程内容来进一步学习和应用,如参数的传递、事务控制、异常处理等,以更好地利用SQL Server的存储过程功能。

    sql数据库存储过程学习

    SQL数据库存储过程是一种预编译的SQL代码集合,它封装了一系列复杂的数据库操作,可以在需要时通过调用存储过程的名字来执行。...学习和掌握存储过程的使用,对于任何SQL数据库开发者来说都是必不可少的技能。

    sql存储过程PPT

    总的来说,学习和熟练使用存储过程是提升SQL Server数据库管理能力的关键步骤,它们能够帮助我们更高效、安全地处理数据和实现复杂的业务逻辑。通过创建、调用存储过程,可以优化数据库性能,提高开发效率,同时确保...

    sql存储过程帮助文档

    SQL存储过程是数据库管理系统中一组为了完成特定功能的SQL语句集合,它们被编译并存储在数据库中,用户可以通过调用这个存储过程来执行预定义的任务,而不是每次需要时都编写相同的SQL代码。这个“sql存储过程帮助...

    Oracle学习开发常用的SQL和存储过程学习(内含SQL面试题目和存储过程,函数面试题目).zip

    本资源“Oracle学习开发常用的SQL和存储过程学习(内含SQL面试题目和存储过程,函数面试题目).zip”提供了全面的学习材料,旨在帮助初学者和求职者提升在Oracle数据库中的SQL查询和存储过程编写技能。 SQL...

    学习SQL Server存储过程入门例子详解

    SQL Server 存储过程入门例子详解 SQL Server 存储过程是数据库管理员和开发人员的必备技能,本文将通过三个简单的例子来详细介绍 SQL Server 存储过程的基本知识。 例 1:简单的存储过程 在这个例子中,我们将...

Global site tag (gtag.js) - Google Analytics