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、 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 = 0736 and type = business;
除了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中,预编译器能够自动转换兼容的数据类型。请看下面这个例子: EXEC SQL BEGIN DECLARE SECTION; int hostvar1 = 39;
char *hostvar2 = telescope; float hostvar3 = 355.95;
EXEC SQL END DECLARE SECTION; EXEC SQL UPDATE inventory SET department = :hostvar1 WHERE part_num = 4572-3; EXEC SQL UPDATE inventory SET prod_descrip = :hostvar2 WHERE part_num = 4572-3; EXEC SQL UPDATE inventory SET price = :hostvar3 WHERE part_num = 4572-3;
在第一个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 Server数据类型SYBASE提供的数据类型描述 shortSmallintCS_SMALLINT2字节整数 IntSmallintCS_SMALLINT2字节整数 LongIntCS_INT4字节整数 FloatRealCS_REAL4字节浮点数 DoubleFloatCS_FLOAT8字节浮点数
CharCarchar[X]VARCHARCS_CHAR字符数据类型 Unsigned charBinaryVarbinaryCS_BINARYBinary数据类型 Unsigned char tinyintCS_TINYINT1字节整数 无DatetimeCS_DATETIME8字节datetime类型 无SmalldatetimeCS_DATETIME44字节datetime类型 无DecimalCS_DECIMALDecimal数据类型 无numericCS_NUMERICNumeric数据类型 无MoneyCS_MONEY8字节money类型 无smallmoneyCS_MONEY44字节money类型 Unsigned char TextCS_TEXT文本数据类型 Unsigned char imageCS_IMAGE图象数据类型 无booleanCS_BITBit数据类型
因为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 SERVER 数据类型C数据类型
CS_TINYINTCS_SMALLINTCS_INTCS_REALCS_CHARCS_MONEYCS_DATETIME char可以可以可以可以可以可以可以 varchar可以可以可以可以可以可以可以 bit可以可以可以可以可以可以 binary可以可以可以可以可以可以 tinyint可以可以可以可以可以可以 smallint可以可以可以可以可以可以 int可以可以可以可以可以可以 float可以可以可以可以可以可以 money可以可以可以可以可以可以 datetime可以可以
decimal可以可以可以可以可以可以 numeric可以可以可以可以可以可以
下表是从C的数据类型到SQL SERVER数据类型的转换关系:
C数据类型SQL SERVER数据类型
tinyintbitsmallintintfloatcharmoneydatetimedecimalnumeric Unsigned char可以可以可以可以可以需要自己转换可以可以可以 Short int可以可以可以可以可以需要自己转换可以可以可以 Long int可以可以可以可以可以需要自己转换可以可以可以 Double float可以可以可以可以可以需要自己转换可以可以可以
Char需要自己转换需要自己转换需要自己转换需要自己转换需要自己转换可以需要自己转换可以需要自己转换需要自己转换
money可以可以可以可以可以可以可以可以可以 datetime需要自己转换可以 3)、主变量和NULL
大多数程序设计语言(如C)都不支持NULL。所以对NULL的处理,一定要在SQL中完成。我们可以使用主机指示符变量(host indicator variable)来解决这个问题。在嵌入式SQL语句中,主变量和指示符变量共同规定一个单独的SQL类型值。如:
EXEC SQL SELECT price INTO :price :price_nullflag FROM titles WHERE au_id = mc3026
其中,price是主变量,price_nullflag是指示符变量。
使用指示符变量的语法为:: host_variable [[indicator] : indicator_variable]。其中,indicator可以不写。针对宿主变量是输出宿主变量,还是输入宿主变量。指示符变量共分两种情况。 情况1:同输出宿主变量一起使用,则indicator_varibale为:
l-1。表示相应列值为NULL。表示主变量应该假设为NULL。(注意:宿主变量的实际值是一个无关值,不予考虑)。
l0。表示非NULL值。该变量存放了非NULL的列值。
l>0。表示宿主变量包含了列值的截断值。该指示变量存放了该列值的实际长度。 下面是一个同输出宿主变量一起使用的指示变量的例子: exec sql begin declare section; CS_CHAR id[6]; CS_SMALLINT indic; CS_CHAR pub_name[41]; exec sql end declare section;
exec sql select pub_id into :id indicator :indic from titles where title like %Stress%; if (indic == -1) {
printf(\\npub_id is null); } else {
exec sql select pub_name into :pub_name from publishers where pub_id = :id; printf(\\nPublisher: %s, pub_name);
情况2:同输入宿主变量一起使用,则indicator_varibale为:
l-1。表示主变量应该假设为NULL。(注意:宿主变量的实际值是一个无关值,不予考虑)。应该将NULL赋值给相应列。
l0。表示非NULL值。该变量存放了非NULL值。应该将宿主变量的值赋值给相应列。 对于以下语句:
EXEC SQL SELECT price INTO :price :price_nullflag FROM titles WHERE au_id = mc3026
如果不存在mc3026写的书,那么price_nullflag为-1,表示price为NULL;如果存在,则price为实际的价格。下面我们再看一个update的例子: EXEC SQL UPDATE closeoutsale
SET temp_price = :saleprice :saleprice_null, listprice = :oldprice; 如果saleprice_null是-1,则上述语句等价为: EXEC SQL UPDATE closeoutsale SET temp_price = null, listprice = :oldprice;
我们也可以在指示符变量前面加上―INDICATOR‖关键字,表示后面的变量为指示符变量。如: EXEC SQL UPDATE closeoutsale
SET temp_price = :saleprice INDICATOR :saleprice_null;
指示符变量也是宿主变量,定义指示符变量同定义宿主变量一样。它应该是一个2个字节的整数(short或CS_SMALLINT)。 2.3.2 连接数据库
在程序中,使用CONNECT语句来连接数据库。该语句的完整语法为: exec sql connect : user [identified by : password] [at : connection_name] [using : server]
[labelname labelname labelvalue labelvalue...] 其中, lserver为服务器名。如省略,则为本地服务器名。
lconnection_name为连接名。可省略。如果你仅仅使用一个连接,那么无需指定连接名。可以使用SET CONNECTION来使用不同的连接。 luser为登录名。 lpassword为密码。
如:使用my_id用户和passes密码连接到SYBASE服务器。 exec sql begin declare section; CS_CHAR user[16]; CS_CHAR passwd[16]; CS_CHAR server[BUFSIZ]; exec sql end declare section; strcpy(server,SYBASE); strcpy(passwd,passes); strcpy(user, my_id);
exec sql connect :user identified by :passwd using :server;
请看下面这些例子来理解连接名的使用方法。 ...
exec sql begin declare section; CS_CHAR user[16]; CS_CHAR passwd[16];