动态SQL
索引:
1.动态SQL处理步骤
装配SQL语句文本;
用PREPARE准备语句;
用EXECUTE/OPEN或FETECH执行语句;
用FREE释放资源。
2.动态SQL的两种管理方法
方法对比
系统描述区 | SQLDA |
---|---|
语言独立性 | 依赖语言 |
与X/OPEN标准一致 | 与X/OPEN标准一致 |
内部仍然分配SQLDA | 向后兼容 |
内存分配对比
系统描述区 | SQLDA |
---|---|
ALLOCATE DESCRIPTOR | Malloc |
DEALLOCATE DESCRIPTOR | Free |
DESCRIBE | DESCRIBE |
GET DESCRIPTOR | |
SET DESCRIPTOR |
3.系统描述区
结构
系统描述区开始是一个COUNT,记录系统描述区中的变量数目或occurrences的数目。
之后是COUNT个变量/occurrences的描述结构。每个结构有如下属性:
- DATA:传送给数据库引擎或从数据库引擎接收的数据;
- TYPE:一个短整数,对应于传送的数据类型;
- LENGTH:一个短整数,给出CHAR类型的数据、DATETIME或INTEVAL数据的编码修饰符的字节大小,或一个DECIMAL或MONEY值的大小;
- INDICATOR:非NULL值为0,NULL值为-1;
- NAME:字段名;
- SCALE,PRECISION:如果相应的项目是DECIMAL或MONEY类型,则设置这些域。LENGTH域根据提供的SCALE和PRECISION来设置;
- NULLABLE:1表示该字段允许空值,0表示该字段不允许空;
- IDATA,ITYPE,ILENGTH:用户定义的指示变量的数据、类型或长度域,指示变量可以是任何合法的宿主变量类型,除DATETIME或INTERVAL外。
预定义常数
常量 | C数据类型 | 整型数 |
---|---|---|
CCHARTYPE | char | 100 |
CSHORTTYPE | short int | 101 |
CINTTYPE | int | 102 |
CLONGTYPE | long | 103 |
CFLOATTYPE | float | 104 |
CDOUBLETYPE | double | 105 |
CDECIMALTYPE | dec_t或struct decimal | 106 |
CFIXCHARTYPE | fixchar | 107 |
CSTRINGTYPE | string | 108 |
CDATETYPE | long | 109 |
CMONEYTYPE | dec_t或struct decimal | 110 |
CDTIMETYPE | dtime_t或struct dtime | 111 |
CLOCATORTYPE | loc_t | 112 |
CVCHARTYPE | varchar | 113 |
CINVTYPE | intrvl_t或struct intrvl | 114 |
CFILETYPE | char | 115 |
X/OPEN标志
当编译时使用了X/OPEN标志,则在SET DESCRIPTOR语句中不能使用下列常数:
常数 | SQL数据类型 | 整型数 |
---|---|---|
SQLCHAR | CHAR | 0 |
SQLSMINT | SMALLINT | 1 |
SQLINT | INTEGER | 2 |
SQLFLOAT | FLOAT | 3 |
SQLSMFLOAT | SMALLFLOAT | 4 |
SQLDECIMAL | DECIMAL | 5 |
SQLSERIAL | SERIAL | 6 |
SQLDATE | DATE | 7 |
SQLMONEY | MONEY | 8 |
SQLDTIME | DATETIME | 10 |
SQLBYTES | BYTE | 11 |
SQLTEXT | TEXT | 12 |
SQLVCHAR | VARCHAR | 13 |
SQLINTEGERVL | INTERVAL | 14 |
必须使用下面的值,以保证X/OPEN的兼容性:
常数 | SQL数据类型 | 整型数 |
---|---|---|
XSQLCHAR | CHAR | 1 |
XSQLSMINT | SMALLINT | 5 |
XSQLINT | INTEGER | 4 |
XSQLFLOAT | FLOAT | 6 |
XSQLDECIMAL | DECIMAL | 3 |
4.SQLDA结构
struct sqlvar_struct { short sqltype; /* variable type */ short sqllen; /* length in bytes */ char *sqldata; /* pointer to data */ short *sqlind; /* pointer to indicator */ char *sqlname; /* variable name */ char *sqlformat; /* reserved for future use */ short sqlitype; /* ind variable type */ short sqlilen; /* ind length in bytes */ char *sqlidata; /* ind data pointer */ }; struct sqlda { short sqld; struct sqlvar_struct *sqlvar; };
不同系统中的定义不尽相同。含义说明如下:
sqld:表示SELECT语句返回值的字段数目或带参数的动态SQL语句中的参数数目。也就是sqlvar指向结构的数目。
sqlvar:指向sqlvar_struct结构的指针。sqlvar_struct结构链描述了各字段或参数的必要信息,下标从0开始。
sqltype:传送数据的类型。
sqllen:字符数组(CHAR和VARCHAR)的字节大小;DATETIME和INTERVAL类型的编码修饰符的字节大小。
sqldata:指向字符数据的指针。
sqlind:指向短整型指示变量的指针。
sqlname:指向字符数组的指针,数组中存放字段名或传送的显示标签。
sqlformat:保留。
sqlitype:指示变量的类型。
sqlilen:指示变量的字节长度。
sqlidata:指向字符指示数据的指针。
5.动态SQL语句语法
(1).PREPARE
PREPARE statement_id FROM sql_string;
其中,statement_id:语句标识符,可以是宿主变量;
sql_string:要准备的语句,可以是宿主变量,但语句中不能包含宿主变量。
该语句把sql发送到后端进行语法分析和分配空间。如果一条语句要反复执行,最好先准备该语句。
不能准备“SELECT … INTO …”语句,也不能准备如下语句:CLOSE、EXECUTE IMMEDIATE、FREE、PUT、DECLARE、FETCH、OPEN、WHENEVER、EXECUTE、FLUSH。
可以使用占位符“?”给表达式提供值,但不能用来表示数据库名、表名或字段名等对象。
statement_id对其所在的源程序中是全局的。所以,在同一个源文件中,一个语句标示符只能对应一条RDSQL语句;在同一个源文件的不同函数里可以引用同一个语句标示符;对于不同的原文件,语句标示符不能像外部变量那样相互引用。
(2).EXECUTE
EXECUTE { IMMEDIATE sql_string | statement_id [ USING { variable_list | SQL DESCRIPTOR descriptor | DESCRIPTOR sqlda_pointer } ] }
运行事先准备好的sql语句,EXECUTE不能执行检索数据到宿主变量的SELECT语句,但可以执行“SELECT …INTO TEMP..”语句。
使用IMMEDIATE表示在一个步骤里既准备语句又执行语句。
(3).DESCRIBE
DESCRIBE statement_id { USING SQL DESCRIPTOR descriptr | INTO sqlda_pointer }
对于SELECT语句,DESCRIBE返回查询字段的部分信息。对于INSERT语句,DESCRIBE返回要输入参数的数目、数据类型和空间大小等信息。返回信息存放到系统描述区或SQLDA结构里。对于SQLDA结构,返回下列值:sqld、sqlvar->sqlname、sqlvar->sqltype、sqlvar->sqllen。
对于UPDATE或DELETE语句,如果没有WHERE语句,则把sqlca.sqlwarn.sqlwarn4的值设置为W。
DESCRIBE不检查WHERE子句。
对于不带INTO TEMP子句的SELECT语句,将sqlca.sqlcode设置为0;对于其他语句,将其设置为一个正整数,该数代表RDSQL语句的类型,其定义在sqlstype.h中。
(4).DECLARE
DECLARE cursor_name [ SCROLL ] CURSOR FOR statement_id;
说明SELECT游标,可通过语句标识符statement_id来说明事先准备的动态语句。
(5).OPEN
OPEN cursor_name [ { USING variable_list | SQL DESCRIPTOR descriptor | DESCRIPTOR sqlda_pointer } ]
为SELECT游标建立搜索准则并将其初始化。
为INSERT游标建立插入缓冲区,此时不能包含USING子句。
(6)FETCH
FETCH [ position ] cursor_name [ { INTO host_varlist | USING SQL DESCRIPTOR descriptor | USING DESCRIPTOR sqlda_pointer } ]
(7).PUT
PUT cusor_name [ {USING SQL DESCRIPTOR descriptor | USING DESCRIPTOR sqlda_pointer | FROM variable_list } ]
(8).FREE
FREE { cursor_id | statement_id }
释放游标标示符/变量,语句标示符/变量。
(9).ALLOCATE DESCRIPTOR
ALLOCATE DESCRIPTOR descriptor [ WITH MAX occurrence ]
其中,descriptor是系统描述区描述符,可以是宿主变量;
occurrence是动态sql语句中的占位符。WITH MAX指定最大的占位符数量,缺省为100。
该语句为系统描述区分配内存空间。
(10).DEALLOCATE DESCRIPTOR
DEALLOCATE DESCRIPTOR descriptor;
释放一个系统描述区。
无法释放SQLDA结构。
(11).GET DESCRIPTOR
GET DESCRIPTOR descriptor { host_variabe = COUNT | VALUE item_number host_variabe = item_info [, host_variable = item_info ] … }
其中item_info含义见系统描述区结构部分。
从系统描述区获取信息,把它们存放到所说明的宿主变量中。由如下三个功能:
- 通过获取COUNT域值判明系统描述符区中有多少个值;
- 判断系统描述符区中描述的字段或表达式的特征;
- 把系统描述区中的值拷贝到一个宿主变量中。
(12).SET DESCRIPTOR
SET DESCRIPTOR descriptor { COUNT = value | VALUE item_number item_info = value [, item_info = value ] … }
设置描述符区的COUNT域和字段。
如果它是一个CHARACTER项,则必须设置LENGTH域。
对于DATETIME或INTERVAL域,可以把DATA域设置为一个内部DATETIME或INTERVAL类型,或作为一个字符串。如果设置了一个字符串,必须把LENGTH域设置到编码修饰符值中。