EXEC SQL DELETE FROM closeoutsale
WHERE temp_price = :saleprice :saleprice_null; 你可以使用下面语句来完成上述功能: if (saleprice_null == -1) {
EXEC SQL DELETE FROM closeoutsale WHERE temp_price IS null; } else {
EXEC SQL DELETE FROM closeoutsale WHERE temp_price = :saleprice;
}
为了便于识别主变量,当嵌入式SQL语句中出现主变量时,必须在变量名称前标上冒号(:)。冒号的作用是,告诉预编译器,这是个主变量而不是表名或列名。
2 数据的查询和修改
可以使用SELECT INTO语句查询数据,并将数据存放在主变量中。如上例中的:
EXEC SQL SELECT au_fname INTO :first_name
from authors where au_lname = :last_name;
使用DELETE语句删除数据。其语法类似于Transact-SQL中的DELETE语法。如: EXEC SQL DELETE FROM authors WHERE au_lname = 'White'
使用UPDATE语句可以更新数据。其语法就是Transact-SQL中的UPDATE语法。如: ` EXEC SQL UPDATE authors SET au_fname = 'Fred' WHERE au_lname = 'White' 使用INSERT语句可以插入新数据。其语法就是Transact-SQL中的INSERT语法。如:
EXEC SQL INSERT INTO homesales (seller_name, sale_price) real_estate('Jane Doe', 180000.00); 多行数据的查询和修改请参见下一节——游标。
3 游标的使用
用嵌入式SQL语句查询数据分成两类情况。一类是单行结果,一类是多行结果。对于单行结果,可以使用SELECT INTO语句;对于多行结果,你必须使用cursor(游标)来完成。游标(Cursor)是一个与SELECT语句相关联的符号名,它使用户可逐行访问由SQL Server返回的结果集。先请看下面这个例子,这个例子的作用是逐行打印staff表的id、name、dept、 job、years、salary和comm的值。
EXEC SQL DECLARE C1 CURSOR FOR
SELECT id, name, dept, job, years, salary, comm FROM staff;
EXEC SQL OPEN c1;
while (SQLCODE == 0) {
/* SQLCODE will be zero if data is successfully fetched */
EXEC SQL FETCH c1 INTO :id, :name, :dept, :job, :years, :salary, :comm; if (SQLCODE == 0)
printf(\ id, name, dept, job, years, salary, comm); }
EXEC SQL CLOSE c1;
从上例看出,你首先应该定义游标结果集,即定义该游标的SELECT语句返回的行的集合。然后,使用FETCH语句逐行处理。
值得注意的是,嵌入SQL语句中的游标定义选项同Transact-SQL 中的游标定义选项有些不同。必须遵循嵌入SQL语句中的游标定义选项。 1)、声明游标:
如:EXEC SQL DECLARE C1 CURSOR FOR
SELECT id, name, dept, job, years, salary, comm FROM staff; 2)、打开游标
如:EXEC SQL OPEN c1;
完整语法为:OPEN 游标名 [USING 主变量名 | DESCRIPTOR 描述名]。关于动态OPEN游标的描述见第四节。 3)、取一行值
如:EXEC SQL FETCH c1 INTO :id, :name, :dept, :job, :years, :salary, :comm; 关于动态FETCH语句见第四节。 4)、关闭游标
如:EXEC SQL CLOSE c1;
关闭游标的同时,会释放由游标添加的锁和放弃未处理的数据。在关闭游标前,该游标必须已经声明和打开。另外,程序终止时,系统会自动关闭所有打开的游标。
也可以使用UPDATE语句和DELETE语句来更新或删除由游标选择的当前行。使用DELETE语句删除当前游标所在的行数据的具体语法如下:
DELETE [FROM] {table_name | view_name} WHERE CURRENT OF cursor_name 其中, ? ? ?
table_name是表名,该表必须是DECLARE CURSOR中SELECT语句中的表。
view_name是视图名,该视图必须是DECLARE CURSOR中SELECT语句中的视图。 cursor_name是游标名。
请看下面这个例子,逐行显示firstname和lastname,询问用户是否删除该信息,如果回答“是”,那么删除当前行的数据。 EXEC SQL DECLARE c1 CURSOR FOR
SELECT au_fname, au_lname FROM authors FOR BROWSE;
EXEC SQL OPEN c1;
while (SQLCODE == 0)
{
EXEC SQL FETCH c1 INTO :fname, :lname; if (SQLCODE == 0) {
printf(\ printf(\ scanf(\ if (reply == 'y') {
EXEC SQL DELETE FROM authors WHERE CURRENT OF c1; printf(\ } } }
4 SQLCA
DBMS是通过SQLCA(SQL通信区)向应用程序报告运行错误信息(见3.4中的例子)。SQLCA是一个含有错误变量和状态指示符的数据结构。通过检查SQLCA,应用程序能够检查出嵌入式SQL语句是否成功,并根据成功与否决定是否继续往下执行。预编译器自动在嵌入SQL语句中包含SQLCA数据结构(见第二节的例子demo.c)。在程序中可以使用EXEC SQL INCLUDE SQLCA,目的是告诉SQL预编译程序在该程序中包含一个SQL通信区。也可以不写,系统会自动加上SQLCA结构。
1)、SQLCODE
SQLCA结构中最重要的部分是SQLCODE变量。在执行每条嵌入式SQL语句时,DBMS在SQLCA中设置变量SQLCODE值,以指明语句的完成状态: 1、0 该语句成功执行,无任何错误或报警。 2、<0 出现了严重错误。 3、>0 出现了报警信息。
2)、SQLSTATE
SQLSTATE变量也是SQLCA结构中的成员。它同SQLCODE一样,都是返回错误信息。SQLSTATE是在SQLCODE之后产生的。这是因为,在制定SQL2标准之前,各个数据库厂商都采用SQLCODE变量来报告嵌入式SQL语句中的错误状态。但是,各个厂商没有采用标准的错误描述信息和错误值来报告相同的错误状态。所以,标准化组织增加了SQLSTATE变量,规定了通过SQLSTATE变量报告错误状态和各个错误代码。因此,目前使用SQLCODE的程序仍然有效,但也可用标准的SQLSTATE错误代码编写新程序。
5 DB2的嵌入SQL程序处理过程
嵌入SQL程序处理,由一个源程序创建为一个可执行文件的过程。 首先对源文件做预编译(precompiler),生成两个部分文件:一部分是纯的C程序源文
件,它们和其他的C程序源文件一起,经过编译和连接生成可执行的程序(executable program),而另一部分是bind文件或package文件。Bind文件经过binder操作以后,也生成为package文件。所谓package,实际上是SQL语句的访问计划。所以,预编译器将源程序中的SQL语句提出来,生成他们的访问计划,并将访问计划存放在数据库管理器中。当执行程序并遇到访问数据库的命令时,它将到数据库管理器中寻找属于它的访问计划,然后按照访问计划中所设计的方法对数据库进行访问。 第一步、预编译
源程序生成以后,在源程序中嵌入了许多SQL语句,而SQL语句是宿主语言编译器所不认识的,所以在用宿主语言编译器进行编译、连接之前必须将SQL语句分离出来,这就是预编译所做的工作。DB2中预编译操作是通过PREP命令执行的,PREP命令首先将源程序中的所有有关SQL语句全部注释起来,对它进行分析和语法检查。如果源程序中的SQL语句全部书写正确,则将这些SQL语句转换成C语言可以识别的一系列的API函数。这些函数可以在函数执行时访问数据库,然后将源文件中所有用于生成数据库管理器的PACKAGE的数据提出组合成一个BIND文件。也可以直接生成一个PACKAGE,但这相当于在预编译后又执行了一次BIND操作。在预编译时,对整个源程序文件中的所有变量做统一处理而不根据变量的生命期来处理,所以宿主变量在整个程序中是唯一的。下面讲解预编译的步骤: 1)、连接到一个数据库,该操作是为BIND做准备。操作如下: db2 connect to cicstest 2)、执行预编译命令,假设源文件为adhoc.sqc,则:
db2 prep adhoc.sqc bindfile
下面我们对预编译的几种输出文件进行讨论。
预编译后生成的C语言源文件:该文件中原有的SQL语句,已经全部加上注释并转换成了C语言可以识别的API调用。
BIND文件:如果在预编译时使用BINDFILE选项,则生成BIND文件,BIND文件的后缀为.bnd,BIND文件可以在将来使用BIND命令来生成PACKAGE。
db2 bind adhoc.bnd
如果在预编译时,只生成BIND文件,那么即使在预编译时,不能访问某些数据库对象,系统也只是报警,而不会报错。如果使用PACKAGE选项,则生成PACKAGE。如果有MESSAGE选项,则生成信息文件,它包含了所有的返回信息,如:警报、错误等。它便于程序员对源程序做进一步的修改。 第二步、编译和连接
在预编译后,程序中只有C语言语句,它们都可以为C语言的编译器所识别。所以,可以按照一般的方法进行编译和连接,但在将SQL语句转换以后,在C语言程序中,又引入了许多一般的C语言系统所没有的INCLUDE文件和函数库,这些均在DB2的SDK中。所以,要生成可执行的程序,就必须安装DB2的SDK,并且做以下设置:
set INCLUDE=$(DB2PATH)\\include;%include% set LIB=$(DB2PATH)\\lib;%LIB% 下面是编译和连接:
cl -o adhoc.exe adhoc.c
生成的可执行文件必须与数据库管理器中的PACKAGE相结合,才能执行。
BIND
PACKAGE是DB2为SQL语句制定的访问计划。通过precompile之后,源程序中的SQL语句部分就被分离出来。PACKAGE就是根据具体的SQL语句和数据库中的信息生成的针