嵌入式静态、动态SQL

您是 DB2 应用程序开发新手吗?有了此实用指南,您将立刻掌握 DB2 的习惯与文化。

如果您已经习惯了基于一种数据库开发应用程序,那么切换到不同的数据库就像是到本国的另一个地区去旅行一样。基本语言虽然差不多,但是很可能不熟悉当地的方言。

当与那些将自己的应用程序从其他供应商的产品迁移到 DB2 Universal Database(DB2 UDB)的人们一起工作时,我发现如果他们一开始能掌握 DB2 环境特有的一些基本概念和术语,就可以取得更大的成功。

这里是特定于 DB2 应用程序开发的几个关键概念的快速指南。关于更详细的探索,请参阅 DB2 Application Development Certification Guide(Prentice Hall,2000 年)、DB2 Application Development Guide(可在 ibm.com/software/ data/db2/udb/ ad/v7/adg.html上获取)和 Application Building Guide( ibm.com/software/ data/db2/java/ v6/abg.html)。

嵌入式 SQL

DB2 通过其预编译器支持 C、C++、Java(SQLJ 和 Java 数据库连接)、COBOL 和 FORTRAN。您可以采用其中一种宿主编程语言编写包含 SQL 语句的应用程序。嵌入在应用程序中的 SQL 语句提供到数据库的接口,宿主语言为应用程序的执行提供必要的支持。而 DB2 预编译器可以将 SQL 语法直接转换为 DB2 运行时服务应用程序编程接口(API)调用。





回页首


静态 SQL

嵌入式静态 SQL 和嵌入式动态 SQL 都要用到 DB2 预编译处理。然而,在已知数据库将被查询哪些问题时(例如,在航空订票系统中),就可以使用静态 SQL 语句。对于静态 SQL 语句,在进行预编译之前就知道 SQL 语句的类型以及表的列名。而未知的元素是语句进行搜索或更新的特定数据值,并且这些值是用宿主语言变量来表示的。宿主变量包含的是数据,而不是 SQL 语句。在运行应用程序之前要准备或者构建静态 SQL 语句。

清单 1 展示了 C 程序中的样本嵌入式静态 SQL。请注意容纳数据的宿主变量(例如, EXEC SQL FETCH c1 INTO :pname, :dept; )和由 EXEC SQL 为预编译目的而分隔的 SQL 语句的用法。

为了使用包含嵌入式 SQL 的程序,不仅要进行典型的准备步骤(编译、链接和运行),还必须执行 DB2 预编译和绑定步骤(见 图 1)。而这些步骤将为数据库管理器创建执行时需要的程序包:

1. 预编译:将嵌入式 SQL 源语句转换为数据库管理器可使用的形式。

2. 编译和链接:创建必要的目标模块。

3. 绑定:创建运行程序时数据库管理器将使用的程序包。

预编译器(带有 BINDFILE 和 PACKAGE 选项的 PREP 命令)将嵌入式 SQL 语句转换为注释。接着,它将生成宿主编译器可处理的 DB2 运行时 API 调用。然后,预编译器将生成相应信息(存储在程序包或绑定文件中),数据库管理器将使用这些信息对数据库执行 SQL 语句。

预编译器选项 BINDFILE 创建一个绑定文件,用于存储创建程序包所必要的数据。

预编译器选项 PACKAGE 进行隐式绑定并且将程序包存储在已连接的数据库中。程序包是存储在数据库中的一种对象,其中包括执行单个源文件中的特定 SQL 语句所需的信息,这类信息又被称为存取路径。


清单 1:带有嵌入式静态 SQL 的 C 程序
嵌入式静态、动态SQL_第1张图片

图 1:静态 SQL 的 DB2 预编译和绑定步骤
嵌入式静态、动态SQL_第2张图片




回页首


动态 SQL

清单 2 展示了带有嵌入式动态 SQL 的样本 C 代码。请注意嵌入式动态 SQL 的用法,它是通过宿主变量来容纳 SQL 语句的 —— 例如, strcpy (qstring, "INSERT INTO name VALUES (?,?)" ); 。该行代码将 SQL 语句存放在 qstring 中。请注意,其中存放的不是数据,而是获取数据的命令。这些语句将由 EXEC SQL PREPARE s1 FROM :qstring; 语句在运行时进行预编译。

注意,嵌入式动态 SQL 是包含在嵌入式静态 SQL 应用程序之中的。 清单 2 中, EXEC SQL PREPARE s1 FROM :qstring; EXEC SQL EXECUTE s1 USING :trialname, :trialvalue; 都是动态语句。因此,对于代码中的静态 SQL 片断要采取相同的程序准备步骤。但是,动态 SQL 需要增加 PREPAREEXECUTE 语句,以便在程序运行期间创建存取路径和执行 SQL 语句(见 图 2)。


清单 2: 带有嵌入式动态 SQL 的 C 程序
嵌入式静态、动态SQL_第3张图片

图 2:动态 SQL 的 DB2 预编译和绑定步骤
嵌入式静态、动态SQL_第4张图片

PREPARE 从字符串形式的语句创建可执行的 SQL 语句。可执行形式被称为已准备语句。而字符串形式则被称为字符串语句。 EXECUTE 语句执行已准备的 SQL 语句。 EXECUTE IMMEDIATE 将字符串形式的语句准备为可执行形式的 SQL 语句,执行该 SQL 语句,并且不使用宿主变量。

既然已经理解了静态和动态 SQL,现在就让我们用 JDBC 和 SQLJ 将它们与 DB2 编程联系起来。





回页首


JAVA 方法

Java 以支持“一次编写,到处运行”的程序而著名。那是如何实现的呢?Java 可以分两步进行编译和执行。首先,将 Java 代码编译成与机器无关的 字节码(bytecode)。字节码是用于理想化 Java 虚拟机的汇编语言。第二步,由运行系统执行该字节码。运行系统既可以是一个解释器(仿真器),也可以是一个即时编译器,它首先将字节码编译成本机码,然后执行编译结果。该过程的两个步骤可以在完全独立的平台上实现。

Java 程序可以从独立的应用程序、Web 浏览器中运行的 applet 或者由 Web 应用程序服务器(如 IBM WebSphere)运行的 servlet 等访问 DB2 数据库。

Java 应用程序在相同的位置存储并执行。Java applet 是存储在 Web 服务器上并在本地 PC 浏览器中执行的 Java 程序。Java servlet 是在应用程序服务器上存储并执行而在本地浏览器中查看执行结果的 Java 程序。





回页首


数字游戏:JDBC

Java 数据库连接(JDBC)的版本号和所有与之相关的东西都是十分混乱的。首先,JDBC 有不同的版本。然后,JDBC 驱动程序有不同的类型,可以被不同版本的 Java 使用。每个 Java 版本都有自己的别名和 Java 开发工具箱(JDK)。

DB2 UDB 支持 JDBC 1.2、2.0 和 2.1 版(存在一些操作系统限制)。JDBC 版本使用不同类型的 JDBC 驱动程序。而 JDBC 驱动程序将充当接口,以允许将 JDBC 实现的通用函数和方法转换为数据库特定调用。JDBC Type 1 驱动程序已经构建于 Java 中并且提供了 JDBC-ODBC 桥。JDBC Type 2 驱动程序是应用程序驱动程序,需要通过本地 DB2 客户机来执行对远程数据库的连接。JDBC Type 3 是网络驱动程序,是一个纯 Java 实现,它需要与提供 DB2 JDBC applet 服务器的中间件交流。JDBC Type 4 驱动程序也是一个纯 Java 实现,它还带有分布式关系型数据库体系结构(DRDA)应用程序请求功能。使用 JDBC Type 4 驱动程序的应用程序不需要为连接与 DB2 客户机交互。

无论使用哪种版本的 JDBC 都有相关的 JDK 和 Java 运行时环境。关于该主题的更多细节,请参阅 DB2 开发者园地中 Paul Zikopoulos 所写的文章“An Overview of DB2 and Java Database Connectivity”,可在 http://www.ibm.com/developerworks/cn/dmdd/library/techarticles/0307zikopoulos/0307zikopoulos.shtml 上在线获得。





回页首


JAVA 程序

DB2 有编写动态 SQL 程序的 JDBC 驱动程序。有了 JDBC API,就不必进行预编译。JDBC API 是核心 Java API 标准的组成部分,也是 Java JDK 必不可少的一部分。JDBC 没有在 Java 代码中直接嵌入 SQL。JDBC 允许您编写对数据库进行动态 SQL 调用的 Java 程序。 它实现了一组方法(类似于 ODBC),以允许将 SQL 语句传递给数据库并且操纵结果。

JDBC 由一个高级 API 和多个用于连接不同数据库的低级驱动程序组成。它指定 Java 接口、类和异常,以支持连接、数据结果集处理,等等。

清单 3 展示了如何编写使用 JDBC 应用程序驱动程序访问 DB2 数据库的 Java 应用程序。编写 JDBC 应用程序与编写使用 CLI 访问数据库的 C 应用程序相似。在创建使用 JDBC 接口的 Java 应用程序的时候,要导入 java.sql 包以及根据 Java 规范调用方法。


清单 3:使用 JDBC 应用程序驱动程序访问 DB2 数据库的 Java 应用程序
嵌入式静态、动态SQL_第5张图片

清单 3 中的 Java 程序导入适当的 Java 包和类,加载适当的 JDBC 驱动程序,连接由 JDBC 规范中所定义的 URL 指定其位置的数据库,将 SQL 语句传递给数据库,接收结果并关闭连接。

您不必预编译或者绑定 JDBC 应用程序。在给程序编码之后,就像对任何其他 Java 程序一样编译它,要使用 JDK 中的 javac 编译器将基于 JDBC 的 Java 程序编译成 Java 字节码。





回页首


JAVA SQLJ

SQLJ 是一组对核心 Java 类的 ANSI 标准扩展,提供了更简单的编程模型并支持创建静态 SQL。在编译产生 Java 源代码之前,还必须用 SQLJ 转换器转换 SQLJ 源文件。

DB2 有一个 SQLJ 驱动程序,用于在 Java 代码中嵌入静态 SQL 语句。SQLJ API 也需要进行类似于预编译(转换)的处理。这些概念与我们在嵌入式静态 SQL 和嵌入式动态 SQL 小节中所讨论的十分相似。

SQLJ API 应用程序将 JDBC 用作连接数据库和处理 SQL 错误等工作的基础,但还可以在 SQLJ 源文件中包含嵌入式静态 SQL 语句。

SQLJ 中的静态 SQL 语句出现在 SQLJ 子句中。SQLJ 子句是一种机制,Java 程序中的 SQL 语句通过此机制与数据库通信。SQLJ 转换器(类似于预编译器)通过 SQLJ 子句的结构(以标志 #sql 开始并以分号结束)以将其与 SQL 语句相区别。嵌入式 SQL 语句的参数由出现在 SQL 语句中的宿主变量来传递,并以冒号前缀开始。

清单 4 展示了如何编写使用 JDBC 应用程序驱动程序访问 DB2 数据库的 SQLJ 应用程序。SQLJ 应用程序导入适当的 Java 包和类,加载适当的 JDBC 驱动程序,并使用 DB2 子协议(subprotocol)连接到由 JDBC 规范中所定义的 URL 指定其位置的数据库。


清单 4
嵌入式静态、动态SQL_第6张图片

DB2 SQLJ 程序准备需要三个步骤:

1. 运行 SQLJ 转换器。SQLJ 转换器类似于用于支持其他语言(如 C)中的嵌入式静态 SQL 的预处理器。它负责从源文件中提取嵌入式 SQL 命令并将之替换为对 SQLJ 运行时库的调用。其结果就是已修改的可使用 Java 编译器进行编译的 Java 源代码程序(.java 文件),以及包含程序中 SQL 操作信息的零个或多个 SQL 配置文件。

2. 使用 javac 命令编译由转换器输出的已修改的 Java 源代码。这将产生包含 Java 字节码的一个或多个 .class 文件。

3. 为 DB2 定制 SQLJ 配置文件。配置文件是与供应商无关的,因此,必须定制它们。默认情况下,SQLJ 配置文件将 .ser 作为扩展名。定制过程将通用的 SQLJ 配置文件转换为 DB2 特定的绑定文件,可通过将绑定文件绑定到程序包来将DB2 特定的绑定文件绑定到 DB2。

参考资料

IBM Software Migration Project Office
ibm.com/solutions/ softwaremigration

DB2 UDB Programming Fastpath Course(免费)
ibm.com/software/ data/db2/ct10crs





回页首


达到熟练

如果您正计划将应用程序从其他数据库环境迁移到 DB2,就需要掌握一些特定于 DB2 的概念。本文只是作为一个简介。我提及的那些出版物提供了更加完整的教学。如果您已经是一个熟练的开发者,那么将发现到 DB2 的转换是十分平坦的。



关于作者

 

Debra Eaton 是 IBM 的 Software Migration Project Office 团队的软件信息技术专家。可通过 [email protected]与她联系。


http://www.ibm.com/developerworks/cn/data/library/techarticles/mag_02q2eaton/eaton.html

你可能感兴趣的:(嵌入式静态、动态SQL)