分享
 
 
 

ESQL/C资料(完全版)二

王朝mssql·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

第三节 IBM DB2嵌入SQL语言

DB2支持SQL嵌入到C/C++、JAVA、COBOL、FORTRAN和REXX等语言。本节以SQL嵌入C/C++为例子,讲解静态的嵌入SQL编程和动态的嵌入SQL编程。

静态SQL嵌入C语言编程是指,应用程序在书写时,每个SQL语句的大部分都已确定下来(如:查询的表、列和语句的格式等),唯一不确定的是查询语句中某些特定变量的值,这些值可以在执行时由变量传进去,但是,值的类型要事先确定。

3.1 一个简单示例

首先,我们来看一个嵌入静态SQL语句的C程序。

例1、连接到SAMPLE数据库,查询LASTNAME为JOHNSON的FIRSTNAME信息。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "util.h"

#include <sqlca.h>

EXEC SQL INCLUDE SQLCA; (1)

#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1;

int check_error (char eString[], struct sqlca *caPointer) {

char eBuffer[1024];

char sBuffer[1024];

short rc, Erc;

if (caPointer->sqlcode != 0) {

printf ("--- error report ---\n");

printf ("ERROR occured : %s.\nSQLCODE : %ld\n", eString,

caPointer->sqlcode);

}

return 0;

}

int main(int argc, char *argv[]) {

EXEC SQL BEGIN DECLARE SECTION; (2)

char firstname[13];

char userid[9];

char passwd[19];

EXEC SQL END DECLARE SECTION;

printf( "Sample C program: STATIC\n" );

if (argc == 1) {

EXEC SQL CONNECT TO sample;

CHECKERR ("CONNECT TO SAMPLE");

}

else if (argc == 3) {

strcpy (userid, argv[1]);

strcpy (passwd, argv[2]);

EXEC SQL CONNECT TO sample USER :userid USING :passwd; (3)

CHECKERR ("CONNECT TO SAMPLE");

}

else {

printf ("\nUSAGE: static [userid passwd]\n\n");

return 1;

} /* endif */

EXEC SQL SELECT FIRSTNME INTO :firstname

FROM employee

WHERE LASTNAME = 'JOHNSON';(4)

CHECKERR ("SELECT statement"); (5)

printf( "First name = %s\n", firstname );

EXEC SQL CONNECT RESET; (6)

CHECKERR ("CONNECT RESET");

return 0;

}

/* end of program : STATIC.SQC */ 上面是一个简单的静态嵌入SQL语句的应用程序。它包括了静态嵌入SQL的主要部分。

(1)中的include SQLCA语句定义并描述了SQLCA的结构。SQLCA用于应用程序和数据库之间的通讯,其中的SQLCODE返回SQL语句执行后的结果状态。

(2)在BEGIN DECLARE SECTION和END DECLARE SECTION之间定义了主变量。主变量可被SQL语句引用,也可以被C语言语句引用。它用于将程序中的数据通过SQL语句传给数据库管理器,或从数据库管理器接收查询的结果。在SQL语句中,主变量前均有“:”标志以示区别。

(3)在每次访问数据库之前必须做CONNECT操作,以连接到某一个数据库上。这时,应该保证数据库实例已经启动。

(4)是一条选择语句。它将表employee中的LASTNAME为“JOHNSON”的行数据的FIRSTNAME查出,并将它放在firstname变量中。该语句返回一个结果。可以通过游标返回多个结果。

(5)在该程序中通过调用宏CHECKERR(即调用函数check_error)来返回SQL语句执行的结果。Check_error函数在下面讲解。

(6)最后断开数据库的连接。

从上例看出,每条嵌入式SQL语句都用EXEC SQL开始,表明它是一条SQL语句。这也是告诉预编译器在EXEC SQL和“;”之间是嵌入SQL语句。如果一条嵌入式SQL语句占用多行,在C程序中可以用续行符“\”。

3.2 嵌入SQL语句

3.2.1宿主变量

1)、声明方法

宿主变量就是在嵌入式SQL语句中引用主语言说明的程序变量(如上例中的firstname变量)。如:

………….

EXEC SQL SELECT FIRSTNME INTO :firstname (4)

FROM employee

WHERE LASTNAME = 'JOHNSON';

………….

在嵌入式SQL语句中使用宿主变量前,必须采用BEGIN DECLARE SECTION 和END DECLARE SECTION之间给宿主变量说明。这两条语句不是可执行语句,而是预编译程序的说明。宿主变量是标准的C程序变量。嵌入SQL语句使用宿主变量把数据库中查询到的值返回给应用程序(称为输出宿主变量),也用于将程序中给定的值传到SQL语句中(称为输入宿主变量)。显然,C程序和嵌入SQL语句都可以访问宿主变量。

在使用宿主变量前,请注意以下几点:

l宿主变量的长度不能超过30字节。开始的字母不能是EXEC和SQL。

l宿主变量必须在被引用之前定义。

l一个源程序文件中可以有多个SQL说明段。

l宿主变量名在整个程序中必须是唯一的。

2)、宿主变量的数据类型

宿主变量是一个用程序设计语言的数据类型说明并用程序设计语言处理的程序变量;另外,在嵌入SQL语句中用宿主变量保存数据库数据。所以,在嵌入SQL语句中,必须映射C数据类型为合适的DB2数据类型。必须慎重选择宿主变量的数据类型。请看下面这个例子:

EXEC SQL BEGIN DECLARE SECTION;

short hostvar1 = 39;

char *hostvar2 = "telescope";

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";

在第一个update语句中,department列为smallint数据类型,所以应该把hostvar1定义为short数据类型。这样的话,从C到DB2的hostvar1可以直接映射。在第二个update语句中,prod_descip列为varchar数据类型,所以应该把hostvar2定义为字符数组。这样的话,从C到DB2的hostvar2可以从字符数组映射为varchar数据类型。

下表列出了C的数据类型和DB2的数据类型的一些转换关系:

DB2数据类型C数据类型

Smallintshort

IntegerLong

Decimal(p,s)无

DoubleDouble

DateChar[11]

TimeChar[9]

TimestampChar[27]

Char(X)Char[X+1]

Varchar(X)Char[X+1]

Graphic(X)Wchar_t[X+1]

Vargraphic(X)Wchar_t[X+1]

因为C没有date或time数据类型,所以DB2的date或time列将被转换为字符。缺省情况下,使用以下转换格式:mm dd yyyy hh:mm:ss[am | pm]。你也可以使用字符数据格式将C的字符数据存放到DB2的date列上。对于DECIMAL数据类型,在C语言中也没有对应的数据类型。但可以使用char数据类型实现。

3)、宿主变量和NULL

大多数程序设计语言(如C)都不支持NULL。所以对NULL的处理,一定要在SQL中完成。我们可以使用主机指示符变量来解决这个问题。在嵌入式SQL语句中,宿主变量和指示符变量共同规定一个单独的SQL类型值。指示变量和前面宿主变量之间用一个空格相分隔。如:

EXEC SQL SELECT price INTO :price :price_nullflag FROM titles

WHERE au_id = "mc3026"

其中,price是宿主变量,price_nullflag是指示符变量。指示符变量的值为:

l-1。表示宿主变量应该假设为NULL。(注意:宿主变量的实际值是一个无关值,不予考虑)。

l=0。表示宿主变量不是NULL。

l>0。表示宿主变量不是NULL。而且宿主变量对返回值作了截断,指示变量存放了截断数据的长度。

所以,上面这个例子的含义是:如果不存在mc3026写的书,那么price_nullflag为-1,表示price为NULL;如果存在,则price为实际的价格。

指示变量也是一种宿主变量,也需要在程序中定义,它对应数据库系统中的数据类型为SMALLINT。为了便于识别宿主变量,当嵌入式SQL语句中出现宿主变量时,必须在变量名称前标上冒号(:)。冒号的作用是,告诉预编译器,这是个宿主变量而不是表名或列名。

3.2.2单行查询

单行查询是通过SELECT INTO语句完成。当这条语句执行时,查询的结果送入INTO所标志的变量中。如果SQLCODE是100,或者SQLSTATE是02000,则说明没有查询到结果或返回结果为NULL,这时,宿主变量不改变,否则,宿主变量中将包含查询的结果。如:

………….

EXEC SQL SELECT FIRSTNME INTO :firstname

FROM employee

WHERE LASTNAME = 'JOHNSON';

…………. 3.2.3多行查询

对于多行结果,必须使用游标来完成。游标是一个与SELECT语句相关联的符号名,它使用户可逐行访问由DB2返回的结果集。下面这个例子演示了游标的使用方法。这个例子的作用是,逐行打印出每个经理的名字和部门。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "util.h"

EXEC SQL INCLUDE SQLCA;

#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1;

int main(int argc, char *argv[]) {

EXEC SQL BEGIN DECLARE SECTION;

char pname[10];

short dept;

char userid[9];

char passwd[19];

EXEC SQL END DECLARE SECTION;

printf( "Sample C program: CURSOR \n" );

if (argc == 1) {

EXEC SQL CONNECT TO sample;

CHECKERR ("CONNECT TO SAMPLE");

}

else if (argc == 3) {

strcpy (userid, argv[1]);

strcpy (passwd, argv[2]);

EXEC SQL CONNECT TO sample USER :userid USING :passwd;

CHECKERR ("CONNECT TO SAMPLE");

}

else {

printf ("\nUSAGE: cursor [userid passwd]\n\n");

return 1;

} /* endif */

EXEC SQL DECLARE c1 CURSOR FOR (1)

SELECT name, dept FROM staff WHERE job='Mgr'

FOR UPDATE OF job;

EXEC SQL OPEN c1; (2)

CHECKERR ("OPEN CURSOR");

do {

EXEC SQL FETCH c1 INTO :pname, :dept; (3)

if (SQLCODE != 0) break;

printf( "%-10.10s in dept. %2d will be demoted to Clerk\n",

pname, dept );

} while ( 1 );

EXEC SQL CLOSE c1; (4)

CHECKERR ("CLOSE CURSOR");

EXEC SQL ROLLBACK;

CHECKERR ("ROLLBACK");

printf( "\nOn second thought -- changes rolled back.\n" );

EXEC SQL CONNECT RESET;

CHECKERR ("CONNECT RESET");

return 0;

}

/* end of program : CURSOR.SQC */

在上面这个程序中,

(1)定义了一个游标,并指明游标的名字为C1,同时给出了相对于游标的查询语句和游标类型(UPDATE)。

(2)打开游标。系统执行查询语句,建立结果表,将游标指针指向第一条记录之前。

(3)FETCH语句将指针的下一条记录取出,将记录中的数据存放在相应的宿主变量中。同时指针下移。

(4)用CLOSE关闭游标。 3.2.4插入、删除和修改操作

DB2中的插入、删除和修改操作同SQL语句中INSERT、DELETE和UPDATE语句类似。只需在相应的SQL语句前加上EXEC SQL即可。请看下面这个例子:

例、将staff表中所有工作为“Mgr”的职工的工作改变为“clerk”,并将staff表中所有工作为“sale”的职工信息删除。最后插入一新行。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <sqlenv.h>

#include "util.h"

EXEC SQL INCLUDE SQLCA; (1)

#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1;

int main(int argc, char *argv[]) {

EXEC SQL BEGIN DECLARE SECTION; (2)

char statement[256];

char userid[9];

char passwd[19];

char jobUpdate[6];

EXEC SQL END DECLARE SECTION;

printf( "\nSample C program: UPDAT \n");

if (argc == 1) {

EXEC SQL CONNECT TO sample;

CHECKERR ("CONNECT TO SAMPLE");

}

else if (argc == 3) {

strcpy (userid, argv[1]);

strcpy (passwd, argv[2]);

EXEC SQL CONNECT TO sample USER :userid USING :passwd; (3)

CHECKERR ("CONNECT TO SAMPLE");

}

else {

printf ("\nUSAGE: updat [userid passwd]\n\n");

return 1;

} /* endif */

strcpy (jobUpdate, "Clerk");

EXEC SQL UPDATE staff SET job = :jobUpdate WHERE job = 'Mgr'; (4)

CHECKERR ("UPDATE STAFF");

printf ("All 'Mgr' have been demoted to 'Clerk'!\n" );

strcpy (jobUpdate, "Sales");

EXEC SQL DELETE FROM staff WHERE job = :jobUpdate; (5)

CHECKERR ("DELETE FROM STAFF");

printf ("All 'Sales' people have been deleted!\n");

EXEC SQL INSERT INTO staff

VALUES (999, 'Testing', 99, :jobUpdate, 0, 0, 0); (6)

CHECKERR ("INSERT INTO STAFF");

printf ("New data has been inserted\n");

EXEC SQL ROLLBACK; (7)

CHECKERR ("ROLLBACK");

printf( "On second thought -- changes rolled back.\n" );

EXEC SQL CONNECT RESET;

CHECKERR ("CONNECT RESET");

return 0;

}

/* end of program : UPDAT.SQC */

上述语句:

(1)包含SQLCA结构。该结构用于将SQL语句执行的结果信息返回给应用程序。

(2)宿主变量定义。

(3)连接到DB2的SAMPLE数据库。

(4)UPDATE语句将staff表中所有工作为“Mgr”的职工的工作改变为“clerk”。

(5)DELETE语句将staff表中所有工作为“sale”的职工信息删除。

(6)INSERT语句插入一新行。 指定位置的UPDATE语句和DELETE语句 游标操作除了可以将多行的查询结果返回给应用程序,它还可以与UPDATE语句和DELETE相结合,根据游标当前的位置,对指针所指的这个行数据执行UPDATE操作和DELETE操作。它的语法为:

UPDATE…. WHERE CURRENT OF cursor_name

DELETE [FROM] {table_name | view_name} WHERE CURRENT OF cursor_name

请看下面这个例子。这个例子的作用是:将部门大于40的员工的工作改变为“clerk”,部门小于等于40的员工信息删除。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

[1] [2] [3] [4] [5] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有