printf(\sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
}
从上面这个例子,我们看出嵌入SQL的基本特点是:
1、每条嵌入式SQL语句都用EXEC SQL开始,表明它是一条SQL语句。这也是告诉预编译器在EXEC SQL和“;”之间是嵌入SQL语句。
2、如果一条嵌入式SQL语句占用多行,在C程序中可以用续行符“\\”,在Fortran中必须有续行符。其他语言也有相应规定。
3、每一条嵌入SQL语句都有结束符号,如:在C中是“;”。 4、嵌入SQL语句的关键字不区分大小写。
5、可以使用“/*….*/”来添加注释。也可以使用“--”来添加注释。
2.2 嵌入SQL的处理过程
嵌入SQL的处理过程如下图所示:
Open Client嵌入宿主语言 嵌入SQLSQL预编译器 程序 源程序 Open client Client-library C编译器 可执行程序 连接器 目标代码
图6-1 SYBASE SQL SERVER嵌入SQL程序处理过程
嵌入SQL程序的后缀为.cp。嵌入SQL处理的第一步是预编译。预编译器(cpre.exe)处理过程分为两个小步:
第一小步:语法分析。检查嵌入SQL语句的语法正确性。
第二小步:增加一些预编译器变量,并注释了所有的嵌入的SQL语句,将嵌入SQL语句转换为对client-library中函数的调用(注意:在连接时,编译后的代码需要使用client-library中的库文件)。如果在编译时,设置一些选项,则生成存储过程。预编译后可能产生3个文件:一个C文件(肯定产生),一个列表文件(需要在编译时设置选项,才能产生)和一个isql脚本文件(需要在编译时设置选项,才能产生)。列表文件包含了输入文件的源语句和一些警告信息和错误信息。Isql脚本文件包含了预编译器产生的存储过程脚本文件。这个存储过程是用T-SQL写的。总之,预编译器的处理方法是,注释了嵌入的SQL语句,用一些特定的函数代替。
第二步是C源程序的编译和链接。cl是编译和链接命令的集成命令,编译的结果是产生.obj,在链接时,将C的系统库和SQL Server提供的库文件同目标文件连接在一起。最后生成.exe。也可以使用SET LIB语句设置库文件的环境信息。
6
2.3 嵌入SQL语句总览
除了print、readtext和writetext外,大多数的Transact-SQL语句都可以在嵌入SQL中使用。嵌入SQL语句的语法为:“exec sql [at connection_name] sql_statement; ”。那么,你可以用Transact-SQL语句来替代sql_statement 就可以完成嵌入SQL的编写。(同T-SQL相比,嵌入SQL提供了:自动数据类型转换、动态SQL、SQLCA数据结构等功能。)
但是,也有一些嵌入式SQL所特有的语句,有些嵌入式SQL语句的名字同Transact-SQL语句相同,但是语句的语法有所不同。
嵌入SQL语句应该包含五个步骤: 1)、通过SQLCA建立应用程序和SQL SERVER的SQL通信区域。 2)、声明宿主变量。 3)、连接到SQL SERVER。 4)、通过SQL语句操作数据。 5)、处理错误和结果信息。
嵌入式SQL语句分为静态SQL语句和动态SQL语句两类。下面我们按照功能讲解这些语句。本节讲解静态SQL语句的作用。动态SQL语句将在下一节讲解。同动态SQL相关的一些语句也在下一节中讲解。
2.3.1 宿主变量
1)、声明方法
宿主变量(host variable)就是在嵌入式SQL语句中引用主语言说明的程序变量(如例中的user[31]变量)。如:
EXEC SQL BEGIN DECLARE SECTION; char user[31],passwd[31];
EXEC SQL END DECLARE SECTION; …………
exec sql connect :user identified by :passwd;
………….
在嵌入式SQL语句中使用主变量前,必须采用BEGIN DECLARE SECTION 和END DECLARE SECTION之间给主变量说明。这两条语句不是可执行语句,而是预编译程序的说明。主变量是标准的C程序变量。嵌入SQL语句使用主变量来输入数据和输出数据。C程序和嵌入SQL语句都可以访问主变量。
另外,在定义宿主变量时也可以使用client-library定义的数据类型,如:CS_CHAR。这些定义存放在cspublic.h文件中。如: EXEC SQL BEGIN DECLARE SECTION; CS_CHAR user[30],passwd[30]; EXEC SQL END DECLARE SECTION;
client-library定义的数据类型共有:CS_BINARY、CS_BIT、 CS_BOOL、 CS_CHAR、 CS_DATETIME、CS_DATETIME4、 CS_DECIMAL、 CS_FLOAT、 CS_REAL、CS_IMAGE、 CS_INT、 CS_MONEY、 CS_MONEY4、 CS_NUMERIC、CS_RETCODE、
7
CS_SMALLINT、 CS_TEXT、 CS_TINYINT、CS_VARBINARY、 CS_VARCHAR、 CS_VOID。
为了便于识别主变量,当嵌入式SQL语句中出现主变量时,必须在变量名称前标上冒号(:)。冒号的作用是,告诉预编译器,这是个主变量而不是表名或列名。不能在声明时,初始化数组变量。
由上可知,SYBASE SQL SERVER使用宿主变量传递数据库中的数据和状态信息到应用程序,应用程序也通过宿主变量传递数据到SYBASE数据库。根据上面两种功能,宿主变量分为输出宿主变量和输入宿主变量。在SELECT INTO和FETCH语句之后的宿主变量称作“输出宿主变量”,这是因为从数据库传递列数据到应用程序。如:
exec sql begin declare section; CS_CHAR id[5];
exec sql end declare section;
exec sql select title_id into :id from titles where pub_id = \
除了SELECT INTO和FETCH语句外的其他SQL语句(如:INSERT、UPDATE等语句)中的宿主变量,称为“输入宿主变量”。这是因为从应用程序向数据库输入值。如:
exec sql begin declare section; CS_CHAR id[7];
CS_CHAR publisher[5];
exec sql end declare section; ...
exec sql delete from titles where title_id = :id; exec sql update titles set pub_id = :publisher
where title_id = :id;
另外,也可以通过宿主变量获得存储过程的执行状态信息。如:
exec sql begin declare section; CS_SMALLINT retcode;
exec sql end declare section; exec sql begin transaction;
exec sql exec :retcode = update_proc; if (retcode != 0) {
exec sql rollback transaction;
也可以通过宿主变量获得存储过程的返回值。如: exec sql exec a_proc :par1 out, :par2 out;
2)、主变量的数据类型
SYBASE SQL SERVER支持的数据类型与程序设计语言支持的数据类型之间有很大差别。这些差别对主变量影响很大。一方面,主变量是一个用程序设计语言的数据类型说明并用程序设计语言处理的程序变量;另一方面,在嵌入SQL语句中用主变量保存数据库数据。所以,在嵌入SQL语句中,必须映射C数据类型为合适的SQL Server数据类型。必须慎重选择主变量的数据类型。在SQL SERVER中,预编译器能够自动转换兼容的数据类型。请看下面这个例子:
8
EXEC SQL BEGIN DECLARE SECTION; int hostvar1 = 39;
char *hostvar2 = \float hostvar3 = 355.95;
EXEC SQL END DECLARE SECTION;
EXEC SQL UPDATE inventory SET department = :hostvar1 WHERE part_num = \
EXEC SQL UPDATE inventory SET prod_descrip = :hostvar2 WHERE part_num = \
EXEC SQL UPDATE inventory SET price = :hostvar3
WHERE part_num = \
在第一个update语句中,department列为smallint数据类型(integer ),所以应该把hostvar1定义为int数据类型(integer)。这样的话,从C到SQL Server的hostvar1可以直接映射。在第二个update语句中,prod_descip列为varchar数据类型,所以应该把hostvar2定义为字符数组。这样的话,从C到SQL Server的hostvar2可以从字符数组映射为varchar数据类型。在第三个update语句中,price列为money数据类型。在C语言中,没有相应的数据类型,所以用户可以把hostvar3定义为C的浮点变量或字符数据类型。SQL Server可以自动将浮点变量转换为money数据类型(输入数据),或将money数据类型转换为浮点变量(输出数据)。
注意的是,如果数据类型为字符数组,那么SQL Server会在数据后面填充空格,直到填满该变量的声明长度(CS_CHAR数据类型除外)。
下表列出了C的数据类型和SQL SERVER数据类型的一些兼容关系:
可兼容的C数据分配的SQL SYBASE提供的数描述 类型 Server数据类型 据类型 short Smallint CS_SMALLINT 2字节整数 Int Smallint CS_SMALLINT 2字节整数 Long Int CS_INT 4字节整数 Float Real CS_REAL 4字节浮点数 Double Float CS_FLOAT 8字节浮点数 Char Carchar[X] CS_CHAR 字符数据类型 VARCHAR Unsigned char Binary CS_BINARY Binary数据类型 Varbinary Unsigned char tinyint CS_TINYINT 1字节整数 Datetime CS_DATETIME 无 8字节datetime类型 Smalldatetime CS_DATETIME4 无 4字节datetime类型 Decimal CS_DECIMAL 无 Decimal数据类型 numeric CS_NUMERIC 无 Numeric数据类型 Money CS_MONEY 无 8字节money类型 smallmoney CS_MONEY4 无 4字节money类型 9
Unsigned char Text CS_TEXT 文本数据类型 Unsigned char image CS_IMAGE 图象数据类型 boolean CS_BIT 无 Bit数据类型 因为C没有date或time数据类型,所以SQL Server的date或time列将被转换为字符。缺省情况下,使用以下转换格式:mm dd yyyy hh:mm:ss[am | pm]。你也可以使用字符数据格式将C的字符数据存放到SQL Server的date列上。你也可以使用Transact-SQL中的convert语句来转换数据类型。如:SELECT CONVERT(char, date, 8) FROM sales。
下表是从SQL SERVER数据类型到C的数据类型的转换关系: SQL C数据类型 SERVER CS_TINYICS_SCS_INT CS_REACS_CHCS_MOCS_DATNT 数据类型 MALLIL AR NEY ETIME NT char 可以 可以 可以 可以 可以 可以 可以 varchar 可以 可以 可以 可以 可以 可以 可以 bit 可以 可以 可以 可以 可以 可以 binary 可以 可以 可以 可以 可以 可以 tinyint 可以 可以 可以 可以 可以 可以 smallint 可以 可以 可以 可以 可以 可以 int 可以 可以 可以 可以 可以 可以 float 可以 可以 可以 可以 可以 可以 money 可以 可以 可以 可以 可以 可以 datetime 可以 可以 decimal 可以 可以 可以 可以 可以 可以 numeric 可以 可以 可以 可以 可以 可以 下表是从C的数据类型到SQL SERVER数据类型的转换关系: C数据SQL SERVER数据类型 tinyinbit smalliint float char money 类型 t nt Unsig可以 可以 可以 可以 可以 需要可以 ned 自己char 转换 Short 可以 可以 可以 可以 可以 需要可以 int 自己转换 Long 可以 可以 可以 可以 可以 需要可以 int 自己转换 Doubl可以 可以 可以 可以 可以 需要可以 e float 自己转换 Char 需要需要需要需要需要可以 需要自自己自己自己自己自己己转换 转换 转换 转换 转换 转换 mone可以 可以 可以 可以 可以 可以 可以 y dateti 需要 me 自己转换 datetime decimal 可以 numeric 可以 可以 可以 可以 可以 可以 可以 可以 可以 需要自己转换 可以 需要自己转换 可以 10