本章主要介绍嵌入式 SQL 中的一些关键概念与术语,并简单介绍了开发 PRO*C 程序的步骤。本文档中从本章开始的所有示例,除了例子中特别建的表外,其余都使用 DM 示例库中的表。
2.1 嵌入式 SQL 关键概念
2.1.1 嵌入式 SQL 语句
嵌入式 SQL 是指在应用程序里直接嵌入 SQL 语句。因为嵌入 SQL,应用程序又叫宿主程序,编写应用程序的高级语言又叫宿主语言。例如,PRO*C/C++ 能够在 C 和 C++ 宿主程序嵌入一些 SQL 语句。
可嵌入的 SQL 语句包括 DDL 与 DML 语句,以及一些事务控制语句,这些语句都是嵌入的可执行语句。可执行语句在编译时会调用 libdmdpc.so 库接口,通过它们连接数据库,进行数据定义及查询操作数据库数据,以及处理事务,它们能存在 C/C++ 语言中任何可执行语句能嵌入的地方。表 2.1 列出了常用的嵌入可执行语句。
可执行语句 | 作用 |
---|---|
ALLOCATE | 初始化变量 |
ALTER,CREATE TABLE | DDL |
DELETE,UPDATE, INSERT,SELECT | DML |
COMMIT,ROLLBACK,SAVEPOINT,SET TRANSACTION | 事务控制 |
DESCRIBE,EXECUTE,PREPARE | 动态 SQL |
除了可执行语句,可嵌入 SQL 还包括一些在宿主程序与 DM 数据库之间传输数据的指令。这些指令在编译时不需要调用 libdmdpc.so 库接口,也不会操作数据库数据,用户可以使用它们声明通信区域和宿主变量。表 2.2 列出了常用的嵌入指令。
指令 | 作用 |
---|---|
BEGIN DECLARE SECTION | 声明宿主变量 |
INCLUDE | 包含其他文件 |
TYPE | 类型定义 |
WHENEVER | 捕获运行错误 |
2.1.2 嵌入式 SQL 语法
在 PRO*C 程序中能够自由地使用 SQL 语句与 C 语句,也可以在 SQL 语句中使用 C 变量和结构。在 PRO*C 中使用 SQL 语句必须在 SQL 语句前加上关键字“EXEC SQL”并且以分号结束。DM 的预编译命令行运行程序 dpc_new 将所有带有“EXEC SQL”的语句转换为对 libdmdpc.so 库中接口的调用。
许多嵌入式 SQL 语句与交互式 SQL 语句的区别只在于能够使用程序变量或者是增加了额外的“EXEC SQL”关键字;同样的,对于 2.1.1 嵌入式 SQL 语句中所介绍的 DDL、DML 和事务控制等常用的嵌入式 SQL 语句,对应的交互式 SQL 语句语法介绍可查看《DM8_SQL 语言使用手册》的相关章节。
下面的例子比较了交互式与嵌入式 COMMIT 语句的区别,他们实际的作用是一样的。
COMMIT; //交互式
EXEC SQL COMMIT; //嵌入式
2.1.3 静态 SQL 与动态 SQL
大多数程序使用静态的 SQL 处理固定的语句,在这种情况下,你必须在运行前事先知道 SQL 语句和事务的组成,以及哪些 SQL 命令会被执行,哪些表的结构会变动,哪些列会被更新等等。
然而,在某些情况下可能要在运行时才能确定要执行的有效的 SQL 语句,因此你在运行前可能不知道所有的 SQL 命令、数据库表、牵涉到的列等,只有在程序执行时才能构造出完整的 SQL。动态 SQL 是一种高级编程技术,能够让程序在运行时处理执行过程中临时生成的 SQL 语句。
2.1.4 嵌入 DMSQL 程序块
PRO*C 把 DMSQL 程序块视作单一的嵌入 SQL 语句,任何 SQL 语句能嵌入的地方也能嵌入 DMSQL 程序块。在宿主程序中嵌入 DMSQL 程序块,必须使用关键字 EXEC SQL EXECUTE 和 END-EXEC 将 DMSQL 程序块括起来。
2.1.5 宿主变量与指示符
宿主变量是数据库与应用程序联系的关键,宿主变量是在 C 中声明的 SQL 与 C 程序都能使用的变量。程序使用输入宿主变量向数据库传递数据,数据库使用输出宿主变量传输数据或其他状态信息给应用程序。宿主变量能够在任何 SQL 表达式可以使用的地方使用。在 SQL 语句中,宿主变量必须以“:”作为前缀以便于同关键字区分开来。
应用程序中也能用结构来包含多个宿主变量,在 SQL 语句中使用结构时也要用“:”作为前缀,DM 会把结构里的每个成员都当宿主变量处理。
每个宿主变量后都能跟一个指示符变量。指示符变量是一个整型的宿主变量,其作用是用来指示宿主变量的取值情况。在 SQL 语句中,指示符变量必须加上“:”前缀并且只能紧跟在它指示的宿主变量后面。可以在宿主变量与指示变量中间加上关键字 INDICATOR 使含义更明确,也可以省略。
如果宿主变量是定义在结构体中,你只需要定义一个指示符的结构,里面的指示变量与宿主结构中的宿主变量一一对应,再在 SQL 语句使用指示结构即可。与非结构指示变量一样,也需要紧跟在宿主结构之后,且前缀加上“:”,也可在中间加上关键字 INDICATOR。
2.1.6DM 数据类型
一般来说,应用程序输入数据到数据库,数据库输出数据到程序。数据库将输入的数据存储到表中,输出数据存放到宿主变量里。
存储数据必须知道数据类型,以确定存储格式。数据在 DM 数据库表中的存储格式为 DM 内部数据类型;数据在宿主变量中的存储格式为外部数据类型。DM 数据库能同时识别这两种数据类型,且在二者间进行转换。
2.1.7 宿主数组
PRO*C 允许定义数组宿主变量和数组结构宿主变量,并且在单个 SQL 中使用。使用数组可以同时操作大量数据,也可以在结构中使用数组宿主变量。
2.1.8 事务
PRO*C 中嵌入的 SQL 也适用交互式 SQL 中事务的概念,可以通过 COMMIT、ROLLBACK、SAVEPOINT 等语句对事务进行控制。
2.1.9 错误与警告
当嵌入式 SQL 执行出错或产生警告时,PRO*C 提供了四种方法来捕获错误与警告:SQLCA 结构、WHENEVER 语句、SQLCODE 与 SQLSTATE、ORACA 结构。具体使用方法见后面章节介绍。
2.2 开发嵌入式程序的步骤
举例说明嵌有 SQL 语句的 C 语言程序 PRO*C 的运行过程:
- 编写嵌有 SQL 语句的源程序 test.pc;
- 使用 DM 预编译工具 dpc_new 编译 test.pc,生成 test.c;
- C 编译器编译链接上述文件,以及 dpc_dll.h、DPI.h、DPItypes.h、sqlca.h、dmdpc.lib、dmdpc.dll,生成 test.exe 可执行程序。若在 Linux 下则将 dmdpc.lib、dmdpc.dll 改为 libdmdpc.a 和 libdmdpc.so。
2.3 程序编写
本节简单介绍一些嵌入式程序编写的语法、惯例、限制等,具体在后续章节中会有详细介绍。
- 程序注释
可以在嵌入的 SQL 语句中使用 C 类型注释(/*…*/),也可以在一行的结尾使用 ANSI 标准的注释(//…)。
例
EXEC SQL SELECT NAME,/*名字*/ SEX
INTO :name, :sex //output host variables
FROM PERSON.PERSON
WHERE PERSONID = :personid;
- 声明节
一个声明节的组成如下例所示:
EXEC SQL BEGIN DECLARE SECTION;
//声明宿主变量在这里
char username[20],password[20],servername[20];
...
EXEC SQL END DECLARE SECTION;
声明节以“EXEC SQL BEGIN DECLARE SECTION;”语句开始,以“EXEC SQL END DECLARE SECTION;”结束。在声明节中能够存在的内容包括有以下语句:
- 宿主变量与指示符变量的定义
- 非宿主的 C 变量
- C 的注释
- EXEC SQL TYPE 语句
- 引号
C 使用单引号表示单个字符,SQL 使用单引号界定字符串,例如:
EXEC SQL SELECT NAME, SEX FROM EMP WHERE PHONE = '123456789';
C 使用双引号界定字符串,SQL 使用双引号界定包含小写或特殊字符的标识符,例如:
EXEC SQL CREATE TABLE "test"(c1 INT);
- 行延长
在 SQL 语句中能够使用反斜杠延长一行字符串到另一行,例如:
EXEC SQL INSERT INTO PERSON.PERSON (NAME, PHONE) VALUES ('XQ', '123\456');