7.sqlda动态SQL预备知识
(1).sqlda的引用
EXEC SQL INCLUDE sqlda;
sqlda *bind_dp;
bind_dp = sqlald( … );
(2).sqlald函数
sqlald函数为sqlda结构分配空间。函数格式如下:
descriptor_name = sqlald(max_vars, max_name, max_ind_name );
其中:
max_vars:sqlda结构中要描述的选择表项或虚拟输入宿主变量的最大个数;
max_name:选择表项或虚拟输入宿主变量名字的最大长度;
max_ind_name:指示器变量名的最大长度。对于选择sqlda,该项设置为0。
一般用指针来引用sqlda。
(3).数据类型转换
对于选择描述区,DESCRIBE SELECT
LIST返回ORACLE的内部数据类型。通常,该内部数据类型正好对应所要用的外部数据类型;但是,个别的映射难以处理,因此,可以重新设置T变量的某些元素。ORACLE在FETCH时做必要的内部和外部数据类型的转换。
对于结合缓冲区,DESCRIBE BIND
VARIABLES并不返回实输入宿主变量的数据类型,而只返回它们的个数和名字。于是,必须显示设置数组T,以告诉ORACLE每一个实输入宿主变量的外部数据类型。ORACLE在OPEN时做外部和内部数据类型之间的必要转换。
除了设置T变量外,有些情况下,还要设置缓冲区长度。在FETCH之前必须重新设置L变量的相应元素,以告诉ORACLE所用的缓冲区长度。
库函数sqlprc()分离精度和定标。通常在DESCRIBE
SELECT LIST之后使用它,并且它的第一个参数时L[i]:
sqlprc( long *length, int *precision, int *scale );
其中,length存储一个ORACLE
NUMBER值得长度。长度存放在L[i],该值得定标和精度存放在相应的低字节和下一个高字节中;
precision存放NUMBER值精度。精度是有效位数,如果选择表项引用的是未指定大小的NUMBER值,则它被设置为0。在这种情况下,可假定为最大精度;
scale存放NUMBER值定标。定标指出在什么地方舍入。如,2:3.456
-> 3.46;-3:3456 -> 3000。
(4).处理Null/Not Null类型
对于每一个选择表列(不是表达式),DESCRIBE SELECT
LIST在T变量中返回一个Null/Not Null指示。如果第i个选择表项被强制为Not
Null,那么T[i]的高位被清除,否则被设置。
在OPEN或FETCH之前,如果Null位被设置的话,则必须清除它。使用库函数sqlnul来发现一个列是否允许Null,并清除该数据类型的Null状态位:
sqlnul(unsigned short *value_type, unsigned short *type_code, \
int *null_status );
其中,value_type存放一个选择表项的数据类型代码,即T[i];
type_code返回该选择表列的数据类型代码,其高位被清除;
null_status返回选择表列的Null状态。1表示允许Null;0表示不允许Null。
8.sqlda动态SQL基本处理步骤
(1).说明一个串型宿主变量
在说明段说明一个串型的宿主变量,以保存查询语句的文本。
EXEC SQL BEGIN DECLARE SECTION
VARCHAR select_stmt[120];
EXEC SQL END DECLARE SECTION
(2).说明SQLDA
说明选择和结合SQLDA。
EXEC SQL INCLUDE sqlda;
sqlda *select_des;
sqlda *bind_des;
(3).分配空间
分配选择和结合缓冲区的空间。
使用sqlald()函数分配,如果max_name非0,则分配由指针变量S、M和C寻址的数组。如果max_ind_name不是0,则分配由指针变量X、Y和Z寻址的数组。如果max_name和max_ind_name为0,则不分配相应的空间。
如果sqlald()成功,则返回该描述区的地址,失败则返回空指针。
select_des = sqlald(3, 5, 0);
bind_des = sqlald(3, 5, 4);
对于选择描述区,总是把max_ind_name设置为0。
(4).设置DESCRIBE的最大个数
设置能被DESCRIBE的选择表项和虚拟输入宿主变量的最大个数。
select_des->N = 3;
bind_des->N = 3;
(5).把查询文本存放在宿主串中
把查询语句文本存放在串型宿主变量中。
strcpy(select_stmt.arr, “select … where …” );
select_stmt.len = strlen(select_stmt.arr);
(6).分析查询语句
PREPARE宿主串中的查询语句。
EXEC SQL PREPARE sql_stmt FROM :select_stmt;
(7).说明一个光标
DECLARE一个查询光标。
EXEC SQL DEACLARE emp_cursor CURSOR FOR sql_stmt;
注意:对于此种方法的动态sql语句(不只是查询语句),都必须说明一个光标,在非查询语句情况下,打开光标即执行该动态sql语句。
(8).DESCRIBE实输入宿主变量
把实输入宿主变量DESCRIBE进结合描述区中。
EXEC SQL DESCRIBE BIND VARIABLES FOR sql_stmt INTO bind_des;
注意:在bind_des之前一定不加冒号。
(9).重新设置虚拟输入宿主变量的个数
把虚拟输入宿主变量的个数重新设置为DESCRIBE实际发现的个数。
bind_des->N = bind_des->F;
(10).为实输入宿主变量分配空间和取值
为DESCRIBE发现的实输入宿主变量取值和分配存储空间。
如:
bind_des->L[i] = strlen( hostval );
bind_des->V[i] = malloc(bind_des->L[i] + 1);
bind_des->I[i] = (unsigned short *)malloc(sizeof(short));
strcpy(bind_des->V[i], hostval);
bind_des->I[i] = 0;
bind_des->T[i] = 1;
(11).打开光标
用OPEN…USING打开与结合描述区相对应的光标。
EXEC SQL OPEN emp_cursor USING DESCRIPTOR bind_des;
注意:在bind_des之前一定不加冒号。
(12).描述选择表
用DESCRIBE SELECT
LIST语句描述选择描述区。
EXEC SQL DESCRIBE SELECT LIST FOR sql_stmt INTO select_des;
注意:DESCRIBE把F设置为该查询选择表项的实际个数,如果语句不是查询,则被设置为0。
此时NUMBER的长度仍然不能用,还需要用sqlprc()来分离精度和定标。
(13).重新设置选择表项的最大数
把选择表项的个数重新设置为DESCRIBE实际发现的个数。
select_stmt->N = select_stmt->F;
(14).重新设置选择表项的长度和数据类型
重新设置选择表项的长度和数据类型,以便显示它们。
如:
sqlnul(&(select_stmt->T[i]), &(select_stmt->T[i]), &nullok);
switch( select_stmt->T[i]) {
case 1: break;
case 2: sqlprc(&select_stmt->L[i], &prec, &scal);
if ( prec == 0 ) prec = 40;
select_des->L[i] = prec + 2;
if (scal < 0) select_des->L[i] += -scal;
break;
case 8: select_des->L[i] = 240;
break;
case 11:select_des->L[i] = 18;
break;
case 12: select_des->L[i] = 9;
break;
case 23: break;
case 24: select_des->L[i] = 240;
break;
}
select_stmt->V[i] = malloc(select_stmt->L[i]);
select_stmt->I[i] = (unsigned short *)malloc(sizeof(short));
if (select_stmt->T[i] != 24) select_stmt->T[i] = 1;
(15).从光标缓冲区中提取行
用FETCH把提取的行放入选择描述区所指向的数据缓冲区。
EXEC SQL FETCH emp_cursor USING DESCRIPTOR select_des;
在输出缓冲区中,对于数据类型1,ORACLE使用存放在L数组中的长度,左对齐CHAR和VARCHAR2数据,右对齐NUMBER数据。
(16).取和处理选择表项的值
处理FETCH所返回的选择表项。
(17).撤销存储分配
释放选择表项、虚拟输入宿主变量、指示器变量和描述区所用的空间。
使用free释放malloc分配的空间。
使用sqlclu()库函数撤销描述区本身的存储空间。
sqlclu(select_des);
sqlclu(bind_des);
(18).关闭光标
关闭光标。
EXEC SQL CLOSE emp_cursor;
9.关于游标的释放
在一个连接中,若该连接引用记数为1,则关闭该连接也释放游标;如在同一个进程中打开连接,操作数据,关闭连接。
若连接记数大于1,如父进程打开连接,子进程共享该连接进行操作,则连接记数大于1,子进程不能做关闭连接操作。此时要释放一个游标,在关闭游标后,还必须做commit或rollback;此外,还要设置release_cursor选项为yes,设置方法是在proc命令行中增加release_cursor=yes,或在程序中编写:
EXEC ORACLE OPTION(RELEASE_CURSOR=YES);
否则不能释放,最终会报-1000错:maximum open
cursors exceeded。
10.Pro*C命令选项
Pro*C的命令格式如下:
proc INAME=filename [Option_name1=value1 Option_name2=value2 … ]
注意:等号两侧不能有空格。
在程序中指定选项的格式如下:
EXEC SQL OPTION(option_name=value);
编译选项如下:
ASACC
ASACC=YES|NO;
缺省值为NO。指出清单文件是否为了回车控制而遵循使用每一行第一列的ASA约定。
注意:只能在命令行上输入。
CODE
CODE=ANSI_C|KR_C
缺省值为KR_C。产生的C函数原型的格式。
DBMS
DBMS=NATIVE|V6|V7
缺省值为NATIVE。指定所用的ORACLE数据库管理系统的版本,是6版、7版或本国版。
注意:只能在命令行上输入。
DEFINE
用于定义一个符号,用于进行条件编译。
如果在程序中输入时,使用如下语法:
EXEC ORACLE DEFINE symbol;
ERRORS
ERRORS=YES|NO;
缺省值为YES。指出预编译程序的错误信息是否被发送到终端和清单文件上,或仅仅给清单文件。
FIPS
FIPS=YES|NO;
缺省值为NO。当FIPS=YES时,如果使用一个ANSI
SQL的ORACLE扩展,或以不一致的方式使用一个ANSI SQL性能,就发出警告(不是错误)信息。
HOLD_CURSOR
HOLD_CURSOR=YES|NO;
缺省值为NO。
当执行SQL数据操纵语句时,其相关的光标被连到光标高速缓冲存储器中的一项上,该项又被依次连接到ORACLE专用的SQL区域上,该区域存储处理该语句所需的信息。
当HOLD_CURSOR=NO时,在ORACLE执行完SQL语句或关闭光标后,预编译程序直接撤去该链,释放分析块和分配给专用SQL区域的内存,并把该链标为可再使用。这时另一个SQL语句就又可使用该链来指向光标高速缓冲存储器的项了。
当HOLD_CURSOR=YES时,该链被保留,预编译程序不再使用它。这对经常使用的SQL语句是有用的。
注意:RELEASE_CURSOR=YES优先于HOLD_CURSOR=YES;HOLD_CURSOR=NO优先于RELEASE_CURSOR=NO。
HOST
HOST=C|COB74|COBOL|FORTRAN|PASCAL|PLI;
指出输入文件的宿主语言。
INCLUDE
INCLUDE=path;
缺省值为当前目录。指定EXEX SQL
INCLUDE文件的目录路径,它只适用于使用目录的操作系统。
IRECLEN
IRECLEN=length;
缺省值为80。指定输入文件的纪录长度。
注意:只能在命令行输入,指定的值不应超过ORECLEN的值。
LINES
LINES=YES|NO;
缺省值为NO。当LINES=YES时,预编译程序对输出文件加C预编译程序命令#line。为NO时不输出。
LNAME
LNAME=path and
filename;
缺省值为“输入文件.LIS”。为清单文件指定非缺省名。
注意:只能在命令行输入。
LRECLEN
LRECLEN=integer;
缺省值为132。指定清单文件的记录长度。
注意:只能在命令行输入。
LTYPE
LTYPE=LONG|SHORT|NONE;
缺省值为LONG。
指定清单类型。当LTYPE=LONG时,清单文件中包含输入行;当LTYPE=SHORT时,不包含输入行;当LTYPE=NONE时,不建立清单文件。
MAXLITERAL
MAXLITERAL=integer;
缺省值为1000(C语言)。指出预编译程序生成的串文字的最大长度。
MAXOPENCURSORS
MAXOPENCURSORS=integer;
缺省值为10。指定同时打开的光标数。每个用户处理能打开的光标的最大数由ORACLE初始化参数OPEN_CURSORS设置,其范围为5至255。该选项可指定一个较初始值小的值,必须比初始值至少低6。
MODE
MODE=ANSI|ISO|ANSI14|ISO14|ANSI13|ISO13|ORACLE;
缺省值为ORACLE。指定程序遵循的标准。
ONAME
ONAME=path and
filename;
指定输出文件名。
注意:只能在命令行上输入。
ORACA
ORACA=YES|NO;
缺省值为NO。指出程序能否使用ORACLE通讯区。
ORECLEN
ORECLEN=integer;
缺省值为80。指定输出文件的记录长度。
注意:只能在命令行输入,值应大于等于IRECLEN的值。
PAGELEN
PAGELEN=integer;
缺省值为66。指定清单文件的每一物理页的行数。
注意:只能在命令行上输入。
RELEASE_CURSOR
RELEASE_CURSOR=YES|NO;
缺省值为NO。
该选项用来控制光标和光标高速缓冲存储器之间的链。为了保证在关闭光标时使有关的资源被释放,必须指定:
RELEASE_CURSOR=YES。
相关描述见HOLD_CURSOR。
SELECT_ERROR
SELECT_ERROR=YES|NO。
缺省值为YES。
当SELECT_ERROR=YES时,若单行SELECT语句返回多于一行,或多行SELECT语句返回的行数比宿主数组能容纳的还要多,则产生错误,且查询的结果是不确定的。当指定SELECT_ERROR=NO时,则不产生错误。
SQLCHECK
SQLCHECK=SEMANTICS|FULL|SYNTAX|LIMITED|NONE;
缺省值为SYNTAX。指定语法和语义检查的类型和范围。
USERID
USERID=username/password;
指定ORACLE用户名和密码。
注意:只能在命令行上输入。
XREF
XREF=YES|NO;
缺省值为YES。指出是否在清单文件中列交叉索引表。