[ Translate by Z.Jingwei. Document address:http://www-db.stanford.edu/~ullman/fcdb/oracle/or-proc.html ] Pro*C介绍 内嵌SQL
- 概要
- Pro*C语法
- 宿主变量
- 基础
- 指针
- 结构
- 数组
- 指示器变量
- 数据类型同等化
- 动态SQL
- 事务
- 错误处理
- Demo程序
- C++用户
- List of Embedded SQL Statements Supported by Pro*C
概要内嵌SQL是结合高级语言如C/C++的计算能力和SQL数据库处理能力的一种方法。它允许你在程序中执行任意的SQL语句。Oracle的嵌入SQL环境称为Pro*C。 Pro*C程序分两步编译。首先,Pro*C的预编译器识别出嵌入在程序中的SQL语句,并将这些语句转换为对SQL运行时库(SQL runtime library)中功能(functions)的适当调用。输出是纯C/C++代码和未被处理的纯C/C++代码。然后,用常规C/C++编译器编译代码并生成可执行程序。更详细的内容请参考Demo程序。 Demo程序。
Pro*C语法
SQL所有SQL语句都要以EXEC SQL开始,并用分号";"结束。SQL语句可以放置在C/C++块中的任何地方,但可执行的(SQL)语句应该在声明语句后面。例: {
int a;
/* ... */
EXEC SQL SELECT salary INTO :a
FROM Employee
WHERE SSN=876543210;
/* ... */
printf("The salary is %d\n", a);
/* ... */
}
预处理指令能够在Pro*C中正常工作的C/C++预处理指令是#include和#if。Pro*C不能识别#define。下面的代码是错误的: #define THE_SSN 876543210
/* ... */
EXEC SQL SELECT salary INTO :a
FROM Employee
WHERE SSN = THE_SSN;/* INVALID */
语句标号可以在SQL中跳转到C/C++标记 EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;
/* ... */
error_in_SQL:
/* do error handling */ 我们会在后面的错误处理一节中讲到有关WHENEVER的含意。 错误处理一节中讲到有关WHENEVER的含意。
宿主变量
基础宿主变量是连接宿主程序与数据库的关键。宿主变量表达式必须视为(resolve to)左值(能被赋值)。你可以像声明普通C变量一样,按着C的语法规则声明宿主变量。宿主变量的声明可以放置在任何C变量声明可以放置的地方。(C++用户需要使用"DECLARE SECTION";参考C++ Users) Oracle可以使用的C数据类型包括: C++ Users) Oracle可以使用的C数据类型包括:- char
- char[n]
- int
- short
- long
- float
- double
- VARCHAR[n] - 它是能被Pro*C的预编译器识别的预处理类型(psuedo-type)。它用来 表示由空白填充(blank-padded,译注:''''\0'''')的变长字符串。Pro*C预编译器会把它转换为有一个2字节(byte)长的域和一个n字(byte)长的字符数组的结构体。
你不能指定寄存器存储类型(译注:指针)为宿主变量。 可以在SQL表达式中使用冒号":"做前缀来引用一个宿主变量,但不能在C表达式中用分号做前缀。当使用字符串作为宿主变量时,必须省略引用;Pro*C明白你正指定一个基于宿主变量声明类型的字符串(译注:这句的意思是,当定义一个字符串做为宿主变量时char *str="string",在嵌入SQL中使用时,要省略"*"而不是*str)。不能将C函数调用和多数的指针计算表达式作为宿主变量使用,即使它们确实被解释为左值。下面的代码同时说明了合法和不合法的宿主变量的引用: int deptnos[3] = { 000, 111, 222 };
int get_deptno() { return deptnos[2]; }
int *get_deptnoptr() { return &(deptnos[2]); }
int main()
{
int x; char *y; int z;
/* ... */
EXEC SQL INSERT INTO emp(empno, ename, deptno)
VALUES(:x, :y, :z); /* LEGAL */
EXEC SQL INSERT INTO emp(empno, ename, deptno)
VALUES(:x + 1, /* LEGAL: the reference is to x */
''''Big Shot'''', /* LEGAL: but not really a host var */
:deptnos[2]);/* LEGAL: array element is fine */
EXEC SQL INSERT INTO emp(empno, ename, deptno)
VALUES(:x, :y,
:(*(deptnos+2)));/* ILLEGAL: although it has anlvalue */
EXEC SQL INSERT INTO emp(empno, ename, deptno)
VALUES(:x, :y,
:get_deptno()); /* ILLEGAL: no function calls */
EXEC SQL INSERT INTO emp(empno, ename, deptno)
VALUES(:x, :y,
:(*get_depnoptr())); /* ILLEGAL: although it has an lvalue */
/* ... */
}
指针可以在SQL表达式中使用普通C语法声明的指针。通常使用一个冒号做前缀: int*x;
/*...*/
EXEC SQL SELECT xyz INTO :x FROM ...; 这个SELECT语句的结果会写入*x,而不是x。
结构结构同样可以作为宿主变量使用,如下面例子: typedef struct {
char name[21];/* one greater than column length; for ''''\0'''' */
int SSN;
} Emp;
/* ... */
Emp bigshot;
/* ... */
EXEC SQL INSERT INTO emp (ename, eSSN)
VALUES (:bigshot);
数组像下面这样使用宿主数组: int emp_number[50];
char name[50][11];
/* ... */
EXEC SQL INSERT INTO emp(emp_number, name)
VALUES (:emp_number, :emp_name); 这样会一次插入所有的50个元素(tuples)。 数组只能是一维数组。例子中的char name[50][11]可能看起来与这个规则矛盾,然而,Pro*C实际上把name视为一维字符串数组而不是二维字符数组。也可以使用结构数组。 当使用数组存放查询结果时,如果宿主数组的大小(n)小于实际查询后返回的结果数量时,那么只有(查询出来的)前n个结果被填入宿主数组。
指示器变量指示器实际上是附在宿主变量后的"NULL标记"。每一个宿主变量都可以选择性的关联到一个指示器变量上。指示器变量的类型必须为2字节整形值(short类型),而且必须紧随在宿主变量后且用冒号做为前缀。你也可以使用关键字INDICATOR放在宿主变量和指示器变量之间。例如: short indicator_var;
EXEC SQL SELECT xyz INTO :host_var:indicator_var
FROM ...;
/* ... */
EXEC SQL INSERT INTO R
VALUES(:host_var INDICATOR :indicator_var, ...); 在SELECT的INTO子句中使用的指示器变量可以用来检查返回给宿主变量的值为空(NULL)或被截断的的情况。Oracle能够赋给指示器变量的值具有下面各项意义: -1字段(译注:原文为column,意为该字段的列)值为NULL,宿主变量的值不确定。0Oracle把完整的字值赋给了宿主变量。>0Oracle把被截断的字段值赋给了宿主变量。指示器变量返回的整形值是字段的原始长度。-2Oracle把被截断的字段值赋给了宿主变量,但原字段值是不确定的。(译注:这种情况可能是数值型的值被切断后不能确定原始值)你也可以在INSERT或UPDATE的VALUES和SET子句中使用指示器变量指明用于输入的宿主变量为NULL值。你的程序可以赋给指示器变量的值具有如下各项意义: -1Oracle会忽略宿主变量的值并给字段赋一个NULL值。>=0Oracle会将宿主变量的值赋给字段。
数据类型同等化Oracle认识两种数据类型:内部类型和外部类型。内部数据类型指示Oracle在数据库表中如何存储字段。外部数据类型指示如何格式化存储在宿主变量中用于输入或输出的值。在预编译期,每一个宿主变量会被赋予一个默认的Oracle外部数据类型。数据类型同等化允许你重载默认的同等化,并允许你控制Oracle输入数据的解释和输出数据的格式化。 同等化通过使用VAR表达式实现基于从变量到变量的转换。语法是: EXEC SQL VAR <host_var> IS <type_name> [ (<length>) ]; 举例来说, 假设你想从emp表中查询雇员名子,然后传给一个需要C类型(以''''\0''''结尾的)字符串的程序,你不需要显式的用''''\0''''来结束这个名子。如下面所示,简单地将宿主变量同等化为外部数据类型STRING: char emp_name[21];
EXEC SQL VAR emp_name IS STRING(21); emp表中ename字段的长是20字符(character),因此,需要分配21字符(character)以适应''''\0''''结束符。Oracle的外部数据类型STRING是为C类型字符串特别设计的接口。当把ename字段值传给emp_name时,Oracle会自动用''''\n''''结尾。 也可以使用TYPE语句将用户自定义数据类型同等化为Oracle外部数据类型。语法是: EXEC SQL TYPE <user_type> IS <type_name> [ (<length>) ] [REFERENCE]; 可以声明一个用户自定义类型的指针,显式的如指向标量或结构的指针,或隐式的如数组,然后在TYPE表达式中使用这个类型。这种情况下,你需要在表达式后使用REFERENCE子句,如下所示: typedef unsigned char *my_raw;
EXEC SQL TYPE my_raw IS VARRAW(4000) REFERENCE;
my_raw buffer;
/* ... */
buffer = malloc(4004); 这里,我们分配了比源类型长(4000)更多的内存,这是因为预编译器要返回长度,而且可能需要填充适当的长度以满足系统的对齐要求。
动态SQL嵌入SQL能够满足一个固定的应用,但有时动态产生完整的SQL语句也是很重要的。对于动态SQL,语句存储在字符串变量中,PREPARE把字符串转换为SQL语句,然后用EXECUTE执行这个语句。考虑下面的例子: char *s = "INSERT INTO emp VALUES(1234, ''''jon'''', 3)";
EXEC SQL PREPARE q FROM :s;
EXEC SQL EXECUTE q; PREPARE和EXECUTE可放到一个语句中,像这样: char *s = "INSERT INTO emp VALUES(1234, ''''jon'''', 3)";
EXEC SQL EXECUTE IMMEDIATE :s;
事务Oracle Pro*C支持标准SQL定义的事务。一个事务是一组SQL语句集合,Oracle把它当作单独的单元运行。一个事务从第一个SQL语句开始,遇到"EXEC SQL COMMIT"(执行当前事务对数据库的永久修改)或"EXEC SQL ROLLBACK"(取消从事务开始到当前位置对数据库的任何修改)时结束事务。当前事务由COMMIT或ROLLBACK语句结束后,下一条可执行SQL语句将自动开始一个新事务。 如果程序结束时没有执行EXEC SQL COMMIT,则对数据库的所作的修改都将被忽略。
错误处理在每个可执行的SQL表达式之后,可以在程序中检查SQLCA显式地或用WHENEVER语句隐式地得到执行状态信息。下面将详细地介绍这两种方法。
SQLCASQLCA(SQL Communications Area,SQL通讯区)用于在程序中检查错误和状态变化。每个可执行 [1] [2] [3] 下一页 [Access]sql随机抽取记录 [Access]ASP&SQL让select查询结果随机排序的实现方法 [办公软件]在sybase中插入图片、PDF、文本文件 [办公软件]安装Sybase ASE [办公软件]linux指令大全(完整篇) [办公软件]Linux新手入门常用命令大全 [办公软件]在RedHat Linux 9里安装gaim0.80 [办公软件]浅谈Linux 下Java 1.5 汉字方块问题解决方法 [办公软件]Linux程序员必读:中文化与GB18030标准 [办公软件]linux指令大全
|