1、基于 C 语言的 DB2 数据库开发 1-15 基于 C 语 言 的 DB2 数据库开发 凌阳, 拇指 凌阳 徐正荣 凌阳, 拇指 凌阳 杭州恒生电子股份有限公司 , 拇指 浙江 凌阳, 拇指 凌阳 杭州 凌阳, 拇指 凌阳 310053 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 摘要 : 本文探讨了 C 语言环境下 DB2 数据库系统的开发过程 , 拇指 着重分析了 DB2 的 开发关键过程及 不同于其他数据库 的特别 之处 , 拇指 并提供 了解决 关键性问题的程序示例 。 食指 凌阳, 拇指 凌阳 关键词 : C 语言; 数据库开发 ; DB2; 嵌入式 SQL 凌阳, 拇指 凌阳 凌阳,
2、 拇指 凌阳 引言 2 凌阳, 拇指 凌阳 1 DB2 应用程序开发概述 2 凌阳, 拇指 凌阳 1.1 嵌入式 SQL 编程 2 凌阳, 拇指 凌阳 1.2 宿主语言 2 凌阳, 拇指 凌阳 1.3 静态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 2 凌阳, 拇指 凌阳 1.4 动态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 2 凌阳, 拇指 凌阳 1.5 宿主变量 (Host 凌阳, 拇指 凌阳 variables)2 凌阳, 拇指 凌阳 2.DB2 静态 SQL 程序开发 2 凌阳, 拇指 凌阳 2.1 静态 SQL 例程 3 凌阳, 拇指 凌阳 2.2 静态 S
3、QL 程序的结构和特点 3 凌阳, 拇指 凌阳 2.3 凌阳, 拇指 凌阳 DB2 预编译及绑定 4 凌阳, 拇指 凌阳 2.3.1 预编译 4 凌阳, 拇指 凌阳 2.3.2 凌阳, 拇指 凌阳 编译和链接 5 凌阳, 拇指 凌阳 2.3.3 绑定 5 凌阳, 拇指 凌阳 2.3.4 和其他数据库的区别 5 凌阳, 拇指 凌阳 2.4 凌阳, 拇指 凌阳 DB2 宿主变量的定义和引用 5 凌阳, 拇指 凌阳 2.4.1 凌阳, 拇指 凌阳 宿主变量的声明 5 凌阳, 拇指 凌阳 2.4.2 凌阳, 拇指 凌阳 宿主变量的约定和限制 6 凌阳, 拇指 凌阳 2.4.3 针对宿主变量限制的解决办
4、法 6 凌阳, 拇指 凌阳 3 凌阳, 拇指 凌阳 DB2 动态 SQL 程序开发 7 凌阳, 拇指凌阳 3.1 动态嵌入式 SQL 语句的类型 7 凌阳, 拇指 凌阳 3.1.1 除 SELECT 之外的动态 SQL 语句 7 凌阳, 拇指 凌阳 3.1.2 凌阳, 拇指 凌阳 输出结果列固定的动态 SELECT 语句 7 凌阳, 拇指 凌阳 3.1.3 全部内容完全动态的 SQL 语句 7 凌阳, 拇指 凌阳 3.1.4 参数化的动态语句 7 凌阳, 拇指 凌阳 3.2 凌阳, 拇指 凌阳 动态 SQL例程 7 凌阳, 拇指 凌阳 3.3 凌阳, 拇指 凌阳 SQLDA 的组成和存储格式
5、9 凌阳, 拇指 凌阳 3.4 凌阳, 拇指 凌阳 SQLDA 的使用规则 10 凌阳, 拇指 凌阳 3.5 动态绑定与静态绑定的比较 11 凌阳, 拇指 凌阳 4 凌阳, 拇指 凌阳 DB2 程序开发的实用示例 11 凌阳, 拇指 凌阳 4.1 如何存取 DECIMAL 类型的数据 11 凌阳, 拇指 凌阳 4.2 凌阳, 拇指 凌阳 如何动态往指定表中插入数据 13 凌阳, 拇指 凌阳 5 凌阳, 拇指 凌阳 结束语 14 凌阳, 拇指 凌阳 参考文献 14 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 基于 C 语言的 DB2 数据库开发 2-15 引言 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳
6、 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 IBM 公司的 DB2 数据库 作为当前三大 主流 数据库 之一 , 拇指 在数据库系统开发中 占优很大的市场份额 , 拇指 特别是 金融行业中 , 拇指 因往往使用 IBM 自身 的 AIX 系统 以及AS400/RS600 等 服务器 , 拇指 有关的应用系统开发更 是 越来越偏重于采用 DB2 数据库 。 食指 然而 , 拇指 在开发过程中 , 拇指 由于 DB2 内部的机制及编程方面 的限制 , 拇指 使 刚开始从事 DB2 数据库开发或从其他数据 库移植到 DB2 的开发人员 感到迷惑重重 , 拇指 难以从其他数据库的开发
7、习惯中适应过来 。 食指 另外 市面上 不像 ORACLE/SQL 凌阳, 拇指 凌阳 SERVER 那样有成排的资料书籍 ,拇指 DB2 除了 IBM 自己提供的英文资料外 , 拇指 对开发有参考价值的 技术资料相对 很少 。 食指 因此笔者结合自己最近开发的几 套 DB2 应用系统 , 拇指 着重从基于 C 语言环境下的 DB2 开发过程做一探讨 , 拇指 并针对和其他数据库开发的不同之处 , 拇指 以及部分关键性问题的解决作详细分析和应用示例 。 食指 凌阳, 拇指 凌阳 1 DB2 应用程序开发概述 凌 阳, 拇指 凌阳 在进行 DB2 应用开发之前 , 拇指 了解 DB2 应用程序的
8、结 构 , 拇指 掌握相关概念 是很必要的 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 1.1 嵌入式 SQL 编程 凌阳, 拇指 凌阳 嵌入式 SQL应用程序就是将 SQL语句嵌入某个宿主语言中 , 拇指 SQL语句提供数据库接口 ,拇指 存取并处理 凌阳, 拇指 凌阳 DB2 凌阳, 拇指 凌阳 数据库中的数据 , 拇指 宿主语言提供应用程序的其他执行功能 。 食指 嵌入式SQL 语句包括静态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句和动态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 1.2 宿主语言 凌阳, 拇
9、指 凌阳 用于创建主程序的程序设计语言称 为宿主语言 , 拇指 例如 DB2 可以 用 凌阳, 拇指 凌阳 C/C+、 COBOL、FORTRAN、 Java 凌阳, 拇指 凌阳 (SQLJ) 凌阳, 拇指 凌阳 以及 凌阳, 拇指 凌阳 REXX 凌阳, 拇指 凌阳 程序设计语言来编写嵌入式 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 应用程序 , 拇指这些程序设计语言都称为宿主语言 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 1.3 静态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 凌阳, 拇指 凌阳 在编译前就知道 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句
10、 内容 以及 以及将 要存取的 表名和列名 。 食指 唯一未知的是语句正搜索或更新的特定数据值 。 食指 可以用宿主语言变量表示那些值 。 食指 在运行应用程序之前 , 拇指要预编译、编译和捆绑静态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 1.4 动态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 凌阳, 拇指 凌阳 是应用程序在运行期构建并执行的那些语句 。 食指 一个提示最终用户输入 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句的关键部分(如要搜索的表和列的名称)的交互式应用程序是动态 凌阳, 拇指 凌阳 SQ
11、L 凌阳, 拇指 凌阳 一个很好的 示例 。 食指 凌阳, 拇指 凌阳应用程序在运行时构建 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 , 拇指 然后提交这些语句进行处理 。 食指 凌阳, 拇指 凌阳 可以编写只有静态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句或只有动态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 语句 , 拇指 或者兼有两者的应用程序 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 1.5 宿主变量 (Host 凌阳, 拇指 凌阳 variables) 凌阳, 拇指 凌阳凌阳, 拇指 凌阳 在主应用程序中由嵌入式 SQL 语句引用的变量 。 食指
12、宿主变量是该应用程序中的程序设计变量 , 拇指 并且是在数据库 中的表与应用程序工作区之间传送数据的主要机制 。 食指 我们称之为“宿主变量” , 拇指 是为了与通常方法声明的源语言变量区分开来 , 拇指 通常方法声明的变量不能被 SQL 语句引用 。 食指 宿主变量在宿主语言程序模块中以一种特殊的方式声明:必须在 BEGIN 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 和 END 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 程序节内定义 。 食指 凌阳, 拇指 凌阳 2.DB2 静态 SQL 程序开发 凌 阳, 拇指 凌阳 基于 C 语
13、言的 DB2 数据库开发 3-15 2.1 静态 SQL 例程 凌阳, 拇指 凌阳 在程序结构上 , 拇指 DB2 和其他数据库 非常相似 , 拇指 下面先来看一个静态 SQL 程序的 C 语言例子 static.sqc: 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 例程 1静态 SQL 例程 凌阳, 拇指 凌阳 2.2 静态 SQL 程序的结构和特点 凌阳, 拇指 凌阳 从上面的例程可以看到 , 拇指 典型的静态 SQL 程序结构包含以下关键部分: 凌阳, 拇指 凌阳 包括结构 SQLCA: 凌阳, 拇指 凌阳 INCLUDE 凌阳, 拇指 凌阳 SQLCA 语句定义和声明了 SQLCA 结构
14、, 拇指 SQLCA 结构中定义了 SQLCODE 和 SQLSTATE 域 。 食指 数据库管理器在执行完每一条 SQL 语句或者每一个数据库管理器 API 调用 , 拇指 都要更新 SQLCA 结构中的 SQLCODE 域的诊断信息 。 食指 凌阳, 拇指 凌阳 声明宿主变量: SQL 凌阳, 拇指 凌阳 BEGIN 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 和 END 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 凌阳, 拇指 凌阳 语句界定宿主变量的声明 。 食指 宿主变量用来将数据传递给数据库管理或者接收数据库管理器返回的数据
15、。 食指 在 SQL 语句中引用宿主变量时 , 拇指 必须在宿主变量前加前缀冒号 (:)。 食指 详细信息看 2.4 节 。 食指 凌阳, 拇指 凌阳 基于 C 语言的 DB2 数据库开发 4-15 连接到数据库:应用程序 必须先连接到数据库 , 拇指 才能对数据库进行操作 。 食指 这个程序连接到 SAMPLE 数据库 , 拇指 请求以共享方式访问 。 食指 其他应用程序也可以同时以共享访问方式连接数据库 凌阳, 拇指 凌阳 输入宿主变量赋值 :在 SQL 语句执行之前 , 拇指 如果要引用宿主变量作为条件或插入值(称之为输入宿主变量) , 拇指 则要求先进行赋值 。 食指 凌阳, 拇指 凌
16、阳 提取或处理数据 。 食指 SELECT 凌阳, 拇指 凌阳 INTO 语句基于一个查询提取了一行值 。 食指 这个例子从EMPLOYEE 表中 , 拇指 将 LASTNAME 列的值为 JOHNSON 的相应行的 FISRTNME 列 的值提取出来 , 拇指 置于宿主变量 凌阳, 拇指 凌阳 firstname 中 。 食指 凌阳, 拇指 凌阳 处理错误 : CHECKERR 凌阳, 拇指 凌阳 宏 /函数是一个执行错误检查的外部函数 , 拇指 判断前面的 SQL 语句是否执行成功 。 食指 凌阳, 拇指 凌阳 程序运行结束 , 拇指 断开数据库连接 。 食指 凌阳, 拇指 凌阳 凌阳,
17、拇指 凌阳 2.3 凌阳, 拇指 凌阳 DB2 预编译及绑定 凌阳, 拇指 凌阳 为了使用包含嵌入式 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 的程序 , 拇指 不仅要进行典型的准备步骤(编译、链接和运行) ,拇指 还必须执行 凌阳, 拇指 凌阳 DB2 凌阳, 拇指凌阳 预编译和绑定步骤 。 食指 这些步骤将为数据库管理器创建执行时需要的程序包 其编译过程如(图一)所示: 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 图 1预编译过程 凌阳, 拇指 凌阳 2.3.1 预编译 凌阳, 拇指 凌阳 将嵌入式 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 源语句转换为数据库管理器可使用的形式 。
18、 食指 以例程 1 为例 , 拇指 预编译 命令如下: 凌阳, 拇指 凌阳 DB2 凌阳, 拇指 凌阳 PREP 凌 阳, 拇指 凌阳 static.sqc 凌阳, 拇指 凌阳 PACKAGE 凌 阳 , 拇指 凌阳 USING 凌阳, 拇指 凌阳 mypack 凌 阳, 拇指 凌阳 BINDFILE 凌 阳, 拇指 凌阳 USING 凌 阳 , 拇指 凌阳mytest.bnd凌 阳, 拇指 凌阳 其中 PACKAGE、 BINDFILE 为可选项 , 拇指 当 PACKAGE 选项(默认的) , 拇指 或者没有指定任何 BINDFILE、 SYNTAX、 SQLFALG 选项 , 拇指 预编
19、译后自动在数据库中生成以文件名前 8 位命名的程序包 , 拇指 USING 凌 阳 , 拇指 凌阳 mypack 凌阳, 拇指 凌阳 指定生成的程序包名 为 mypack;BINDFILE 在预编译时同时产生文件名前 8 位 .bnd, 拇指 USING 凌阳, 拇指 凌阳 mytest.bnd 指 定生成的绑基于 C 语言的 DB2 数据库开发 5-15 定文件名为 mytest.bnd 文件 ( 详细命令请参考 IBM 提供的 IBM 凌阳, 拇指 凌阳 DB2 凌阳, 拇指 凌阳 Universal 凌阳, 拇指 凌阳Database 凌阳, 拇指 凌阳 Command 凌阳, 拇指 凌
20、阳 Reference) 。 食指 凌阳, 拇指 凌阳 该步骤最多可以生成 4 类文件: 凌阳, 拇指 凌阳 修改后的文件:该文件中 SQL 语句被屏蔽 , 拇指 转换成可以被宿主语言直接调用的 API 函数 , 拇指 本例中此文件为 static.c。 食指 凌阳, 拇指 凌阳 程序包: 程序包存放在对应数据库中 , 拇指 里面 包含数据库系统在捆绑时对特 定 SQL 语句所产生的访问策略 。 食指 凌阳, 拇指 凌阳 绑定文件: 如果使用了 BINDFILE 选项将产生该文件 , 拇指 每一个独立预编译的源代码文件都将创建一个程序包 。 食指 凌阳, 拇指 凌阳 消息文件:如果使用了 ME
21、SSAGES 选项 , 拇指 预编译器将警告和错误信息重定向到指定的文件中 , 拇指 否则被写到标准输出上 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.3.2 凌阳, 拇指 凌阳 编译和链接 凌阳, 拇指 凌阳 宿主语 言 自身的编译链接过程 , 拇指 创建必要的目标模块 , 拇指 链接生成执行文件 。 食指 如 C 语言采用 CC 命令生成 .o 文件 , 拇指 再 链接相关库产 生执行文件 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.3.3 绑定 凌阳, 拇指 凌阳 如果预编译时使用了 BINDFILE 选项 , 拇指 并且 预编译时和运行在不同的机器环境上 , 拇指
22、则要求把预编译生成的 *.bnd 文件拷贝到运行环境 , 拇指 再执行 DB2 凌阳, 拇指 凌阳 BIND 命令 , 拇指 以便在运行环境数据库中生成 数据库管理器将使用的程序包 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.3.4 和其他数据库的区别 凌阳, 拇指 凌阳 从上面的分析可以看到 DB2 的编译过程 不同于其他数据库 (如 ORACLE, 拇指 SYBASE, 拇指INFORMIX 等 ), 拇指 预编译时将源文件中的 SQL 语句注释掉 , 拇指 替换为对应的数据库运行时API 调用外 , 拇指 DB2 还将产生存取程序包 或绑定文件(如果使用的 BINDFILE 选
23、项 , 拇指 相应的要增加 DB2 凌阳, 拇指 凌阳 BIND 操作) , 拇指 这是其他数据库所没有的 。 食指 正因为如此 , 拇指 在预编译或绑定时 , 拇指 如果程序中包括静态 SQL 语句 , 拇指 编译时必须要求: 凌阳, 拇指 凌阳 连接到程序中涉及的数据库 。 食指 凌阳, 拇指 凌阳 SQL 语句中涉及的表和字段要求存在(创建类的语句除外) 。 食指 凌阳, 拇指 凌阳 当数据库结构修改或数据库统计信息更新后 , 拇指 必须重新编译程序 。 食指 静态 SQL 语句的性能决定于应用程序最后一次被捆绑时数据库的统计信息 。 食指 凌阳, 拇指 凌阳 然而 , 拇指 如果这些统
24、计信息改变了 , 拇指 那么比较起来 , 拇指 等效的动态 SQL 语句的性能可能好些 。 食指 在某个使用静态 SQL 的应用程序捆绑之后 , 拇指 数据库增加了一个索引 , 拇指 如果这个应用程序不重新捆绑 , 拇指 就不能利用这个索引 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 4) DB2INCLUDE 变量指向相关 头文件 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 5) xlC 凌阳, 拇指 凌阳 p 凌阳, 拇指 凌阳 DMYMACRO 凌阳, 拇指 凌阳 =1 凌阳, 拇指 凌阳 - 凌
25、阳, 拇指 凌阳 processor-command。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 6) EXEC 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 INCLUDE 中不能出现双引号 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 7) char 类型最长为 254 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.4 凌阳, 拇指 凌阳 DB2 宿主变量的定义和引用 凌阳, 拇指 凌阳 2.4.1 凌阳, 拇指 凌阳 宿主变量的声明 凌阳, 拇指 凌阳 在 C 语言环境下 , 拇指 DB2 宿主变量
26、声明 表示如下: 凌阳, 拇指 凌阳 EXEC 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 BEGIN 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION; 凌阳, 拇指 凌阳凌阳, 拇指 凌阳 short 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 dept=38, 凌阳, 拇指 凌阳 age=26; 凌阳, 拇指 凌阳凌阳, 拇指 凌阳 基于 C 语言的 DB2 数据库开发 6-15 double 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 salary; 凌阳, 拇指 凌阳
27、凌阳, 拇指 凌阳 char 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 CH; 凌阳, 拇指 凌阳凌阳, 拇指 凌阳 char 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 name19, 凌阳, 拇指 凌阳 NAME29;凌阳, 拇指 凌阳 /* 凌阳, 拇指 凌阳 C 凌阳, 拇指 凌阳 注释 凌阳, 拇指 凌阳 */ 凌阳, 拇指 凌阳凌阳, 拇指 凌阳 short 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指
28、 凌阳 凌阳, 拇指 凌阳 nul_ind; 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 char 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 *address, 凌阳, 拇指 凌阳 *telno10;凌阳, 拇指 凌阳 EXEC 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 END 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION;凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.4.2 凌阳, 拇指 凌阳 宿主变量的约定和限制 凌阳, 拇指 凌阳 DB2 宿主变量的定义和引用遵循以下常规 约定: 凌阳, 拇指 凌阳 所有
29、被嵌入 SQL 引用 的宿主变量必须在 BEGIN 和 END 凌阳, 拇指 凌阳 DECLARE 语句界定的代码区里声明; 凌阳, 拇指 凌阳 在一个源文件中 , 拇指 可以有多个界定区 , 拇指 可以出现在任何变量声明允许的地方 ; 凌阳, 拇指 凌阳 BEGIN 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 和 END 凌阳, 拇指 凌阳 DECLARE 凌阳, 拇指 凌阳 SECTION 语句必须成对出现 , 拇指 并且不能嵌套; 凌阳, 拇指 凌阳 宿主变量的数据类型必须与列的数据类型匹配 , 拇指 而且尽量避免数据转换和截取; 凌阳, 拇指 凌阳 在同一作
30、用域内 , 拇指 宿主变量和常规变 量不能同名; 凌阳, 拇指 凌阳 宿主语言标号在 SQL 语句中引用时前面加冒号 。 食指 凌阳, 拇指 凌阳 宿主变量声明可以使用 SQL 凌阳, 拇指 凌阳 INCLUDE 语句指定 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 另外 , 拇指 DB2 宿主变量的定义还有以下限制: 凌阳, 拇指 凌阳 宿主变量名不能以 EXEC、 SQL、 sql 开头; 凌阳, 拇指 凌阳 宿主变量应该被看作是模块程序的全局变量 , 拇指 而不是定义所在函数的局部变量 , 拇指 因此在同一个嵌入式 SQL 程序文件中 , 拇指 不同函数间申明的宿主变量不能同名!
31、凌阳, 拇指 凌阳 不能引用宏定义 , 拇指 如 char 凌阳, 拇指 凌阳 bufLEN_MAX是非法的 , 拇指 必须将 LEN_MAX 替换为常量数据 。 食指 凌阳, 拇指 凌阳 char 凌阳, 拇指 凌阳 *方式声明的宿主变量和 C 语言常规变量有异义:在 C 语言中 , 拇指 char 凌阳, 拇指 凌阳 *address 表示一个指向字符串变量的指针 , 拇指 而如果是 DB2 宿主变量的话 , 拇指 则表示一个指向字符的指针 , 拇指 char 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 *address60在 DB2 中表示一个指向长度为 60 的字符串变量的指针 , 拇指
32、而这在 C 语言中表示 60 个指向字符串变量的指针数组! 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 2.4.3 针对宿主变量限制的解决办法 凌阳, 拇指 凌阳 上面的限制对刚开始接触 DB2 开发或从其他数据库移植到 DB2 时感到非常困惑 , 拇指 通过实践和咨询 IBM 技术人员 , 拇指 笔者对上面的限制采用下面的办法进行解决 , 拇指 希望能给读者有所帮助 。 食指 凌阳, 拇指 凌阳 对于限制 2) , 拇指 可以 下列方法 (要求同名的宿主变量类型相同或兼容) : 凌阳, 拇指 凌阳 将本文件中所以相同名称的宿主变量在文件开始处统一声明为全局变量 , 拇指 再取消函数内的局部宿主变
33、量声明 。 食指 凌阳, 拇指 凌阳 或 者 在第一 次 出现 要引用该宿主变量的地 方声明为宿主变量 , 拇指 在其他函数中声明为常规局部变量(此宿主变量在该函数仍可以作为宿主变量引用) 凌阳, 拇指 凌阳 对于限制 3) , 拇指 在预编译 ( DB2 凌阳, 拇指 凌阳 PREP 命令) 可以增加 PREPROCESSOR 选项 , 拇指 则预编译器会首先处理 所有 SQL 凌阳, 拇指 凌阳 INCLUDE 语句引用的文件 进行内容替换 , 拇指 预编译再用替换后的文件进行编译 。 食指 凌阳, 拇指 凌阳 对于限制 4) , 拇指 如果采用了 char 凌阳, 拇指 凌阳 *pVar
34、 的方式 , 拇指 则只能修改为 char 凌阳, 拇指 凌阳 sVarLEN的方式了 ,基于 C 语言的 DB2 数据库开发 7-15 拇指 并需要修 改指针方式下的 凌阳, 拇指 凌阳 “ pVar=sString” 凌阳, 拇指 凌阳 为 凌阳, 拇指 凌阳 strcpy(sVar,sString)。 食指 凌阳, 拇指 凌阳 3 凌阳, 拇指 凌阳 DB2 动态 SQL 程序开发 凌 阳, 拇指 凌阳 为了增加应用程序的灵活性 , 拇指 允许应用程序在运行过程中动态地产生并执行 SQL 语句 ,拇指 我们称其为动态嵌入式 SQL 语句 , 拇指 一个提示最终用户输入 凌阳, 拇指 凌阳
35、 SQL 凌阳, 拇指 凌阳 语句的关键部分(如要搜索的表和列的名称)的交互式应用程序是动态 凌阳, 拇指 凌阳 SQL 凌阳, 拇指 凌阳 一个很好的示例 。 食指 由于动态嵌入式 SQL 语句的内容(或其中一部分内容)是在程序运行中产生的 , 拇指 在预编译时还无法确定 , 拇指 所以 BIND 过程无法象对待静态嵌入式 SQL 语句那样 , 拇指 在程序实际运行之前确定其执行方案并创建相应的程序包 。 食指 因此 , 拇指 动态嵌入式 SQL 语句的 BIND 过程只能是动态的 , 拇指 即在程序实际运行过程中完成的 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 3.1 动态嵌入式
36、SQL 语句的类型 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 按照动态嵌入式 SQL 语句是否为查询语句以及是否包含参数标志 , 拇指 可以将其分为以下几种类型: 凌阳, 拇指 凌阳 3.1.1 除 SELECT 之外的动态 SQL 语句 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 即除了 SELECT 之外的其它所有可执行的 SQL 语句 。 食指 由于这类语句没有返回结果集 ,拇指 所以其处理也相对最为简单 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 3.1.2 凌阳, 拇指 凌阳 输出结果列固定的动态 SEL
37、ECT 语句 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 与处理静态嵌入式 SELECT 语句的返回结果集一样 , 拇指 在应用程序中也需要使用游标来处理动态嵌入式 SELECT 语句的返回结果集 。 食指 而对于输出结果列完全固定的 SELECT语句 , 拇指 由于在编程时已事先知道其输出结果列的数据类型 , 拇指 所有可以在程序中预先定义相应的宿主语言变量来接收查询结果集中的数据值 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 3.1.3 全部内容完全动态的 SQL 语句 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳
38、 而对于所有内容都不固定的 SELECT 语句 , 拇指 由于在编程时无法事先知道其会产生哪些输出结果列 , 拇指 所有只能在程序中使用 SQLDA(又称 SQL 描述符区)这种动态数据结构及动态 分配的宿主语言变量来接收查询结果集中的数据值 。 食指 凌阳, 拇指 凌阳 凌 阳, 拇指 凌阳 3.1.4 参数化的动态语句 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 即当中含有参数标记(?)的动态 SQL 语句 。 食指 由于参数化的语句在执行之前必须对其中的参数标记进行赋值 , 拇指 所以 , 拇指 相对非参数化的语句 , 拇指 其处理
39、要更加复杂一些 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 3.2 凌阳, 拇指 凌阳 动态 SQL 例程 凌阳, 拇指 凌阳 以下是采用 SQLDA 处理任意动态 SQL 语句的程序代码片段 (例程 2) : 凌阳, 拇指 凌阳 基于 C 语言的 DB2 数据库开发 8-15 凌阳, 拇指 凌阳 例程 2动态 SQL 语句例程 凌阳, 拇指 凌阳 我们分析一下例程 2 中关键的步骤: 凌阳, 拇指 凌阳 定义 SQL 描述区 , 拇指 用来在应用程序和数据库系统之间传递有关列(或宿主变量)的数目及数据类型与 /或值等方面的信息 (描述区将在下文进行详细叙述) 。 食指 凌阳, 拇指 凌
40、阳 调用 PREPARE 语句 对 动态 语句进行预处理 ,并将得到的结果集描述信息填入 描述区 ,拇指 其语法格式为: 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 PREPARE 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 语句名 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 INTO 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 描述符 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 FROM 凌阳, 拇指 凌阳 凌阳,
41、 拇指 凌阳 :宿主变量 凌阳, 拇指 凌阳 其中 , 拇指 语句名可为任何标识符 , 拇指 宿主变量是一个字符串型的变量并且必须含有一条有效的 SQL 语句 , 拇指 描述符是一个类型为 SQLDA 的宿主语言变量 。 食指 该语句的功能是对一条 SQL 语句(包含在 FROM 之后的宿主变量中)进 行预处理 , 拇指 并用语句名作为处理后的语句的标识(以便在后面的 DESCRIBE, 拇指 EXECUTE 或 OPEN 语句中引用) 。 食指 PREPARE语句要求被处理 SQL 语句中不能出现任何宿主变量 , 拇指 但可以包含一个或多个参数标记(用问号“?”表示) , 拇指 表示语句执行
42、时需要从外部得到的值 。 食指 如果 PREPARE 语句出现“ INTO 凌阳, 拇指 凌阳 描述符”选项 , 拇指 则将被处理语句的结果集中各个列的描述信息填入所给的描述符中 。 食指 对 sSqlstr 中的语句进行预处理 凌阳, 拇指 凌阳 调用 EXECUTE 语句 , 拇指 该语句的功能是执 行一条前面已预处理过的语句(由语句名所标识) 。 食指 语法格式为: 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳
43、, 拇指 凌阳 EXECUTE 凌阳, 拇指 凌阳 语句名 凌阳, 拇指 凌阳 USING 凌阳, 拇指 凌阳 宿主变量 1, 拇指 , 拇指 宿主变量 n 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 | 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳
44、 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 USING 凌阳, 拇指 凌阳 DESCRIPTOR 描述符 凌阳, 拇指 凌阳 基于 C 语言的 DB2 数据库开发 9-15 其中 , 拇指 语句名为一个标识符并且必须标识一条前面已预处理过的语句 , 拇指 描述符是一个类型为 SQLDA 的宿主语言变量 。 食指 凌阳, 拇指 凌阳 调用 DESCRIBE 语句 , 拇指 该语句的作用类似于 PREPARE 语句中的“ INTO 描述符”子句 , 拇指 其功能是得到语句名所标识的那条语句(已预处理过的)的结果集中各个列的描述信息 , 拇指 并将其填入所给的描述符中 。 食指 格
45、式为: 凌阳, 拇指 凌阳 DESCRIBE 凌阳, 拇指 凌阳 语句名 凌阳, 拇指 凌阳 INTO 凌阳, 拇指 凌阳 描述符 凌阳, 拇指 凌阳 其中 , 拇指 语句名为一个标识符并且必须标识一条前面已预处理过的语句 , 拇指 描述符是一个类型为 SQLDA 的宿主语言变量 。 食指 凌阳, 拇指 凌阳 调用 FETCH 语句 , 拇指 将当前游标结果提取到描述区 , 拇指 然后进行处理 。 食指 凌阳, 拇指 凌阳 处理结束 , 拇指 释放描述区空间 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 3.3 凌阳, 拇指 凌阳 SQLDA 的组成和存储格式 凌阳, 拇指 凌阳 在上面的
46、动态例程中 , 拇指 有一个很关键的结构: struct 凌阳, 拇指 凌阳 sqlda 凌阳, 拇指 凌阳 *sqldaprt。 食指 SQLDA 又称 SQL描述符区( Descriptor 凌阳, 拇指 凌阳 Area) , 拇指 SQLDA 是一种功能非常强大且使用非常灵活的动态数据结构 。 食指 SQLDA 的存储空间可在程序运行期间根据需要动态进行分配 , 拇指 并可针对任何动态 SQL 语句 , 拇指 得到有关列的数目、数 据类型、长度、精度等方面的描述信息 , 拇指 或针对动态分配的宿主变量设置变量的数目、数据类型、位置及变量值 。 食指 因此 , 拇指 SQLDA 比程序中的
47、静态宿主变量列表更加灵活 , 拇指 也更加复杂 。 食指 凌阳, 拇指 凌阳 凌阳, 拇指 凌阳 图 2 凌 阳, 拇指 凌阳 SQLDA 的存储格式 凌阳, 拇指 凌阳 如图 2 所示 , 拇指 SQLDA 是由 1 个头 (header)及若干个(可以为 0 个或多个)需要描述的列或变量(又称为条目 (entry))的描述信息组成 。 食指 其中 SQLDA 头 (header)信息的大小为16 字节 (Byte);每一个条目信息占 44 字节 (Byte) 。 食指 因此 , 拇指 一个 SQLDA 的总的大小是由其中所包含的条目数 (sqlvars)决定的 , 拇指 即按字节计算 ,
48、拇指 一个 SQLDA 的大小应为 16+条目数 *44 凌阳, 拇指 凌阳 Byte。 食指 凌阳, 拇指 凌阳 SQLDA 的头信息包括下列内容: 凌阳, 拇指 凌阳 sqldaid: 凌阳, 拇指 凌阳 存储块标志 , 拇指 其中固定含有字符串“ SQLDA”; 凌阳, 拇指 凌阳 sqldabc:SQLDA 存储块的总长(以字节计); 凌 阳, 拇指 凌阳 注:通常 , 拇指 sqldabc 的值是由 DESCRIBE 语句设置的 。 食指 但如果程序员在使用 SQLDA时基于 C 语言的 DB2 数据库开发 10-15 未调用 DESCRIBE 语句 , 拇指 则应有程序员自己负责为该域设置适当的值 。 食指 凌阳, 拇指 凌阳 sqln:SQLDA 中可以使用的描述区块( 44Byte)的数目;( SQLVARs) 凌 阳, 拇指 凌阳 sqld:SQLDA 中实际描述的条目数; 凌 阳, 拇指 凌阳 注: sqld 的值可以程序执行不同的语句而改变 , 拇指 但必须总是小于或等于 sqln。 食指 凌阳, 拇指 凌阳 SQLDA 中每一个条目的信息
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。