将定制的和庞大的营业逻辑集成到 SQL 语句中
内部存储进程
独霸内部存储进程
经由进程引用内部次序递次可以得到超出跨越 SQL PL 范围的茂盛遵守。经由进程独霸一个内部存储进程(即独霸 Java 措辞或 C# 等编程措辞编写的存储进程),可以处置惩罚内部数据源,也许实验数据库之外的内部法子。
与内部 UDF 近似,内部存储进程可以定义为以 NOT FENCED
或 FENCED
情势运转。异常,独霸 NOT FENCED
进程的长处是可以进步性能。然则,如果没有适外地编写这种进程,就会泛起内存裂痕,这种内存裂痕会掩饰覆盖与 DB2 引擎关系联的内存,因此会发作很是恶劣的影响。
确立内部存储进程
清单 25 显示了注册内部存储进程的简化语法图:
清单 25. 注册内部存储进程的简化语法图
>>-CREATE PROCEDURE--procedure-name-----------------------------> >-- -------------------------------------------------------- ---> '-(-- ---------------------------------------------- --)-' | .-,----------------------------------------. | | V .-IN----. | | '--- ------- -- ---------------- --data-type- -' -OUT--- '-parameter-name-' '-INOUT-' >--*-- ------------------------- --*----------------------------> '-SPECIFIC--specific-name-' .-DYNAMIC RESULT SETS 0--------. .-MODIFIES SQL DATA-. >-- ------------------------------ --*-- ------------------- ---> '-DYNAMIC RESULT SETS--integer-' -NO SQL------------ -CONTAINS SQL------ '-READS SQL DATA----' .-NOT DETERMINISTIC-. .-CALLED ON NULL INPUT-. >--*-- ------------------- --*-- ---------------------- --*-----> '-DETERMINISTIC-----' .-OLD SAVEPOINT LEVEL-. >-- --------------------- --*--LANGUAGE-- -C----- --*-----------> '-NEW SAVEPOINT LEVEL-' -JAVA-- -COBOL- -CLR--- '-OLE---' >--EXTERNAL-- ---------------------- --*------------------------> '-NAME-- -'string'--- -' '-identifier-' .-FENCED------------------------. >-- ------------------------------- --*-------------------------> -FENCED--*-- -THREADSAFE----- - | '-NOT THREADSAFE-' | | .-THREADSAFE-. | '-NOT FENCED--*-- ------------ -' .-EXTERNAL ACTION----. .-INHERIT SPECIAL REGISTERS-. >-- -------------------- -- --------------------------- --*-----> '-NO EXTERNAL ACTION-' >--PARAMETER STYLE-- -DB2GENERAL--------- --*-------------------> -DB2SQL------------- -GENERAL------------ -GENERAL WITH NULLS- -JAVA--------------- '-SQL----------------'
这个语法图中的很多子句在之前的一些大节中曾经联络过。本节着重引见内部存储进程特有的一些主要部门。
LANGUAGE
: 标明进程是用什么措辞编写的。可用于编写内部进程的措辞有 C、Java 措辞、COBOL、CLR 和 OLE。EXTERNAL NAME
: 指定用户编写的用来完成所定义进程的代码的称号。该字符串的花式取决于所指定的措辞。本教程简要地联络在独霸 C、Java 和 CLR 措辞时该字符串的花式。EXTERNAL ACTION
: 决定进程能否可以实验内部法子。PARAMETER STYLE
: 该子句用于指定进程通报参数和前去值的商定。可用的选项有:DB2GENERAL
: 独霸为 Java 方式定义的参数通报商定。只需在独霸LANGUAGE JAVA
时,才气指定该选项。DB2SQL
: 当指定该选项时,可以将提供附加诊断信息的附加参数通报给进程。只需在指定LANGUAGE C
、COBOL
、CLR
或OLE
时,才气指定该选项。GENERAL
: 招致进程接纳CALL
语句中指定的参数,而不独霸 SQLDA 构造。只需在指定LANGUAGE C
、COBOL
或CLR
时,才气指定该选项。GENERAL WITH NULLS
: 近似于GENERAL
选项,然则还将另一个参数通报给进程:该参数是由 null 指示符组成的一个向量,CALL
语句的每个参数对应一个 null 指示符。JAVA
: 招致进程独霸驯服 Java 措辞和 SQLJ 例程模范模范的参数通报商定。 以单条目数组的情势通报IN/OUT
和OUT
参数,以便于前去值。只需当独霸LANGUAGE JAVA
时,才气指定该选项。SQL
: 当指定该选项时,CALL
语句中包括提供附加诊断信息的附加参数。只需当独霸LANGUAGE C
、COBOL
、CLR
或OLE
时,才气指定该选项。
方式会关于 CREATE PROCEDURE
语句中这些子句和其他子句的更多信息,请参阅 DB2 文档。
回页首
EXTERNAL NAME 子句选项
内部存储进程一个最紧张的强逼性质句就是 EXTERNAL NAME
子句。该子句控制 DB2 可以在那里探求编译后的进程代码。在本节中,您将认识在 C、Java 和 CLR 措辞中,该子句的字符串是若何任务的。
C 措辞
指定的字符串是库名和库中的进程,数据库打点器调用它来实验所确立的进程。在实验 CREATE PROCEDURE
语句时,这个库(以及库中的进程)不需求曾经存在。然则,当进程被调用时,这个库和库中的进程必须存在,并且可以也许从数据库效能器上会晤到。关于 C 措辞,指定的字符串花式如下:
>>-'-- -library_id------- -- ------------ --'------------------>| '-absolute_path_id-' '-!--proc_id-'
下面别离刻画它的差别组成部门:
library_id
: 包括该进程的库的称号。数据库打点器按如下方式探求库:- 在 UNIX 系统上,如果指定的
library_id
为myfunc
,数据库打点器在 /u/production 目录下运转,当指定FENCED
时,数据库打点器在 /u/production/sqllib/function/myfunc 中探求进程库;当指定NOT FENCED
时,数据库打点器在 /u/production/sqllib/function/unfenced/myproc 中探求进程库。 - 在 Windows 操作系统上,数据库打点器在
LIBPATH
或PATH
情况变量指定的目录途径中探求进程库。
- 在 UNIX 系统上,如果指定的
absolute_path_id
: 标识包括该进程的文件的无缺途径名。! proc_id
: 标识要调用的进程的入口称号。!
是库 ID 与进程 ID 之间的定界符。比喻,!proc8
将指示数据库打点器在absolute_path_id
指定的职位探求库,并独霸那个库中的proc8
入口。如果这个字符串的花式不对,就会前去错误。
Java 措辞
指定的字符串包括可选的 JAR 文件标识符、类标识符和方式标识符,数据库打点器调用它来实验所确立的进程。当实验 CREATE PROCEDURE
语句时,类标识符和方式标识符不需求曾经存在。如果指定了一个 jar_id
,那么当实验 CREATE PROCEDURE
语句时,它必须曾经存在。异常的,当进程被调用时,类标识符和方式标识符必须曾经存在,并且可以从数据库效能器上会晤到。否则会前去错误。关于 Java 措辞,该字符串的花式为:
>>-'-- ---------- -->
下面别离刻画它的差别组成部门:
jar_id
: JAR 聚集在被布置到数据库中时得到的 JAR 标识符。它可所以一个庞大的标识符,比喻myJar
,也可所以一个情势限定的标识符,比喻mySchema.myJar
。>
: Java 对象的类标识符。如果这个类属于一个包,则类标识符部门还必须包括无缺的包前缀。比喻,如果独霸myPacks.StoredProcs
,则 Java 编造机将在 .../myPacks/StoredProcs/(关于 Windows,则为 ...\myPacks\StoredProcs\)目录中探求类。method_id
: 被调用的 Java 类中的方式的称号。
CLR
指定的字符串走漏表示 .NET 组合件(库或可实验文件)、组合件中的类以及类中的方式,数据库打点器将调用它来实验所确立的进程。当实验 CREATE PROCEDURE
语句时,模块、类和方式不需求曾经存在。然则,当进程被调用时,模块、类和方式必须存在,并且可以从数据库效能器上会晤到,否则会前去错误。关于 .NET 组合件(库或可实验文件),该字符串花式如下:
>>-'--assembly--:-->
下面别离刻画它的差别组成部门:
assembly
: 类地址的 DLL 或其他文件的标识符。这里必须指定文件扩展名(比喻 .dll)。如果没有提供无缺的途径称号,那么该文件必须在 DB2 布置途径(比喻 C:\sqllib\function)的函数目录中。如果该文件在布置途径下的函数目录中的一个子目录中,那么可以在文件名之前提供这个子目录,而不用指定无缺的途径。比喻,如果布置目录为 C:\sqllib\function\myprocs\mydotnet.dll,那么只需为组合件指定 myprocs\mydotnet.dll。该参数的巨细写敏感性与文件系统相反。>
: 指定在给定的组合件中,要调用的方式地址的类的称号。如果这个类在一个称号空间中,那么除了类名之外,还需指定无缺的称号空间。比喻,如果类Employee>
在称号空间MyCompany.Procedure>
中,那么必须指定MyCompany.Procedure>
。该参数是巨细写敏感的。method_id
: 指定在给定类中要调用的方式。该参数是巨细写敏感的。
今朝,您曾经回首回头回忆了确立内部存储进程的语法,接上去可以看看确立 Java 存储进程的一个例子。
回页首
Java 存储进程例子
我们来看一个确立 Java 存储进程的例子。 清单 26 包括该进程的 Java 源代码:
清单 26. 一个庞大的 Java 存储进程的代码
import java.sql.*; public >
该进程的代码包括在一个名为
SimpleInsert()
的 Java 方式中,而这个 Java 方式又包括在一个名为Simple
的 Java 类中。(因此寄存代码的文件名为 Simple.java)。清单 26 中的代码没有什么特别之处,它是规范的含有 JDBC 方式调用的 Java 代码。该进程有两个参数,都是字符串型的。第一个参数是输入参数,第二个参数是输入参数。仔细,输入参数被定义为一个String
数组。该进程用于注册的PARAMETER STYLE JAVA
属性要求OUT
和INOUT
参数定义为数组。还需仔细的是该进程继承调用者到数据库的毗连的方式,它独霸的毗连字符串差别于规范的 JDBC 独霸次序递次。
经由进程独霸布置的系统上的也许 DB2 附带的 JDK,可以像下面这样编译该进程:
javac Simple.java
编译后会生成一个类文件。然后,可以将该文件转移到 sqllib/function 目录(DB2 探求存储进程可实验文件的默许职位),也许转移到您所选择的其他职位(只需在
CREATE PROCEDURE command
中独霸这个定制途径)。关于这个例子,独霸前一种目录,将类文件复制到 sqllib/function 目录中。
将类文件放在合适的职位后,便可以独霸
CREATE PROCEDURE
语句将该函数注册到 DB2 中,如 清单 27 所示:
清单 27. 注册 Java 存储进程
CREATE PROCEDURE simple_insert (IN input CHAR(3), OUT outMsg VARCHAR(254)) SPECIFIC simple1 DYNAMIC RESULT SETS 0 DETERMINISTIC LANGUAGE JAVA PARAMETER STYLE JAVA FENCED THREADSAFE MODIFIES SQL DATA EXTERNAL NAME 'Simple!SimpleInsert'
注册函数之后,就可以调用该函数,如 清单 28 所示。仔细,问号(
?
)用于走漏表示输入参数。当从命令行调用存储进程时,都是用问号走漏表示输入参数。
清单 28. 调用 Java 存储进程
CALL simple_insert('ABC', ?) Value of output parameters -------------------------- Parameter Name : OUTMSG Parameter Value : The update was successful. Return Status = 0 Result from DB2 sample database: SELECT * FROM db2admin.mydata COL1 ---------------------------- ABC 1 record(s) selected.
这个很是庞大的 Java 存储进程实践上也可以很苟且地编写成 SQL 存储进程。然则,看过这个例子之后,就应该了解,如果独霸主机编程措辞的悉数遵守和 API,可以编写出多么庞大的内部存储进程。
版权声明: 原创作品,许可转载,转载时请务必以超链接情势标明文章 原始情由 、作者信息和本声明。否则将清查执法责任。