DB2 9 应用开发(733 考试)认证指南,第 1 部分
2009-01-13 16:36:49 来源:WEB开发网开始之前
本教程的内容
本教程介绍了不同类型的数据库对象和编程方法。在本教程中,我们将学习:
不同类型的数据库对象
模式与数据库对象之间的关系
SQL 例程的基本原理
编程接口的基础知识:动态 SQL、静态嵌入式 SQL、CLI 和 ODBC、.NET、JDBC 和 SQLJ、PHP、Perl、Python 以及 XML
应用程序数据访问相关的安全考虑
这是包含九篇教程的系列文章的第一篇,此系列用于为 DB2 9 Family Application Development 认证考试 (Exam 733) 作准备。本教程的内容主要涵盖了该考试第 1 部分的考察目标,标题为:“数据库对象和编程方法。”
学习本教程不一定要拥有一份 DB2 9。
哪些人应学习本教程?
要参加 DB2 9 Family Application Development 考试,必须已通过 DB2 9 Family Fundamentals 考试 (Exam 730)。可以使用 “DB2 Family Fundamentals 教程系列” 为后一考试作准备。该系列教程很受欢迎,已帮助许多人了解 DB2 系列产品的基本原理。
虽然要理解本教程描述的概念,不必完全掌握 Family Fundamentals 系列教程中讨论的所有内容,但应至少具备以下几个方面的基础知识:
DB2 实例
数据库
数据库对象
DB2 安全
本教程是可以帮助您为 Exam 733 作准备的方式之一。
DB2 数据库对象
基本数据库对象
数据库对象是构建数据库的原料。DB2 提供了不同类型的数据库对象,用于存储和表示不同的信息。可使用数据库定义语言 (DDL) 创建、修改和删除这些对象。要操作这些对象,请使用数据库操作语言 (DML),该语言包含 SELECT、UPDATE、INSERT 和 SELECT 语句。一些常用的数据库对象如下:
表
自定义数据类型
约束
视图
索引
如果您对这些基本的数据库对象不太熟悉,请查阅标题为 “使用 DB2 对象”(developerWorks,2006 年 7 月)的 Family Fundamentals 教程,了解背景信息。
除 Family Fundamentals 教程中介绍的数据库对象以外,还有一些其他对象,在开发 DB2 应用程序时比较有用。本教程将在此部分介绍这些对象。
在继续学习之前需要注意一点:在本文提供的示例中,对象名称以小写字母表示。不论 DB2 在何种平台上运行,它总是以大写形式存储名称,除非标识符的名称加了双引号 ("")。
例如,下列语句将创建一个表 employee(小写),它与表 EMPLOYEE(大写)具有相同的列定义。
CREATE TABLE "employee" LIKE employee
别名
别名 是现有表、视图或昵称的备用名。别名还可作为其他别名的备用名。与对象类似,可创建或删除别名,别名可拥有相关的注释。以下是几个 CREATE ALIAS 语句示例:
CREATE ALIAS aliastab1 FOR tab1;
CREATE ALIAS bob.aliastab1 FOR tom.tab1;
CREATE SYNONYM bob.aliastab2 FOR bob.aliastab1;
如您所见,CREATE ALIAS 语句非常简单。可使用与源对象相同的模式创建别名(如第一行所示),也可完全限定别名名称(如第二行所示)。用关键字 SYNONYM 替代 ALIAS(如第三行所示)也有效,这样做是为了与 DB2 for zSeries 兼容。
使用别名不需要具备特殊权限。但是,需要获得引用的底层对象相关的适当授权。要获得数据库对象权限的完整列表,请查阅标题为 “服务器管理”(developerWorks,2006 年 6月)的 DB2 DBA 认证教程。
前面提到可以为昵称 创建别名。昵称是引用联合系统上数据表或视图的数据库对象。但是,联合数据库支持超出了本教程的讨论范围。
要给别名添加注释,可使用以下语句:
COMMENT ON aliastab1 IS 'My first alias on tab1'
要删除别名,可以与删除任何其他数据库对象一样,使用 DROP 语句:
DROP ALIAS aliastab1
序列对象
序列 是允许自动生成值的数据库对象。与绑定到特定表的标识列不同,序列是全局的、独立的对象,可被同一数据库中的任何表使用。
标识列是一种特殊类型的序列对象。因此,标识列的特征也适用于序列对象。下面是 CREATE SEQUENCE 语句示例:
清单 1. CREATE SEQUENCE 语句
CREATE SEQUENCE myseq AS INTEGER
START WITH 360
INCREMENT BY 10
NO MAXVALUE
CYCLE
CACHE 20
任何数值范围包含零值的整数数据类型都可用作序列值。这些类型包括 SMALLINT、INTEGER、BIGINT 或 DECIMAL。基于这些数据类型的自定义特殊类型也都可用作序列值。这进一步扩展了自定义特殊类型在应用程序中的应用。
如上面的清单 1 所示,可以通过指定序列的初始值来定制序列对象。在本例中,序列的初始值为 360。后续值的生成由 INCREMENT BY 子句控制。支持使用正、负常量生成升序、降序序列值。
默认情况下,序列生成的最小值和最大值受序列数据类型限制的约束。例如,INTEGER 序列值必须介于 -2,147,483,647 到 2,147,483,647 的范围之内。可在 DB2 SQL 参考指南(参见 参考资料)中找到所有数值数据类型的限制。要更改这种约束行为,可使用 MINVALUE 和 MAXVALUE 选项为生成的值设定界限。如果达到最小或最大值,则可使用另一个称作 CYCLE 或 NO CYCLE 的选项来指定序列值是否可循环。请注意:当 CYCLE 生效时,该序列可能生成重复的值。
CACHE 选项允许 DB2 在内存中保存一些预分配的值以改善性能。CACHE 20 是默认行为。关于此选项需要注意一点:如果 DB2 在停止时没有用完所有缓存的值,则所有未使用的缓存值将被丢弃。DB2 重新启动后,就会生成并缓存下一组值,导致产生值差异。如果您的应用程序不允许存在值差异,可考虑改为使用 NOCACHE 选项。
如果未使用缓存,若序列的数字生成速度很快,性能就会非常糟糕。每生成一个新值时就会写一个日志记录。因此,在一个请求中获取值并将其缓存在内存中,效率更高。
可使用 ALTER SEQUENCE 语句更改序列对象的特征。可以更改上面讨论的所有设置,但序列值的数据类型除外。要获得完整的语法图,请查阅 DB2 SQL 参考指南(参见 参考资料)。
删除序列对象与删除任何其他数据库对象一样。语句末尾的 RESTRICT 关键字用于防止在存在依赖项的情况下删除序列。这是默认行为。您可在语句中显式地指定 RESTRICT 关键字。
DROP SEQUENCE myseq RESTRICT
生成和检索序列值
序列 是数据库对象的一种类型;因此,其访问也由权限控制。默认情况下,只有序列的创建者、SYSADM 和 DBADM 拥有对象的 USAGE 权限。如果希望其他用户能使用该序列,需使用以下语句:
GRANT USAGE ON SEQUENCE seq_object_name TO PUBLIC
如果要更改序列对象的属性,需要有对象的 ALTER 权限:
GRANT ALTER ON SEQUENCE seq_object_name TO GROUP group_name
请查阅标题为 “服务器管理” 的 DB2 DBA 认证教程,了解关于 DB2 安全的更多信息。
系统提供了两个表达式用于生成和检索序列值。NEXT VALUE FOR seq-name 用于获得下一个序列值,而 PREVIOUS VALUE FOR seq-name 用于检索上一个生成的序列值。下面的清单 2 中的示例展示了这些表达式的用法。
清单 2. NEXT VALUE FOR 和 PREVIOUS VALUE FOR 表达式
INSERT INTO t1 VALUES (NEXT VALUE FOR myseq, 'BOB');
INSERT INTO t1 VALUES (NEXT VALUE FOR myseq, 'PAT');
COMMIT;
INSERT INTO t1 VALUES (NEXT VALUE FOR myseq, 'GENE');
ROLLBACK;
INSERT INTO t1 VALUES (NEXT VALUE FOR myseq, 'PAUL');
VALUES PREVIOUS VALUE FOR myseq INTO :hostvar
假设以一个空表 t1 开始操作,并且 myseq 的下一个序列值为 1。禁用自动提交,执行上面的语句后,表 t1 将包含下列行:
1 NAME
------- -------
1 BOB
2 PAT
4 PAUL
3 record(s) selected.
虽然生成的 GENE 值发生了回滚,但 DB2 不会重用该值。因此,下一个为 PAUL 生成的序列值为 4 而不是 3。
上面清单 2 中的最后一个语句展示了 PREVIOUS VALUE 表达式的用法。主机变量 :hostvar 存储当前会话中生成的最后一个值。如果希望保存以前生成的任何值,应在生成下一个值之前保存前一个值。
临时表
顾名思义,临时表 不是永久数据库对象。临时表的行为跟普通表相似,但并不支持或需要所有特性和选项。它只在连接期间存在。连接关闭时,其中声明的所有临时表将被自动删除。
只有声明临时表的会话或应用程序可访问该临时表。如果两个应用程序创建了同名的临时表,则表的每个实例是惟一的。因此,无需担心出现临时数据冲突的情况;因为临时表只允许单个连接访问,所以无需进行锁定。这是临时表的主要性能优点之一。
声明临时表
要声明临时表,必须存在 USER 临时表空间,以便存储临时表的定义和内容。(USER 临时表空间与 SYSTEM 临时表空间不同;后者只在 DB2 内部用于执行排序等操作。)下面这个简单语句创建一个 USER 临时表空间:
CREATE USER TEMPORARY TABLESPACE usertempspace
MANAGED BY SYSTEM USING ('usertempspace')
声明全局临时表时,支持很多可选子句。 清单 3 中的例子阐释了它们的行为:
清单 3. 全局临时表支持的可选子句
DECLARE GLOBAL TEMPORARY TABLE t_dept
( deptid CHAR(6), deptname CHAR(20) )
ON COMMIT PRESERVE ROWS
NOT LOGGED ON ROLLBACK DELETE ROWS
IN usertempspace
在清单 3 中的例子中,临时表 t_dept 的声明用了两列。ON COMMIT PRESERVE ROWS 子句说明执行 COMMIT 操作时,将保留临时表中的行。
该例子指定对表的更改是 NOT LOGGED。就是说在表上进行的任何插入、更新或删除操作都不会留下日志记录。但记录表的创建和删除。如果创建表时执行了一组操作,并且在此之后发生了回滚,则该临时表将被删除。另一方面,如果删除表时执行了一组操作,则该表将恢复为没有任何行的空表。
无需使用 IN 子句指定临时表将要使用的用户临时表空间。如果不指定此信息,则 DB2 将搜索最合适的表空间。如果无法找到用户临时表空间,DB2 将引发一个错误。
请看下面的另一个示例:
清单 4. 声明全局临时表
DECLARE GLOBAL TEMPORARY TABLE t_proj
LIKE project
ON COMMIT PRESERVE ROWS
WITH REPLACE
IN usertempspace
使用关键字 LIKE 声明临时表 t_proj,因此它拥有与名为 project 的永久表或视图相同的列定义。ON COMMIT PRESERVE ROWS 子句表明在 COMMIT 时将保留临时表中的所有行。因此,它们可以在后面的事务中进一步进行处理。
在同一会话中使用同一名称声明另一个临时表之前,必须先删除原临时表。可显式地完成此操作,也可利用 WITH REPLACE 选项,如清单 4 所示。通过 WITH REPLACE 选项,DB2 隐式地删除所有数据和临时表并使用新定义重新创建该表。
WITH REPLACE 选项与连接入池 一起使用时非常便捷。连接入池是重用数据库连接的一种机制,避免根据需要分配和释放资源。这些操作很耗费资源,尤其是存在大量执行相对较短事务的连接时更是如此。由于没有释放连接,因此可能没有清理以前使用的临时表。使用该连接的下一个应用程序可能获得前面执行所遗留的数据。因此,使用 WITH REPLACE 选项来保证通过新定义刷新临时表。
模式和数据库对象
大多数数据库对象通过模式 和对象名 来识别。数据库模式提供数据库对象的逻辑分类。下面是这类由两部分组成的对象名称示例:
DB2ADMIN.EMPLOYEE
HRPROD.AUDIT_VIEW
HRPROD.AUDIT_TRIG
如果访问数据库对象时未指定模式,则建立数据库连接时使用的用户 ID 将被设置为默认模式。例如,如果用户 db2admin 连接到数据库并创建表 T1,则 DB2 将创建名为 db2admin.T1 的表。所有引用时未限定表 T1 的后续 SQL 语句都将被解析为 db2admin.T1。
DB2 特有的注册项:CURRENT SCHEMA
您可能已经注意到:在数据库操作中,如果用户的用户名就是要操作对象的模式名时,使用用户 ID 有时无法连接到数据库。对应用程序进行硬编码从而完全限定对象也并非最佳解决方案。幸运的是,DB2 允许使用 SET CURRENT SCHEMA 命令更改当前模式。默认情况下,DB2 特有的注册项 CURRENT SCHEMA 被设置为连接数据库的 USER。当更改 CURRENT SCHEMA 时,所有未限定的数据库对象都会加上该新值作为前缀。
可使用以下命令获得当前模式:
VALUES CURRENT SCHEMA
要更改当前模式,可简单地使用下列任意一条命令:
SET SCHEMA=db2admin
SET CURRENT SCHEMA=db2admin
DB2 应用程序开发数据库对象
例程
在本部分,还将了解另外几种类型的数据库对象。这些对象的总称为例程。有三种主要功能类型的例程:存储过程、函数 和方法。(有关这些类型之间的区别的更多信息,请参见下面标题为 “存储过程、函数和方法” 的部分。)
例程是用于封装与特定任务相关的编程和数据库逻辑的数据库对象。通过有效地使用例程,可简化应用程序代码并提高代码重用率。例如,如果将某种业务逻辑封装在例程中,则对业务规则的更改将只能影响到该具体例程。因此,可将对应用程序的更改最小化。
在数据库服务器上定义和处理例程。这将允许应用程序充分利用数据库服务器的能力,同时又降低客户机上所需的处理负载。通常,复杂业务逻辑发出多个 SQL 语句。语句从客户机分别发送到服务器,如果涉及大量数据库活动,则会导致网络通信量很高。如果在例程中捕获这些操作,则客户机与服务器机器之间的网络通信量将大大减少,从而改善应用程序的总体性能。
能够增强安全性是使用例程的另一个主要优点。例程可用来屏蔽对底层数据库对象的直接访问。拥有 EXECUTE 权限就足以调用例程;无需具备底层数据库对象的显式权限。
例程的不同实现
有以下几种可能的例程实现:
内置 例程是 DB2 系统附带的。它们是在 SYSIBM、SYSPROC、SYSFUN 和 SYSTOOLS 之类的系统模式中定义的。
有源 例程仅适用于函数。有源函数复制另一函数的语义。
外部 例程使用外部编程语言实现。可在下列支持语言中开发例程:
Java™ 语言
C/C++
.NET
OLE(仅适用存储过程)
OLE DB(仅适用表函数)
SQL 例程使用 SQL Procedural Language (SQL PL) 实现。DB2 SQL PL 是 SQL Persistent Stored Modules (SQL/PSM) 语言标准的子集。此标准是结构化编程语言的基础,将后者与 SQL 一起使用可编写存储过程、函数和方法。它结合了 SQL 数据访问的方便性与简单编程语言的流控制结构。这就是 SQL PL 如此流行的主要原因。
存储过程、函数和方法
存储过程 是包含一些程序的数据库对象,这些程序专用于访问和修改一个或多个表中数据。在存储过程中,可将多个 SQL 语句与流逻辑包装在一起。它们用作客户机应用程序或其他例程的子例程扩展。它们在关系数据库管理系统 (RDBMS) 的控制下执行和管理。
函数 是可自定义的 SQL 扩展。可在 SQL 语句(如 select-list 或 FROM 子句)中调用它们。有以下四种类型的函数:集聚、标量、行 和表。
存储过程通常用于封装复杂应用程序逻辑以及执行大量数据库操作,比如多表连接和游标操作。另一方面,函数(尤其是 SQL 函数)通常包含较为简单的操作。SQL 函数中编码的语句扩展到引用该函数的 SQL 语句,并通过此语句执行。这就导致了语句在执行时动态编译。如果 SQL 语句中使用了复杂的 SQL 函数,则 DB2 需要额外的资源来编译该语句并生成数据访问计划。这可能影响运行时的总体性能。
方法 封装了一些逻辑,这些逻辑为包含一个或多个指定属性的结构化类型提供行为,其中每个属性均拥有其自己的数据类型。
DB2 特有的注册项:CURRENT PATH
与大多数 DB2 数据库对象一样,完整的例程名包括模式和例程名。本教程中前面介绍的 DB2 特有的注册项 CURRENT SCHEMA(在上面的标题为 “DB2 特有的注册项:CURRENT SCHEMA ” 的部分也讨论过),为大多数数据库对象解析模式,但例程除外。DB2 改为使用特有的注册项 CURRENT PATH 来定位例程。
可使用以下命令获得 CURRENT PATH 设置:
VALUES CURRENT PATH
默认路径包含三种系统模式,后面是当前连接到数据库的用户。例如:
"SYSIBM"、"SYSFUN"、"SYSPROC"、"DB2ADMIN"
下面是几个可用于更新 PATH 的技巧示例:
清单 5. 更新 PATH:示例 1
SET PATH=CURRENT PATH,"USER2"
VALUES CURRENT PATH
------------------------------
"SYSIBM","SYSFUN","SYSPROC","DB2ADMIN","USER2"
1 record(s) selected.
清单 6. 更新 PATH:示例 2
SET PATH=SYSTEM PATH,"USER2"
VALUES CURRENT PATH
------------------------------
"SYSIBM","SYSFUN","SYSPROC","USER2"
1 record(s) selected.
清单 7. 更新 PATH:示例 3
SET PATH="USER1","USER2","USER3"
VALUES CURRENT PATH
------------------------------
"USER1","USER2","USER3"
1 record(s) selected.
嵌入式 SQL 程序
嵌入式 SQL 简介
DB2 提供了不同的编程方法,以便开发人员用来编写应用程序。其中最直接的一种方法是嵌入式 SQL 编程。此编程方法很直接,这是由于程序中嵌入了直接与 DB2 交互的 SQL 语句。可用下列任意一种支持的编程语言来编写程序:
C/C++
Java 语言 (SQLJ)
FORTRAN
COBOL
REXX
如何构造嵌入式 SQL 语句取决于所选的编程语言。C/C++ 和 FORTRAN 中的嵌入式 SQL 语句具有 EXEC SQL 关键字前缀:
EXEC SQL SELECT lastname,empid INTO :hostvar1, :hostvar2
FROM employee WHERE deptno="OPERATIONS";
COBOL 中的嵌入式 SQL 语句与 C/C++ 中编码的类似,但是语句的末尾需加上关键字 END-EXEC:
EXEC SQL SELECT lastname,empid INTO :hostvar1, :hostvar2
FROM employee WHERE deptno="OPERATIONS" END-EXEC;
Java 语言中的嵌入式 SQL 语句与上述两种语言中的语句稍有不同,因为必须指定要执行该语句的连接上下文。下面是一个示例:
#sql [myConnCtx] {SELECT lastname, empid INTO :hostvar1, :hostvar2
FROM employee WHERE deptno="OPERATIONS"};
为了更好地了解嵌入式 SQL 程序的形式,清单 8 包含了一小段用 C 编写的程序。在本系列的第四篇教程中(见 参考资料),将学习关于程序预编译和实际代码开发的更多信息。
清单 8. 一小段用 C 编写的嵌入式 SQL 程序
int TbBasic(void)
{
int rc = 0;
struct sqlca sqlca;
EXEC SQL BEGIN DECLARE SECTION;
char hostVarStmt[50];
EXEC SQL END DECLARE SECTION;
/* declare cursor */
EXEC SQL DECLARE c1 CURSOR FOR
SELECT deptnumb, deptname FROM org WHERE deptnumb = 40;
/* open cursor */
EXEC SQL OPEN c1;
/* fetch cursor */
EXEC SQL FETCH c1 INTO :deptnumb, :deptname;
while (sqlca.sqlcode != 100)
{
printf(" %8d %-14sn", deptnumb, deptname);
EXEC SQL FETCH c1 INTO :deptnumb, :deptname;
}
/* close cursor */
EXEC SQL CLOSE c1;
/* prepare the statement */
strcpy(hostVarStmt, "DELETE FROM org WHERE deptnumb = 15");
EXEC SQL PREPARE Stmt FROM :hostVarStmt;
/* execute the statement */
EXEC SQL EXECUTE Stmt;
/* ROLLBACK the transaction */
EXEC SQL ROLLBACK;
return 0;
}
静态 SQL
刚刚展示了两种不同类型的嵌入式 SQL 语句:静态嵌入式 SQL 和动态嵌入式 SQL。
示例中使用的 SELECT 语句阐释了静态 SQL 的用法。要编写静态 SQL,必须指定完整的语句。引用的表、列的名称以及数据类型是已知的。在运行时惟一可以指定的信息是使用主机变量的 SQL 语句的 WHERE 子句中的值。
静态 SQL 语句编译(使用 DB2 术语则为准备)后,生成数据访问计划并将其存储在数据库包中。调用包含该语句的应用程序时,将执行此包。由于没有语句需在运行时编译,所以执行静态 SQL 时没有编译成本。
在准备语句时,DB2 使用数据库统计信息和配置参数来计算并获得访问计划。随着数据库统计信息的更改,预生成的访问计划可能不如最初生成时那样理想。
使用准备静态 SQL 语句的用户的授权来创建包和将包绑定到数据库。只要执行包的用户拥有该包的 EXECUTE 权限,该用户就无需拥有包中所引用数据库对象的显式权限。
动态 SQL
动态 SQL 语句在运行时动态处理。执行应用程序时才需要知道语句结构。
请注意:清单 8 所示的示例 SQL 语句使用动态 SQL 来 PREPARE 和 EXECUTE 一个 DELETE 语句。DELETE 语句中的文本存储在一个主机变量 hostVarStmt 中。PREPARE 语句后,就创建了该语句的可执行形式,并将其存储于数据库包中。一旦生成数据访问计划,即可 EXECUTE 准备后的语句。这听起来很熟悉,不是么?是的:这两个处理阶段与静态 SQL 语句几乎完全一样。惟一的不同是动态 SQL 在运行时处理 PREPARE 和 EXECUTE。而静态 SQL 在预编译时准备访问计划并将其保存在数据库中。
动态 SQL 语句必须总是在执行前准备,无论是不是多次使用同一语句(因此,使用同一访问计划)。为了仅可能降低这些 PREPARE 的消耗,DB2 提供了包缓存(也称作动态查询缓存),用于将频繁使用访问计划保存在内存中。包缓存大大地降低了重复 SQL 准备请求的消耗,但仍然存在发出和响应准备请求的系统开销。
总是在准备语句时使用当前的数据库统计信息。因此,可生成最理想的数据访问路径。
SQL 语句的授权是在运行时决定。执行应用程序的用户必须拥有适当的权限,用来访问语句中所引用的数据库对象。
安全考虑
要预编译嵌入式静态 SQL 程序,需拥有程序中所引用的数据库对象的显式权限。因为预编译或 PREPARE 阶段生成包并将其存储在数据库中,所以必须同时拥有 BINDADD 权限才能将新包添加到数据库中。要使用静态 SQL 执行程序,只需拥有相关包的 EXECUTE 权限即可。
如果要编译嵌入式动态 SQL 程序,还需拥有 BINDADD 权限。因为动态 SQL 不是在编译时准备,所以无需拥有其他权限。程序执行时,必须拥有发出每个 SQL 语句必需的所有权限,并对为嵌入式 SQL 程序所创建的包,拥有 EXECUTE 权限。
表 1 总结了预编译和执行只使用静态或纯动态 SQL 语句的程序所需的权限:
表 1. 预编译和执行程序所需的权限
角色 | 静态 SQL 所需的权限 | 动态 SQL 所需的权限 |
开发人员(预编译程序) | BINDADD 权限用于向数据库中添加新包;数据库对象的显式权限 | BINDADD 权限用于向数据库中添加新包 |
应用程序用户(执行程序) | EXECUTE 权限用于执行程序相关的包 | 数据库对象的显式权限;EXECUTE 权限用于执行程序相关的包 |
静态 SQL 与动态 SQL 对比
下面在表 2 中总结并扩展所了解的静态和动态 SQL 知识:
表 2. 静态 SQL 与动态 SQL 对比
静态 SQL | 动态 SQL |
SQL 语句的结构是已知的。对列、表和数据类型的引用必须明确指定。变量只能用作语句的 WHERE 子句中的搜索值。 | 预编译时无需知道语句结构。语句文本自身可存储在应用程序执行期间引用的一个变量中。这就提供了支持程序的灵活性,因为在应用程序设计时并不知道语句的最终形式。 |
在预编译时生成数据访问计划。包在数据库中是持久的,并且可重用。如果只是偶尔运行语句,则与动态 SQL 相比,静态 SQL 可能提供更好的运行时性能。 | 在运行时生成数据访问计划。存储在内存中称为包缓存 的位置。如果多次执行同一语句,则可重用 PREPARE 阶段在内存中生成的数据访问计划。因此,动态 SQL 的性能不一定比静态 SQL 差。但是,首次执行动态 SQL 时必须承受 PREPARE 阶段的全部成本。 |
预编译时的数据库统计信息和配置参数用于生成理想的数据访问计划。 | 运行时的数据库统计信息和配置参数用于生成理想的数据访问计划 如果需要频繁地执行 RUNSTATS,则动态 SQL 可利用最新、最佳的数据库统计信息。 |
预编译时验证授权。开发人员要预编译包含静态 SQL 的程序,必须拥有访问语句中所引用的对象的适当授权和权限。创建包之后,执行包的用户必须拥有包的 EXECUTE 权限。 | 运行时验证授权。用户若要执行包含动态 SQL 的程序,必须对语句中所引用的对象拥有适当授权和权限。 |
基于驱动程序的 API
虽然大多数数据库供应商支持嵌入式 SQL 数据库访问,但如果希望使用相同的源代码并将嵌入式 SQL 应用程序部署到多个数据库系统,则需进行一些额外的操作。必须使用不同供应商的专用预编译器预编译程序。还必须生成数据访问计划并将其绑定到目标数据库。要增强应用程序的可移植性,可考虑使用本部分介绍的基于驱动程序的解决方案。
基于驱动程序的解决方案涉及与应用程序相连接的驱动程序管理器。驱动程序管理器提供了一组行业标准的应用程序编程接口 (API) 来访问数据源。编写应用程序来调用这些 API;然后编译该程序并将其与管理器的库链接起来。因为驱动程序符合该标准,所以应用程序可通过使用(或加载)正确的驱动程序轻松访问不同供应商的数据源。
在本部分中,将看到 DB2 支持的一些 API。在此系列的其他几篇教程中将了解每个 API 的详细信息。
CLI 和 ODBC API
DB2 Call Level Interface (CLI) 是面向 DB2 数据库服务器的 IBM 可调用 SQL 接口。这是用于数据库访问的 C/C++ API。正如可以使用嵌入式动态 SQL 语句编程一样,也可以使用 DB2 CLI 开发动态应用程序。在上述两种情形中,都是在运行时准备和处理 SQL 语句。只是嵌入式动态 SQL 需要预编译器,DB2 CLI 则不需要。只需简单地编译应用程序并将其链接到 DB2 CLI 驱动程序库即可。
DB2 CLI 基于 Microsoft 的 Open Database Connectivity (ODBC) 和 X/Open CLI 标准。在 ODBC 环境中,应用程序与使用 ODBC 驱动程序管理器的数据库服务器相连接。该管理器为应用程序连接到的数据库服务器动态地加载必需的驱动程序。ODBC 提供了几个级别的功能支持,DB2 CLI 目前遵从的是 ODBC 3.51。
要开发 DB2 CLI 应用程序,需要 DB2 客户机或 DB2 运行时客户机。它们包含了编译和链接 CLI 应用程序必需的所有头文件和库。另一方面,要开发 ODBC 应用程序,需要有 Microsoft 提供的 ODBC Developer's Software Kit。
图 1 为 DB2 CLI 和 ODBC 环境之间的简单比较:
图 1. DB2 CLI 与 ODBC 对比
在很多情况下,客户从软件供应商处获得或购买 ODBC/CLI 应用程序。他们只需一个运行时环境来运行 ODBC/CLI 应用程序。伴随 DB2 9 引入了一个新的驱动程序产品,即 IBM DB2 Driver for ODBC and CLI,您可以免费下载该产品。可以在 DB2 9 Information Center 找到该驱动程序的配置步骤。
.NET 框架和 ADO.NET API
.NET 框架是可帮助实现多种应用程序的开发平台。.NET 框架中有以下三个主要组件:
公共语言运行库 (CLR)
框架类库
.NET 兼容的语言
编译 .NET 兼容的语言(如 C# .NET 和 Visual Basic .NET)时,将产生称为中间语言 (IL) 的字节码。公共语言运行库是为 IL 代码提供代码执行服务的运行时环境。因为所有 .NET 兼容的语言都会被编译成 IL,所以 CLR 可集成以各种语言编写的代码。例如,Visual Basic (VB) 方法可访问 C# 方法,而 C# 中定义的类可从 VB 进行访问。
.NET 框架库是开发人员用来构建 .NET 应用程序的类和 API。它们提供了一组通用服务,如文件 I/O 和数据源访问,允许开发人员向程序添加功能,而无需顾忌编程语言。ADO.NET 是部分 .NET 框架的编程模型示例。像 Open Database Connectivity (ODBC) 和 Object Linking and Embedding Database (OLE DB) 一样,ActiveX Data Objects .NET (ADO.NET) 是 Microsoft 提供的另一个数据访问应用程序接口。这个更新后的数据访问模型结合了其前身 ActiveX Data Objects (ADO) 以及传统数据库访问、集成的 XML 支持和断开的数据架构的优良特性。
使用 ADO.NET 从 .NET 应用程序连接到 DB2 数据库可能有三种访问方法。可使用 Microsoft ODBC .NET 数据提供程序、Microsoft OLE DB .NET 数据提供程序或 DB2 .NET 数据提供程序。DB2 数据库和 .NET 应用程序间的数据访问替代方案如图 2 所示:
图 2. DB2 支持 ADO.NET
可以看到,ODBC 和 OLE DB 选项都需要将应用程序请求从 ODBC 和 OLE DB .NET 数据提供程序翻译成 DB2 ODBC 和 OLE DB 本地驱动程序。因为驱动程序间翻译产生了更长的代码路径和限制,所以强烈建议使用本地 DB2 .NET 数据提供程序选项。DB2 .NET 数据提供程序支持 .NET 框架 1.1 和 2.0 版本。
JDBC 和 SQLJ API
Java 平台已流行了很久。但人们仍在进行多种努力以扩展其功能,改善其性能。访问和操作 DB2 的 Java 程序可使用 Java Database Connectivity (JDBC) API 和 Embedded SQL for Java (SQLJ) 标准。二者都是供应商中立的 SQL 接口,通过标准化的 Java 方法提供对应用程序的数据访问。
JDBC 是 事实上的 标准 Java API,它使用动态 SQL 和一个功能强大的面向对象接口来访问关系数据库。JDBC 将动态 SQL 传递给 DB2 附带的 JDBC 驱动程序。DB2 通过 JDBC API 执行 SQL 语句,并将结果传回 Java 代码。JDBC 与 DB2 CLI 的类似之处在于,无需预编译或绑定 JDBC 程序,这是由于 JDBC 使用动态 SQL。
另一方面,SQLJ 程序包含静态嵌入式 SQL 语句。准备 SQLJ 程序时需要执行类似于预编译和绑定的步骤。在编译 SQLJ 源文件之前,必须用 SQLJ 翻译器对其进行翻译,从而创建本地 Java 源代码。翻译完成后,需要使用 DB2 为 Java 配置文件定制器 (db2profc) 创建 DB2 包。本系列的第七篇教程(标题为 “Java 编程”)将完整地讨论如何构建 SQLJ 应用程序。
用于 JDBC 和 SQLJ 的支持 DB2 的驱动程序
根据 Java 2 Platform, Enterprise Edition (J2EE) 规范,用于获得数据访问的 Java 方法和接口可包装为 JDBC 驱动程序。DB2 提供了以下两种类型的 JDBC 驱动程序:
用于 Linux™、UNIX® 和 Windows® 的 DB2 JDBC Type 2 Driver
用于 JDBC 和 SQLJ 的 IBM DB2 Driver(Type 2 和 type 4)
用于 Linux™、UNIX® 和 Windows® 的 DB2 JDBC Type 2 Driver 构建于本地 DB2 CLI 之上。此驱动程序已被否决并且 DB2 的后续版本将不再对其提供支持。可使用下面介绍的 JDBC 驱动程序作为替代。
用于 JDBC 和 SQLJ 的 IBM DB2 Driver 使用 DB2 家族中对所有数据库都通用的 Distributed Relational Database Architecture (DRDA) 协议。此驱动程序使用 Type 4 驱动程序架构将 Java 直接连接到 DB2 服务器。该驱动程序既包括 JDBC type 2 的行为,又包括 type 4 的行为,还包括 SQLJ 运行时支持。实现类的名称为 com.ibm.db2.jcc.DB2Driver。 图 3 中提供了对该驱动程序的说明:
图 3. 用于 JDBC 和 SQLJ 的 IBM DB2 Driver
以开放源码语言进行的 DB2 数据库应用程序开发
DB2 也提供 API 来支持常见的开放源码编程语言(包括 PHP、Perl 和 Python)。
PHP:Hypertext Processor (PHP) 是用于创建 Web 内容的开放源码服务器端脚本语言,并且是用于创建 Web 应用程序以访问 DB2 数据的功能强大的选择。可通过以下两种产品从 PHP 应用程序访问 DB2 数据库:
ibm_db2 是 IBM 为访问 DB2 数据库而编写、维护和支持的扩展。ibm_db2 扩展为执行对用户数据和数据库元数据的数据库操作提供过程 API。可使用 PHP 4 或 PHP 5 编译 ibm_db2 扩展。
PDO_ODBC 是 PHP Data Objects (PDO) 扩展的驱动程序,通过 PHP 5.1 中引入的面向对象的标准数据库接口提供对 DB2 数据库的访问。虽然此驱动程序的名称提到 ODBC,但可直接使用 DB2 库编译 PDO_ODBC 扩展,从而避免通信开销和 ODBC 驱动程序管理器的潜在干扰。
图 4 演示了这些产品:
图 4. DB2 的 PHP 接口
Perl
Perl 是一种功能强大、易于使用的编程语言,可以源代码或二进制形式免费获得。可使用 Perl 快速操作关系数据库中的大量数据。连接 Perl 脚本到关系数据库的标准是称作 DBI 的数据库接口模块。要从 Perl 脚本访问 DB2 数据库,需要用于 Perl 的 DB2 驱动程序。
如图 5 所示,Perl 脚本使用标准 API 与 DBI 进行通信。Perl DBI 模块只支持动态 SQL。该模块定义了一组方法、变量和约定,用来提供独立于实际所使用数据库的一致的数据库接口。对于编程人员希望使用的任何数据库,DBI 均为 API 提供了一致的接口。DBD::DB2 是允许 Perl 与 DB2 进行通信的 Perl 模块。
图 5. DB2 Perl 驱动程序
Python
Python 是翻译过的交互式面向对象的编程语言。 编程人员无需编译应用程序中的 Python 代码;因为 Python 源代码总是被翻译成字节码,所以编译过程是自动进行的。要使用 Python 应用程序访问 DB2 数据库,只需要一个 Python DB API 即可,如图 6 所示:
图 6. DB2 的 Python DB API 2.0 接口
Python 还拥有称作 Jython 的百分之百纯 Java 实现,可用于连接到 Java 组件。
XML 编程
您肯定听说过可扩展标记语言,或 XML。XML 是一种非常灵活的自描述语言。可轻松地扩展或转换成其他格式。它独立于平台和供应商并且易于共享。XML 基于分层数据模型,后者是存储非结构化信息的理想模型。
现在,根据需要获取有价值的信息非常重要。随需应变的业务必须具备集成的、灵活的系统,以便更快地响应市场更改。但是,信息通常以不同格式存储在不同种类的应用程序中。首先必须通过将这些应用程序封装为服务,以便对信息进行整合。设计为使用 Service-Oriented Architecture (SOA) 方法的系统真正地简化了此整合过程。 SOA 基于 Web 服务技术,而 Web 服务的核心是 XML。XML 不仅是 Web 服务的实现技术,也是新的 Web 2.0 技术(如 Ajax、RSS、网络日志等)的实现技术。图 7 阐释了 XML 的重要性:
图 7. XML 技术
很多技术和编程语言都支持 XML。DB2 9 在支持 XML 方面取得了重大进步。DB2 9 是混合或多结构的数据服务器,既可使用关系数据,又可使用 XML 数据。它是当前惟一的提供 XML 文档的本地 XML 存储的数据服务器。
结束语
总结
本教程向您介绍了 DB2 应用程序开发的基础知识。在进行任何开发工作之前,必须熟悉不同类型的数据库对象。在本教程中,介绍了几种高级的数据库对象。别名、序列对象和临时表经常用于简化应用程序代码。存储过程、函数和方法主要用来封装编程和数据库逻辑。我们还讨论了使用例程的若干优点,如减少网络通信量、增强安全性和提高代码重用率。
应根据应用程序逻辑的复杂程度封装过程和函数中的逻辑。存储过程用作程序的子例程,通常包含复杂的应用程序逻辑。另一方面,自定义函数是对 SQL 的扩展。它们可利用简单的语句和逻辑高效率地执行。
本教程还介绍了几种编程方法。嵌入式 SQL 编程允许将 SQL 语句嵌入到 C/C++、FORTRAN、COBOL 或 Java 语言编写的程序中。还强调了静态和动态 SQL 代码的特征。您必须理解静态和动态 SQL 语句用法的区别以便从中做出选择。
CLI、ODBC、ADO.NET、JDBC 之类的 API 和用于 PHP、Perl 和 Python 的 API 共同实现了动态程序。DB2 提供了本地驱动程序,使应用程序可通过这些接口处理 DB2 数据。另一方面,SQLJ 是用 Java 语言编写的静态程序。本教程还讨论了应用程序使用这些 API 与 DB2 进行连接的基本方法。
本教程对 DB2 应用程序开发的基本原理进行了介绍,您现在可以深入了解关于不同开发方法的更多信息。
- ››db2 对float类型取char后显示科学计数法
- ››DB2中出现SQL1032N错误现象时的解决办法
- ››DB2 锁升级示例
- ››db2诊断系列之---定位锁等待问题
- ››db2 命令选项解释
- ››DB2 最佳实践: 使用 DB2 pureXML 管理 XML 数据的...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 基础: 表空间和缓冲池
- ››DB2 XML 编程,第 1 部分: 理解 XML 数据模型
- ››DB2 pureScale 实战
更多精彩
赞助商链接