,。:,提供访问数据库服务器、操作各种数据类型、出错信息的处理等函数。(UNIX环境:$INFORMIXDIR/incl/esql下,WINDOWS环境:%INFORMIXDIR%\incl\esql下),提供程序用的数据结构、常数和宏的定义信息。。UNIX系统下,是程序获得INFORMIX的错误信息,WINDOWS平台下是获得错误信息。还有一些GLS locale文件,提供一些特定的locale信息。在WINDOWS平台下,还有另外一些文件,如:setnet32、ilogin、regcopy、esqlmf程序。 如:。5.4 动态SQL语言所谓静态SQL的编程方法,就是指在预编译时SQL语句已经基本确定,即访问的表或视图名、访问的列等信息已经确定。但是,有时整个SQL语句要到执行的时候才能确定下来,而且SQL语句所访问的对象也要到执行时才能确定。这就需要通过动态SQL语句完成。PREPARE语句是动态SQL语句独有的语句。其语法为: 该语句接收含有SQL语句串的宿主变量,并把该语句送到DBMS。DBMS编译语句并生成执行计划。,当执行语句时,DBMS需要参数来替代这些“?”。PREPRARE执行的结果是,DBMS用语句名标志编译后的语句。在执行SQL语句时,EXECUTE语句后面是这个语句名。请看下面这个例子: EXEC SQL prepare slct_id from 'select company from customer where customer_num = ?'; 可以通过SQLCA检查PREPARE操作是否成功。 EXECUTE语句的语法如下:它的作用是,请求DBMS执行PREPARE语句准备好的语句。当要执行的动态语句中包含一个或多个参数标志时,这样的话,准备语句中的参数标志(“?”),从而,为动态执行语句。 如果是多行查询,则使用游标,使用语句传递参数;如果是单行查询,则使用。如果是修改数据:则使用语句。如果知道参数个数,就可以使用宿主变量。。下表总结了动态SQL语句的处理方法:语句类型是否有输入参数执行的方法INSERT、DELETE、UPDATE没有EXECUTEINSERT、DELETE、UPDATE有(数据类型和个数确定)EXECUTE …USINGINSERT、DELETE、UPDATE有(数据类型和个数不确定)EXECUTE...USINGSQL DESCRIPTOR或EXECUTE...USINGDESCRIPTORSELECT(返回多行)无OPENSELECT(返回多行)有(数据类型和个数确定)OPEN…USINGSELECT(返回多行)有(数据类型和个数不确定)OPEN...USINGSQL DESCRIPTOR或OPEN...USINGDESCRIPTORSELECT(返回一行)无EXECUTE...INTOSELECT(返回一行,但是返回的数据类型和个数不确定)无EXECUTE...INTODESCRIPTOR或EXECUTE...INTOSQL DESCRIPTORSELECT(返回一行)有EXECUTE...INTO...USINGSELECT(返回一行,但是返回的数据类型和个数不确定)有EXECUTE...INTO...USING SQLDESCRIPTOR或EXECUTE...INTO...USINGDESCRIPTOR5.4.1 SQLDA可以。理解。我们知道,动态SQL语句在编译时可能不知道有多少列信息。在嵌入SQL语句中,这些不确定的数据是通过SQLDA完成的。SQLDA的结构非常灵活,在该结构的固定部分,指明了多少列等信息(如下图中的sqld=2,表示为两列信息),在该结构的说明每列的信息。 是一种。位于SQLDA开端的sqldaid用于标志该SQLDA描述了多少列的信息;而后是一个或多个sqlvar结构 ,用于标志列数据。当用SQLDA把参数送到执行语句时,都是一个sqlvar结构;当用SQLDA返回输出列信息时,都是一个sqlvar结构。。具体每个元素的含义为:。即输出列的个数。指向sqlvar_struct结构。 即指向。Sqlda的名称。。Sqlda结构的大小。。指向下一个SQLDA结构。。代表参数或列的数据类型。它是一个整数数据类型代码。具体每个整数的含义见第二节。l 代表传送数据的长度。如:2,即代表二字节整数。如果是字符串,则该数据为字符串中的字符数量。l。指向数据的地址。注意,仅仅是一个地址。l。代表是否为NULL。如果该列不允许为NULL,则该字段不赋值;如果该列允许为NULL,则:该字段若为0,表示数据值不为NULL,若为-1,表示数据值为NULL。l。代表列名或变量名。它是一个结构。包含length和data。Length是名字的长度;data是名字。l。保留为以后使用。l。指定用户定义的的数据类型。lSqllen。指定用户定义的的长度。lSqldata。指向用户定义的所存放的数据。;/*连接到数据库服务器*/EXEC SQL connect to 'stores7';if ( SQLCODE sqld);/* Step 1: 获得一行数据的长度 */for (i = 0, col_ptr = in_da->sqlvar; i sqld; i++, col_ptr++)/* msglen变量存放查询数据的所有列的长度和。*/msglen += col_ptr->sqllen; /* get database sizes *//* 为col_ptr->sqllen 重新赋值,该值是在C下的大小。如:在数据库中的字符串,在C中应该多一个字节空间来存放NULL的结束符。*/col_ptr->sqllen = rtypmsize(col_ptr->sqltype, col_ptr->sqllen);/*row_size变量存放了在C程序中的所有列的长度和。这个值是应用程序为存放一行数据所需要申请的内存空间*/row_size += col_ptr->sqllen;}if (print) printf("Total row size = %d\n", row_size);/* Step 2: 设置FetArrSize值*/if (FetArrSize == -1) /* if FetArrSize not yet initialized */{if (FetBufSize == 0) /* if FetBufSize not set */FetBufSize = 4096; /* default FetBufSize */FetArrSize = FetBufSize/msglen;}num_to_alloc = (FetArrSize == 0)? 1: FetArrSize;/* 设置sqlvar_struct结构中的数据类型为相应的C的数据类型*/for (i = 0, col_ptr = in_da->sqlvar; i sqld; i++, col_ptr++){switch(col_ptr->sqltype){case SQLCHAR:type = "char ";col_ptr->sqltype = CCHARTYPE;break;case SQLINT:type = "int ";col_ptr->sqltype = CINTTYPE;break;case SQLBYTES:case SQLTEXT:if (col_ptr->sqltype == SQLBYTES)type = "blob ";elsetype = "text ";col_ptr->sqltype = CLOCATORTYPE;/* Step 3 :只有数据类型为TEXT 和BLOB时,才执行。为存放TEXT 或BYTE列数据申请空间*/temp_loc = (loc_t *)malloc(col_ptr->sqllen * num_to_alloc);if (!temp_loc){fprintf(stderr, "blob sqldata malloc failed\n");return(-1);}col_ptr->sqldata = (char *)temp_loc;/* Step 4:只有数据类型为TEXT 和BLOB时,才执行。初试化loc_t结构*/byfill(temp_loc, col_ptr->sqllen*num_to_alloc ,0);for (j = 0; jloc_loctype = LOCMEMORY;temp_loc->loc_bufsize = BLOBSIZE;temp_loc->loc_buffer = (char *)malloc(BLOBSIZE);if (!temp_loc->loc_buffer){fprintf(stderr, "loc_buffer malloc failed\n");return(-1);}temp_loc->loc_oflags = 0; /* clear flag */} /* end for */break;default: /* 其他数据类型*/fprintf(stderr, "not yet handled(%d)!\n", col_ptr->sqltype);return(-1);} /* switch *//* Step 5: 为指示符变量申请空间*/col_ptr->sqlind =(short *) malloc(sizeof(short) * num_to_alloc);if (!col_ptr->sqlind){printf("indicator malloc failed\n");return -1;/* Step 6 :为存放非TEXT 和BLOB的数据类型的sqldata申请空间.注意的是,申请的地址是(char *),在输出数据时,要按照相应的数据类型做转换。*/if (col_ptr->sqltype != CLOCATORTYPE){col_ptr->sqldata = (char *) malloc(col_ptr->sqllen * num_to_alloc);if (!col_ptr->sqldata){printf("sqldata malloc failed\n");return -1;}if (print)printf("column %3d, type = %s(%3d), len=%d\n", i+1, type,col_ptr->sqltype, col_ptr->sqllen);} /* end for */return msglen;}/************************************************************************* 函数: print_sqlda* 作用: 打印存放在SQLDA结构中的数据。************************************************************************/struct sqlda *sqlda;int count;{void *data;int i, j;loc_t *temp_loc;struct sqlvar_struct *col_ptr;char *type;char buffer[512];int ind;char i1, i2;/* 打印列数 (sqld) 和行数*/printf("\nsqld: %d, fetch-array elements: %d.\n", sqlda->sqld, count);/* 外循环:针对每一行数据循环处理 */for (j = 0; j 1){printf("record[%4d]:\n", j);printf("col | type | id | len | ind | rin | data ");printf("| value\n");printf("--------------------------------------------");printf("------------------\n");}/* 内循环: 针对每一列数据处理*/for (i = 0, col_ptr = sqlda->sqlvar; i sqld;i++, col_ptr++){data = col_ptr->sqldata + (j*col_ptr->sqllen);switch (col_ptr->sqltype){case CFIXCHARTYPE:case CCHARTYPE:type = "char";if (col_ptr->sqllen > 40)sprintf(buffer, " %39.39ssqllen,col_ptr->sqllen, data);break;case CINTTYPE:type = "int";sprintf(buffer, " %d", *(int *) data);break;case CLOCATORTYPE:type = "byte";temp_loc = (loc_t *)(col_ptr->sqldata +(j * sizeof(loc_t)));sprintf(buffer, " buf ptr: %p, buf sz: %d,blob sz: %d", temp_loc->loc_buffer,temp_loc->loc_bufsize, temp_loc->loc_size);break;default:type = "??????";sprintf(buffer, " type not implemented: ","can't print %d", col_ptr->sqltype);break;} /* end switch */i1 = (col_ptr->sqlind==NULL) ? 'X' :(((col_ptr->sqlind)[j] != 0) ? 'T' : 'F');i2 = (risnull(col_ptr->sqltype, data)) ? 'T' : 'F';printf("%3d | %-6.6s | %3d | %3d | %c | %c | ",i, type, col_ptr->sqltype, col_ptr->sqllen, i1, i2);printf("%8p |%s\n", data, buffer);} /* end for (i=0...) */} /* end for (j=0...) */}/************************************************************************* 函数: free_sqlda* 作用: 释放以下对象申请的内存空间* o loc_buffer memory (used by TEXT & BYTE)* o sqldata memory* o sqlda structure************************************************************************/struct sqlda *sqlda;{int i,j, num_to_dealloc;struct sqlvar_struc *col_ptr;loc_t *temp_loc;for (i = 0, col_ptr = sqlda->sqlvar; i sqld;i++, col_ptr++){if ( col_ptr->sqltype = CLOCATORTYPE ){/* Free memory for blob buffer of each element in fetch array */num_to_dealloc = (FetArrSize == 0)? 1: FetArrSize;temp_loc = (loc_t *) col_ptr->sqldata;for (j = 0; jloc_buffer);}/* Free memory for sqldata (contains fetch array) */free(col_ptr->sqldata);}/* Free memory for sqlda structure */free(sqlda);} 09-03 13:58