📄 esql-c资料(完全版)四_unix_操作系统_网络学院_天新网.htm
字号:
Sqllen。代表传送数据的长度。如:2,即代表二字节整数。如果是字符串,则该数据为字符串中的字符数量。<BR>lSqldata。指向数据的地址。注意,仅仅是一个地址。<BR>lSqlind。代表是否为NULL。如果该列不允许为NULL,则该字段不赋值;如果该列允许为NULL,则:该字段若为0,表示数据值不为NULL,若为-1,表示数据值为NULL。<BR>lSqlname。代表列名或变量名。它是一个结构。包含length和data。Length是名字的长度;data是名字。<BR>lSqlformat。保留为以后使用。<BR>lSqlitype。指定用户定义的指示符变量的数据类型。<BR>lSqlilen。指定用户定义的指示符变量的长度。<BR>lSqlidata。指向用户定义的指示符变量所存放的数据。
<P>下面这个ADHOC程序非常经典,演示了SQLDA的作用。模拟一个不确定的查询,然后通过SQLDA来获得数据,并打印出来。<BR>EXEC
SQL include locator.h;<BR>EXEC SQL include sqltypes.h;<BR>#define
BLOBSIZE 32276;<BR>main()<BR>{<BR>int i = 0;<BR>int
row_count;<BR>/**** Step 1: 声明一个SQLDA结构,来存放查询的数据 ********/<BR>struct
sqlda *da_ptr;<BR>/*连接到数据库服务器*/<BR>EXEC SQL connect to
'stores7';<BR>if ( SQLCODE < 0 )<BR>{ printf("CONNECT failed:
%d\n", SQLCODE)<BR>exit(0);<BR>}<BR>/*
创建一个临时表,模拟一个不确定列和表的环境*/<BR>EXEC SQL create table blob_tab (int_col
integer, blob_col byte);<BR>/*
load_db函数是往blob_tab表插入数据,读者不用关心它的代码*/<BR>load_db();<BR>/*
PREPARE查询语句 */<BR>EXEC SQL prepare selct_id 'select * from
tab1';<BR>/* Step 2: 使用describe函数完成两个功能:一是为sqlda分配空间,
二是获取语句信息,并存放在SQLDA结构中。*/<BR>EXEC SQL describe selct_id into
da_ptr;<BR>/* Step 3: 初试化sqlda结构,如:为列分配空间,改变数据类型等。*/<BR>row_size =
init_sqlda(da_ptr, 0);<BR>/* 为PREPARE的SELECT语句声明和打开游标*/<BR>EXEC SQL
declare curs for selct_id;<BR>EXEC SQL open curs;<BR>while
(1)<BR>{<BR>/* Step 4: 执行fetch操作,将一行数据存放在sqlda结构中*/<BR>EXEC SQL
fetch curs using descriptor da_ptr;<BR>/* 是否到达最后一行?,若是,则退出。 */<BR>if
( SQLCODE == SQLNOTFOUND )<BR>break;<BR>/* Step 5:
从SQLDA中打印数据,使用sqlca.sqlerrd[2]来获得查询的行数*/<BR>printf("\n===============\n");<BR>printf("FETCH
%d\n", i++);<BR>printf("===============");<BR>print_sqlda(da_ptr,
((FetArrSize == 0) ? 1 : sqlca.sqlerrd[2]));<BR>/* Step 6:
循环执行FETCH,直到处理完所有的行(SQLCODE为SQLNOTFOUND)*/<BR>}<BR>/* Step 7:
释放申请的内存空间,如游标、SQLDA、创建的临时表等*/<BR>EXEC SQL free selct_id;<BR>EXEC SQL
close curs;<BR>EXEC SQL free
curs;<BR>free_sqlda(da_ptr);<BR>cleanup_db();<BR>}<BR>/************************************************************************<BR>*
函数: init_sqlda()<BR>* 作用: 为SQLDA申请空间<BR>* 返回值: 0
正确,否则有错误<BR>************************************************************************/<BR>int
init_sqlda(in_da, print)<BR>struct sqlda *in_da;<BR>int
print;<BR>{<BR>int i, j, row_size=0, msglen=0,
num_to_alloc;<BR>struct sqlvar_struct *col_ptr;<BR>loc_t
*temp_loc;<BR>char *type;<BR>if (print)<BR>printf("columns: %d. ",
in_da->sqld);<BR>/* Step 1: 获得一行数据的长度 */<BR>for (i = 0, col_ptr =
in_da->sqlvar; i < in_da->sqld; i++, col_ptr++)<BR>/*
msglen变量存放查询数据的所有列的长度和。*/<BR>msglen += col_ptr->sqllen; /* get
database sizes */<BR>/* 为col_ptr->sqllen
重新赋值,该值是在C下的大小。如:在数据库中的字符串,在C中应该多一个字节空间来存放NULL的结束符。*/<BR>col_ptr->sqllen
= rtypmsize(col_ptr->sqltype,
col_ptr->sqllen);<BR>/*row_size变量存放了在C程序中的所有列的长度和。这个值是应用程序为存放一行数据所需要申请的内存空间*/<BR>row_size
+= col_ptr->sqllen;<BR>}<BR>if (print) printf("Total row size =
%d\n", row_size);<BR>/* Step 2: 设置FetArrSize值*/<BR>if (FetArrSize ==
-1) /* if FetArrSize not yet initialized */<BR>{<BR>if (FetBufSize
== 0) /* if FetBufSize not set */<BR>FetBufSize = 4096; /* default
FetBufSize */<BR>FetArrSize =
FetBufSize/msglen;<BR>}<BR>num_to_alloc = (FetArrSize == 0)? 1:
FetArrSize;<BR>/* 设置sqlvar_struct结构中的数据类型为相应的C的数据类型*/<BR>for (i = 0,
col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)<BR>{<BR>switch(col_ptr->sqltype)<BR>{<BR>case
SQLCHAR:<BR>type = "char ";<BR>col_ptr->sqltype =
CCHARTYPE;<BR>break;<BR>case SQLINT:<BR>type = "int
";<BR>col_ptr->sqltype = CINTTYPE;<BR>break;<BR>case
SQLBYTES:<BR>case SQLTEXT:<BR>if (col_ptr->sqltype ==
SQLBYTES)<BR>type = "blob ";<BR>else<BR>type = "text
";<BR>col_ptr->sqltype = CLOCATORTYPE;<BR>/* Step 3 :只有数据类型为TEXT
和BLOB时,才执行。为存放TEXT 或BYTE列数据申请空间*/<BR>temp_loc = (loc_t
*)malloc(col_ptr->sqllen * num_to_alloc);<BR>if
(!temp_loc)<BR>{<BR>fprintf(stderr, "blob sqldata malloc
failed\n");<BR>return(-1);<BR>}<BR>col_ptr->sqldata = (char
*)temp_loc;<BR>/* Step 4:只有数据类型为TEXT
和BLOB时,才执行。初试化loc_t结构*/<BR>byfill(temp_loc,
col_ptr->sqllen*num_to_alloc ,0);<BR>for (j = 0; j<
num_to_alloc; j++, temp_loc++)<BR>{<BR>temp_loc->loc_loctype =
LOCMEMORY;<BR>temp_loc->loc_bufsize =
BLOBSIZE;<BR>temp_loc->loc_buffer = (char
*)malloc(BLOBSIZE);<BR>if
(!temp_loc->loc_buffer)<BR>{<BR>fprintf(stderr, "loc_buffer
malloc failed\n");<BR>return(-1);<BR>}<BR>temp_loc->loc_oflags =
0; /* clear flag */<BR>} /* end for */<BR>break;<BR>default: /*
其他数据类型*/<BR>fprintf(stderr, "not yet handled(%d)!\n",
col_ptr->sqltype);<BR>return(-1);<BR>} /* switch */<BR>/* Step 5:
为指示符变量申请空间*/<BR>col_ptr->sqlind =<BR>(short *)
malloc(sizeof(short) * num_to_alloc);<BR>if
(!col_ptr->sqlind)<BR>{<BR>printf("indicator malloc
failed\n");<BR>return -1;<BR>/* Step 6 :为存放非TEXT
和BLOB的数据类型的sqldata申请空间.注意的是,申请的地址是(char
*),在输出数据时,要按照相应的数据类型做转换。*/<BR>if (col_ptr->sqltype !=
CLOCATORTYPE)<BR>{<BR>col_ptr->sqldata = (char *)
malloc(col_ptr->sqllen * num_to_alloc);<BR>if
(!col_ptr->sqldata)<BR>{<BR>printf("sqldata malloc
failed\n");<BR>return -1;<BR>}<BR>if (print)<BR>printf("column %3d,
type = %s(%3d), len=%d\n", i+1, type,<BR>col_ptr->sqltype,
col_ptr->sqllen);<BR>} /* end for */<BR>return
msglen;<BR>}<BR>/************************************************************************<BR>*
函数: print_sqlda<BR>* 作用:
打印存放在SQLDA结构中的数据。<BR>************************************************************************/<BR>void
print_sqlda(sqlda, count)<BR>struct sqlda *sqlda;<BR>int
count;<BR>{<BR>void *data;<BR>int i, j;<BR>loc_t
*temp_loc;<BR>struct sqlvar_struct *col_ptr;<BR>char *type;<BR>char
buffer[512];<BR>int ind;<BR>char i1, i2;<BR>/* 打印列数 (sqld)
和行数*/<BR>printf("\nsqld: %d, fetch-array elements: %d.\n",
sqlda->sqld, count);<BR>/* 外循环:针对每一行数据循环处理 */<BR>for (j = 0; j
< count; j ++)<BR>{<BR>if (count >
1)<BR>{<BR>printf("record[%4d]:\n", j);<BR>printf("col | type | id |
len | ind | rin | data ");<BR>printf("|
value\n");<BR>printf("--------------------------------------------");<BR>printf("------------------\n");<BR>}<BR>/*
内循环: 针对每一列数据处理*/<BR>for (i = 0, col_ptr = sqlda->sqlvar; i <
sqlda->sqld;<BR>i++, col_ptr++)<BR>{<BR>data =
col_ptr->sqldata + (j*col_ptr->sqllen);<BR>switch
(col_ptr->sqltype)<BR>{<BR>case CFIXCHARTYPE:<BR>case
CCHARTYPE:<BR>type = "char";<BR>if (col_ptr->sqllen >
40)<BR>sprintf(buffer, " %39.39s<..",
data);<BR>else<BR>sprintf(buffer, "%*.*s",
col_ptr->sqllen,<BR>col_ptr->sqllen, data);<BR>break;<BR>case
CINTTYPE:<BR>type = "int";<BR>sprintf(buffer, " %d", *(int *)
data);<BR>break;<BR>case CLOCATORTYPE:<BR>type = "byte";<BR>temp_loc
= (loc_t *)(col_ptr->sqldata +<BR>(j *
sizeof(loc_t)));<BR>sprintf(buffer, " buf ptr: %p, buf sz:
%d,<BR>blob sz: %d",
temp_loc->loc_buffer,<BR>temp_loc->loc_bufsize,
temp_loc->loc_size);<BR>break;<BR>default:<BR>type =
"??????";<BR>sprintf(buffer, " type not implemented: ",<BR>"can't
print %d", col_ptr->sqltype);<BR>break;<BR>} /* end switch
*/<BR>i1 = (col_ptr->sqlind==NULL) ? 'X'
:<BR>(((col_ptr->sqlind)[j] != 0) ? 'T' : 'F');<BR>i2 =
(risnull(col_ptr->sqltype, data)) ? 'T' : 'F';<BR>printf("%3d |
%-6.6s | %3d | %3d | %c | %c | ",<BR>i, type, col_ptr->sqltype,
col_ptr->sqllen, i1, i2);<BR>printf("%8p |%s\n", data,
buffer);<BR>} /* end for (i=0...) */<BR>} /* end for (j=0...)
*/<BR>}<BR>/************************************************************************<BR>*
函数: free_sqlda<BR>* 作用: 释放以下对象申请的内存空间<BR>* o loc_buffer memory (used
by TEXT & BYTE)<BR>* o sqldata memory<BR>* o sqlda
structure<BR>************************************************************************/<BR>void
free_sqlda(sqlda)<BR>struct sqlda *sqlda;<BR>{<BR>int i,j,
num_to_dealloc;<BR>struct sqlvar_struc *col_ptr;<BR>loc_t
*temp_loc;<BR>for (i = 0, col_ptr = sqlda->sqlvar; i <
sqlda->sqld;<BR>i++, col_ptr++)<BR>{<BR>if ( col_ptr->sqltype
= CLOCATORTYPE )<BR>{<BR>/* Free memory for blob buffer of each
element in fetch array */<BR>num_to_dealloc = (FetArrSize == 0)? 1:
FetArrSize;<BR>temp_loc = (loc_t *) col_ptr->sqldata;<BR>for (j =
0; j< num_to_dealloc; j++,
temp_loc++)<BR>free(temp_loc->loc_buffer);<BR>}<BR>/* Free memory
for sqldata (contains fetch array)
*/<BR>free(col_ptr->sqldata);<BR>}<BR>/* Free memory for sqlda
structure */<BR>free(sqlda);<BR>}<BR>第六节Microsoft SQL
Server7嵌入式SQL语言<BR>6.1
一个嵌入SQL语言的简单例子<BR>我们首先来看一个简单的嵌入式SQL语言的程序(C语言):在YANGZH服务器的pubs数据库上查询lastname为“White”的firstname。用sa(口令为pass<A
href="http://school.21tx.com/office/word/"
target=_blank>Word</A>)连接数据库服务器。这个例子程序如下:<BR>例1、查询lastname为“White”的firstname的信息。<BR>main()<BR>{<BR>EXEC
SQL BEGIN DECLARE SECTION;<BR>char first_name[50];<BR>char
last_name[] = "White";<BR>EXEC SQL END DECLARE SECTION;<BR><BR>EXEC
SQL CONNECT TO YANGZH.pubs<BR>USER sa.password;<BR>EXEC SQL SELECT
au_fname INTO :first_name<BR>from authors where au_lname =
:last_name;<BR>printf("first name: %s\n",first_name);<BR>return
(0);<BR>}
<P>从上面这个例子,我们看出嵌入SQL的基本特点是:<BR>1、每条嵌入式SQL语句都用EXEC
SQL开始,表明它是一条SQL语句。这也是告诉预编译器在EXEC
SQL和“;”之间是嵌入SQL语句。<BR>2、如果一条嵌入式SQL语句占用多行,在C程序中可以用续行符“\”,在Fortran中必须有续行符。其他语言也有相应规定。<BR>3、每一条嵌入SQL语句都有结束符号,如:在C中是“;”。
<P>如果你需要在NT平台编写C的嵌入SQL语句,那么你必须保证设置了以下环境:<BR>l<A
href="http://school.21tx.com/os/win2000/" target=_blank>Windows
NT</A> Workstation 3.51或以上;或者Windows NT Server
3.51或以上<BR>lVC++版本2.0或以上;或者其他100%兼容的编译器和连接器。<BR>lSQL
Server6.0或以上<BR>如果你需要在Windows95/98平台编写C的嵌入SQL语句,那么你必须保证设置了以下环境:<BR>lWindows
95/98<BR>lVC++版本2.0或以上;或者其他100%兼容的编译器和连接器。<BR>lSQL
Server6.0或以上<BR>6.2
嵌入SQL的处理过程<BR>下面我们来说明整个嵌入SQL的处理过程。以下是生成可执行文件的步骤:<BR>1、在命令提示符下执行
…\VC98\bin\vcvar32.bat,作用是设置C的环境信息。<BR>2、在命令提示符下执行:nmake –f demo.mk
。执行后,生成demo.exe。<BR>其中,demo.mk为(在NT平台):<BR>demo.exe:demo.sqc<BR>set
include=e:\mssql7\devtools\include;%include%;<BR>nsqlprep
demo.sqc<BR>cl -o demo.exe e:\mssql7\devtools\lib\sqlakw32.lib
\<BR>e:\mssql7\devtools\lib\caw32.lib demo.c<BR>其中,<BR>l“set
include=e:\mssql7\devtools\include;%include%;”的作用是,说明整个头文件的路径信息。即包含sqlca.h和sqlda.h路径信息。在嵌入SQL程序中,无需使用“#include
<sqlca.h>”和“#include
<sqlda.h>”语句,这是因为nsqlprep.exe预编译器会自动将这些语句插入预编译后的C程序中。<BR>l“nsqlprep
demo.sqc”是SQL Server7的预编译处理。Nsqlprep.exe是SQL
Server7的预编译器。处理的结果产生C的程序,如demo.c。demo.c的程序为:<BR>例2、demo.c程序<BR>/*
===== demo.c =====*/
<P><BR>/* ===== NT doesn't need the following... */<BR>#ifndef
WIN32<BR>#define WIN32<BR>#endif<BR>#define _loadds<BR>#define
_SQLPREP_<BR>#include <sqlca.h><BR>#include
<sqlda.h><BR>#include <string.h><BR>#define SQLLENMAX(x)
( ((x) > 32767) ? 32767 : (x) )<BR>short ESQLAPI _loadds
sqlaaloc(<BR>unsigned short usSqlDaId,<BR>unsigned short
sqld,<BR>unsigned short stmt_id,<BR>void far *spare);
<P>short ESQLAPI _loadds sqlxcall(<BR>unsigned short
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -