printf(\/*释放申请的内存空间*/
exec sql deallocate prepare statement; /* 多行结果示例。对多行查询语句做准备和描述操作*/ exec sql prepare statement from \\
\/*为多行结果声明游标*/
exec sql declare c cursor for statement;
exec sql describe input statement using descriptor input_descriptor; /*设置查询的参数地址信息*/
input_descriptor->sqlda_column->sqlda_sqldata = character;
input_descriptor->sqlda_column->sqlda_datafmt.maxlength =CS_NULLTERM; /*设置参数值为banana,也可以提示用户输入这些信息*/ strcpy(character, \
input_descriptor->sqlda_column->sqlda_sqllen = CS_NULLTERM; /*打开游标*/
exec sql open c using descriptor input_descriptor; /*设置输出列的信息*/
exec sql describe output statement using descriptor output_descriptor; /*设置存放数据的地址信息*/
output_descriptor->sqlda_column->sqlda_sqldata = character;
output_descriptor->sqlda_column->sqlda_datafmt.datatype =CS_CHAR_TYPE; output_descriptor->sqlda_column->sqlda_datafmt.maxlength = 20; output_descriptor->sqlda_column->sqlda_sqllen = 20; output_descriptor->sqlda_column->sqlda_datafmt.format = (CS_FMT_NULLTERM | CS_FMT_PADBLANK);
exec sql fetch c into descriptor output_descriptor; /*打印列的数据*/
printf(\exec sql commit work;
……….
上面这个例子是典型的动态查询程序。该程序中演示了PREPARE语句和DESCRIBE语句的处理方式,以及为程序中检索到的数据分配空间。要注意程序中如何设置sqlda_column结构中的的各个变量。这个程序也演示了OPEN、FETCH和CLOSE语句在动态查询中的应用。值得注意的是,FETCH语句只使用了SQLDA,不使用主变量。由于程序中预先申请了sqlda_column结构中的SQLDATA空间,所以DBMS知道将查询到的数据保存在何处。该程序还考虑了查询数据为NULL的处理。
值得注意的是,SQDA结构不是SQL标准。每个数据库厂商的实现方式有可能不同。
2.4.4 DESCRIBE语句
该语句只有动态SQL才有。该语句是在PREPARE语句之后,在OPEN语句之前使用。该语句的作用是,设置SQLDA中的描述信息,如:列名、数据类型和长度等。DESCRIBE
26
语句的语法为:
DESCRIBE 语句名 INTO 描述符名
如:exec sql describe output statement using descriptor output_descriptor;。
在执行DESCRIBE前,用户必须给出SQLDA中的SQLN的值(表示最多有多少列),该值也说明了SQLDA中最多有多少个sqlda_column结构。然后,执行DESCRIBE语句,该语句填充每一个sqlda_column结构。每个sqlda_column结构中的相应列为:
? Sd_datafmt结构:列名等信息。 ? Sd_sqllen列:给出列的长度。
注意,sd_sqldata列不填充。由程序在FETCH语句之前,给出数据缓冲器地址和指示符地址。
2.5 两个例子程序
2.5.1 TELECOM程序
该程序是模拟电信费用查询。
#include
#if defined (SYBASE) #define SQLNOTFOUND 100 #endif EXEC SQL INCLUDE sqlca;
EXEC SQL BEGIN DECLARE SECTION; char user[30]; char passwd[30]; char Usr_name[61]; char Dev_no[9]; long Call_flg;
27
char Called_arno[11]; char Called_no[15]; char Call_dat[21]; double Call_dur; double Call_rate; double Call_fee; double Add_fee; char as_dev_no[9];
EXEC SQL END DECLARE SECTION; void main(){
char statusbuf[1024], s[30];
/*连接到SQL SERVER服务器*/
printf(\gets(user);
printf(\gets(passwd);
exec sql connect :user identified by :passwd;
exec sql use pubs2; /*输入想要查询的电话号码*/
printf(\ gets(as_dev_no ); /*声明游标*/ EXEC SQL DECLARE c1 CURSOR FOR SELECT bas_infot.Usr_name, auto10a_list.Dev_no, auto10a_list.Call_flg, auto10a_list.Called_arno, auto10a_list.Called_no , auto10a_list.Call_dat, auto10a_list.Call_dur, auto10a_list.Call_rate, auto10a_list.Call_fee, FROM auto10a_list, bas_infot WHERE ( auto10a_list.Dev_no = bas_infot.Dev_no ) AND auto10a_list.Dev_no = :as_dev_no;
/*打开游标,指向查询相关电话信息的结果集*/ EXEC SQL OPEN c1; /* :rk.2:erk. */ do{
/*取出一行数据到各个变量*/ EXEC SQL FETCH c1 INTO :Usr_name, :Dev_no, :Call_flg, :Called_arno, :Called_no, :Call_dat, :Call_dur, :Call_rate, :Call_fee, :Add_fee; if( (sqlca.sqlcode == SQLNOTFOUND) || (sqlca.sqlcode <0) ) break;
/*显示数据*/ printf(\ , Usr_name, Dev_no, Call_flg, Called_arno, Called_no, Call_dat, Call_dur, Call_rate, Call_fee, Add_fee ); }while(1);
28
EXEC SQL CLOSE c1;
EXEC SQL DEALLOCATE CURSOR c1; Exec sql disconnect all; return (0); }
2.5.2 ADHOC程序
该程序的功能是:用户输入任意SQL语句,并执行和打印结果。
#include
/* Defines for BINDING */ /*初试化SQLDA*/
int init_da (SQLDA **DAPointer, int DAsqln); /*为存放列数据的sd_column结构申请空间*/ int alloc_host_vars (SQLDA *sqldaPointer); /*释放SQLDA所申请的空间*/ void free_da (SQLDA *sqldaPointer); /*获取列名信息*/
char * readColName (SQLDA *sqldaPointer, short sd_columnIndex, char * buffer); /*获取列数据*/
char * readCol (SQLDA *sqldaPointer, short sd_columnIndex, char * buffer); #ifdef __cplusplus }
#endif
/*定义最大列数*/
#define MAX_COLUMNS 255
#define MAX_CHAR_FOR_DOUBLE 20 #define MAX_CHAR_FOR_LONG 15 #define MAX_CHAR_FOR_DATETIME 30 #define MAX_CHAR_FOR_DEFAULT 100 EXEC SQL INCLUDE SQLCA ; EXEC SQL INCLUDE SQLDA ;
#define SQLSTATE sqlca.sqlstate #define SQLCODE sqlca.sqlcode /*处理SQL语句*/
int process_statement( char * ) ; int main() { int rc ;
29
char st[1024]; char tmpstr[1024]; /*获得SQL语句*/
printf(\ gets( st);
/* 处理该语句 */
rc = process_statement( st ) ; /*打印处理结果*/ printf( \
printf(\}
/****************************************************************************** * FUNCTION : process_statement * 处理SQL语句
*****************************************************************************/ int process_statement ( char * sqlInput ) {
int counter = 0 ;
SQLDA * sqldaPointer ;
short sqlda_d ; /* Total columns */ short idx;
char buffer[4096]; char varname[1024]; char colnamelist[4096];
EXEC SQL BEGIN DECLARE SECTION ; char st[1024] ;
EXEC SQL END DECLARE SECTION ; strcpy( st, sqlInput ) ;
/* 为SQLDA结构申请空间\
if (init_da( &sqldaPointer, MAX_COLUMNS ) == -1) {
return -1;
}
/*准备SQL语句*/
EXEC SQL PREPARE statement1 from :st ; if (SQLCODE < 0) {
free_da(sqldaPointer); return SQLCODE; }
/*获取查询列的信息到SQLDA结构*/
EXEC SQL DESCRIBE statement1 USING DESCRIPTOR sqldaPointer ; /* 如果SQLCODE为0,则表示为SELECT语句 */ if ( SQLCODE != 0 ) {
30