第三章 静态SQL编程方法
更新时间:2023-10-22 12:19:01 阅读量: 综合文库 文档下载
- 第三章第五幕任务流程推荐度:
- 相关推荐
第三章 静态SQL应用编程
静态SQL语句,是指嵌入在宿主语言中的SQL语句在预编译时完全知道。这是相对于动态SQL而言的,动态SQL语句的语法在运行时才知道。注意:解释语言中不支持静态SQL语句,例如REXX只支持动态SQL语句。
一条SQL语句的结构在预编译时完全清楚,才被认为是静态的。例如,语句中涉及到的表(TABLES)和列的名字,在预编译时,必须完全知道,只能在运行时指定的是语句中引用的宿主变量的值。然而,宿主变量的信息,如数据类型,也必须在预编译时确定。
当静态SQL语句被准备时,SQL语句的可执行形式被创建,存储在数据库中的程序包里。SQL语句的可执行形式可以在预编译时创建或者在捆绑时创建。不论哪种情况,SQL语句的准备过程都发生在运行之前。捆绑应用程序的人需要有一定的权限,数据库管理器中的优化器还会根据数据库的统计信息和配置参数对SQL语句进行优化。对静态SQL语句来说,应用程序运行时,不会被优化。
3.1 静态SQL程序的结构和特点
3.1.1 例程
下面先来看一个静态SQL程序的C语言例子。这个例程演示了静态SQL语句的使用,它将表中LASTNAME列等于‘JOHNSON’的记录的FIRSTNME列的值输出,否则打印错误信息。
/****************************************************************************** **
** Source File Name = static.sqc 1.4 **
** Licensed Materials - Property of IBM **
*******************************************************************************/ #include
#ifdef DB268K
/* Need to include ASLM for 68K applications */ #include
EXEC SQL INCLUDE SQLCA; /* :rk.1:erk. */
#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1; int main(int argc, char *argv[]) {
EXEC SQL BEGIN DECLARE SECTION; /* :rk.2:erk. */ char firstname[13]; char userid[9]; char passwd[19];
EXEC SQL END DECLARE SECTION;
#ifdef DB268K
/* Before making any API calls for 68K environment, need to initial the Library Manager */ #endif
printf( \\\n\ ); if (argc == 1) {
EXEC SQL CONNECT TO sample; }
else if (argc == 3) { strcpy (userid, argv[1]); strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd; /* :rk.3:erk. */ } else {
printf (\\\nUSAGE: static [userid passwd]\\n\\n\); return 1; } /* endif */
EXEC SQL SELECT FIRSTNME INTO :firstname /* :rk.4:erk. */ FROM employee
WHERE LASTNAME = 'JOHNSON'; CHECKERR (\); /* :rk.5:erk. */
printf( \\\n\, firstname );
EXEC SQL CONNECT RESET; /* :rk.6:erk. */ CHECKERR (\); return 0; }
/* end of program : static.sqc */
CHECKERR (\); CHECKERR (\); InitLibraryManager(0,kCurrentZone,kNormalMemory); atexit(CleanupLibraryManager);
这个例程中实现了一个选择至多一行(即单行)的查询,这样的查询可以通过一条
SELECT INTO语句来执行。SELECT INTO 语句从数据库中的表选择一行数据,然后将这行数据的值赋予语句中指定的宿主变量(下节将要讨论宿主变量)。例如,下面的语句将姓为‘HAAS’的雇员的工资赋予宿主变量empsal: SELECT SALARY INTO :empsal
FROM EMPLOYEE
WHERE LASTNAME='HAAS'
一条SELECT INTO语句必须只能返回一行或者零行。如果结果集有多于一行,就会产生一个错误(SQLCODE –811,SQLSTATE 21000)。如果查询的结果集中有多行,就需要游标(CURSOR)来处理这些行。在节3.2.3中介绍如何使用游标。
静态程序是如何工作的呢?
1.包括结构SQLCA。 INCLUDE SQLCA语句定义和声明了SQLCA结构,SQLCA结构中定义了SQLCODE和SQLSTATE域。数据库管理器在执行完每一条SQL语句或者每一个数据库管理器API调用,都要更新SQLCA结构中的SQLCODE域的诊断信息。
2.声明宿主变量。SQL BEGIN DECLARE SECTION和END DECLARE SECTION 语句界定宿主变量的声明。
有些变量在SQL语句中被引用。宿主变量用来将数据传递给数据库管理或者接收数据库管理器返回的数据。在SQL语句中引用宿主变量时,必须在宿主变量前加前缀冒号(:)。详细信息看下节。
3.连接到数据库。应用程序必须先连接到数据库,才能对数据库进行操作。这个程序连接到SAMPLE数据库,请求以共享方式访问。其他应用程序也可以同时以共享访问方式连接数据库
4.提取数据。SELECT INTO语句基于一个查询提取了一行值。这个例子从EMPLOYEE表中,将LASTNAME列的值为JOHNSON的相应行的FISRTNME列的值提取出来,置于宿主变量 firstname中。
5.处理错误。CHECKERR 宏/函数是一个执行错误检查的外部函数。
3.1.2 创建应用程序
创建应用程序的整个过程如图所示:
3.1.3 静态SQL的特点
静态SQL编程比动态SQL编程简单些. 静态SQL语句嵌入宿主语言源文件中,预编译器将SQL语句转换为宿主语言编译器能够处理的数据库运行时服务API调用。
因为在捆绑应用程序时,做捆绑的人需要有一定的授权,因此最终用户不需要执行程序包里的语句的直接权限。例如,一个应用程序可以只允许某个用户更新一个表的部分数据 ,而不用将更新整个表的权利给予这个用户。这个功能通过限制嵌入的静态SQL语句只能更新表中的某些列或者一定范围内的值,只将程序包的执行权限给予这个用户。
静态SQL语句是持久稳固的,动态SQL语句只是被缓存,直到变为无效、因为空间管理原因被清理或者数据库被关闭。如果需要,当被缓存的语句变为无效时,DB2 SQL编译器隐性地重新编译动态SQL语句。
静态SQL语句的主要优点是静态SQL在数据库关闭后仍然存在,而动态SQL语句在
数据库关闭后就被清除了。另外,静态SQL在运行时不需要DB2 SQL编译器来编译,相反,动态SQL语句需要在运行时编译(例如,使用PREPARE语句)。因为DB2缓存动态SQL语句,这些语句也不总是需要DB2编译。但是,每一次运行程序至少需要编译一次。
静态SQL有性能上的优势。对简单、运行时间短的SQL程序,静态SQL语句 比相同目的的动态SQL语句执行得快。因为静态SQL语句准备执行形式的开销在预编译时间,而不是在运行时。
注意:静态SQL语句的性能决定于应用程序最后一次被捆绑时数据库的统计信息。 然而,如果这些统计信息改变了,那么比较起来,等效的动态SQL语句的性能可能好些。在某个使用静态SQL的应用程序捆绑之后,数据库增加了一个索引,如果这个应用程序不重新捆绑,就不能利用这个索引。还有,如果在静态SQL语句中使用宿主变量,优化器也不能使用表的分布信息来优化SQL语句。
3.2 宿主变量和指示符变量的应用
3.2.1 宿主变量的声明
宿主变量(Host variables) 在主应用程序中由嵌入式SQL语句引用的变量。宿主变量是该应用程序中的程序设计变量,并且是在数据库中的表与应用程序工作区之间传送数据的主要机制。我们称之为“宿主变量”,是为了与通常方法声明的源语言变量区分开来,通常方法声明的变量不能被SQL语句引用。宿主变量在宿主语言程序模块中以一种特殊的方式声明:必须在BEGIN DECLARE SECTION和END DECLARE SECTION程序节内定义。
下图显示在不同编程语言中声明宿主变量的例子。 语言 例子源码 C/C++ EXEC SQL BEGIN DECLARE SECTION; short dept=38, age=26; double salary; char CH; char name1[9], NAME2[9]; /* C comment */ short nul_ind; EXEC SQL END DECLARE SECTION; Java // Note that Java host variable declarations follow // normal Java variable declaration rules, and have // no equivalent of a DECLARE SECTION short dept=38, age=26; double salary; char CH; String name1[9], NAME2[9]; /* Java comment */ short nul_ind; COBOL EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 age PIC S9(4) COMP-5 VALUE 26. 01 DEPT PIC S9(9) COMP-5 VALUE 38. 01 salary PIC S9(6)V9(3) COMP-3. 01 CH PIC X(1). 01 name1 PIC X(8). 01 NAME2 PIC X(8). * COBOL comment
据库尽可能返回更多的数据)。
例子:
定义宿主变量和指示符变量:
EXEC SQL BEGIN DECLARE SECTION; char too_little[5]; short iv1;
EXEC SQL END DECLARE SECTION;
表BANK_ITEMS: ITEM# QTY DESCRIPTION 101 3000 PASSBOOKS 200 100 CHECKBOOKS … … … 执行的SQL语句:
SELECT DESCRIPTION INTO :too_little:iv
FROM BANK_ITEMS WHERE ITEM# = 200 结果:
:too_little中的值为’CHECK’,:iv1中的值为10
3.3 使用游标处理多行结果集
为了使应用程序能够提取多行结果集,SQL使用了一种机制,叫做游标(cursor)。 为了理解游标的概念,我们假设数据库管理器创建了一个结果表(result table),里面包含有执行一条SELECT语句所提取的所有行。通过标识或指向这个表的“当前行”,游标使得结果表中的行对应用程序可用。当一个是拥游标时,应用程序可以顺序从结果表中提取每一行,直到产生一个数据结束条件,这个条件就是NOT FOUND条件,SQLCA中的SQLCODE为+100(SQLSTATE为02000)。执行SELECT语句的结果集,可能有零行、一行或者更多行,决定于有多少行符合搜索的条件。
处理一个游标涉及到以下几个步骤:
1.使用DECLARE CURSOR语句声明一个游标 2.使用OPEN语句执行查询和创建结果表 3.使用FETCH语句每次提取一行结果
4.使用DELETE或UPDATE语句处理行(如果需要) 5.使用CLOSE语句终止(关闭)游标 一个应用程序中,可以使用多个游标,但是每一个游标要有自己的DECLARE CURSOR,OPEN,CLOSE和FETCH语句集。
3.3.1声明和使用游标
DECLARE CURSOR语句定义和命名游标,确定使用SELECT语句要提取的行结果集。 应用程序给游标分配一个名字。这个名字在随后的OPEN、FETCH和CLOSE语句中都要被参考到。查询可以是任何有效的SELECT语句。
下面例子展示了一条DECLARE语句如何与一条静态SELECT语句关联起来:
源码例程 C/C++ EXEC SQL DECLARE C1 CURSOR FOR SELECT PNAME, DEPT FROM STAFF WHERE JOB=:host_var; Java (SQLJ) #sql iterator cursor1(host_var data type); #sql cursor1 = { SELECT PNAME, DEPT FROM STAFF WHERE JOB=:host_var }; COBOL EXEC SQL DECLARE C1 CURSOR FOR SELECT NAME, DEPT FROM STAFF WHERE JOB=:host-var END-EXEC. FORTRAN EXEC SQL DECLARE C1 CURSOR FOR + SELECT NAME, DEPT FROM STAFF + WHERE JOB=:host_var 注解:DECLARE语句的在程序中位置是任意的,但是它必须在第一次使用游标的位置之前。
语言 3.3.2游标与工作单元的考虑
COMMIT或者ROLLBACK操作的动作随游标的不同而不同,依赖于游标的定义。 1.只读游标(Read Only Cursors)
如果一个游标被确定为只读的,并且使用可重复读隔离级(isolation level),那么系统表仍会收集和维护工作单元需要的可重复读锁。因此,即使只读游标,应用程序周期性地发出COMMIT语句还是很重要的。 2.有WITH HOLD选项
如果应用程序通过发出一条COMMIT语句来完成一个工作单元,除了声明时有WITH HOLD选项的游标,所有游标将自动地被数据库管理器关闭。
用WITH HOLD声明的游标维护它访问的跨多个工作单元的资源。用WITH HOLD声明的游标受到的影响依赖于工作单元如何结束。
如果工作单元使用一条COMMIT语句结束,已打开的定义为WITH HOLD的游标将保持打开状态。游标的位置在结果集的下一个逻辑行之前。另外,参考用WITH HOLD定义的已准备好的语句也会被保留。紧跟COMMIT语句后面, 只有与一个某个特定游标相关联的FETCH和CLOSE请求才有效。UPDATE WHERE CURRENT OF和DELETE WHERE CURRENT OF 语句仅仅对在同一个工作单元中提取的行有效。如果程序包在工作单元期间被重新绑定,那么所有保持的游标都会被关闭。
如果工作单元使用一条ROLLBACK语句结束,所有打开的游标被关闭,所有在工作单元中获得的锁被释放,以及所有依赖于这个工作单元的已准备好的语句被删除。
举个例子,假设TEMPL表中有1000条记录。要更新所有雇员的工资,应该每更新100行就要发出一条COMMIT语句。
A. 使用WITH HOLD选项声明游标:
EXEC SQL DECLARE EMPLUPDT CURSOR WITH HOLD FOR
SELECT EMPNO, LASTNAME, PHONENO, JOBCODE, SALARY FROM TEMPL FOR UPDATE OF SALARY
B. 打开游标,每一次从结果表中提取一行数据: EXEC SQL OPEN EMPLUPDT . . .
EXEC SQL FETCH EMPLUPDT
INTO :upd_emp, :upd_lname, :upd_tele, :upd_jobcd, :upd_wage,
C. 当想要更新或者删除一行时,使用带WHERE CURRENT OF选项的UPDATE或者DELETE语句。例如,要更新当前行,程序可以发出下面的语句:
EXEC SQL UPDATE TEMPL SET SALARY = :newsalary WHERE CURRENT OF EMPLUPDT
在一条COMMIT语句发出之后,在更新其它行之前必须发出FETCH语句。
如果应用程序使用了用WITH HOLD声明的游标或者执行了多个工作单元并且有一个用WITH HOLD声明的游标跨工作单元处于打开状态,那么在程序中应该加入代码检测和处理SQLCODE为-501(SQLSTATE为24501)的错误,这个错误由FETCH或者CLOSE语句返回。
如果应用程序的程序包由于其依赖的表被删除而变得无效,程序包会自动被重新绑定。这种情况下,FETCH或CLOSE语句返回SQLCODE –501(SQLSTATE 24501),因为 数据库管理器关闭游标。在此情形下,处理SQLCODE –501(SQLSTATE 24501)的方法决定于是否要从游标提取行数据。
? 如果要从游标提取行,打开游标,然后运行FETCH语句。注意,OPEN语句使得
游标重定位到开始处。原来的位置信息丢失。
? 如果不准备从游标提取行,那么不要对游标发出任何SQL请求。
WITH RELEASE 选项:当应用程序用WITH RELEASE选项关闭一个游标时,DB2试图去释放游标持有的所有读锁(READ locks)。游标只继续持有写锁(WRITE locks)。如果应用程序没有用RELEASE选项关闭游标,那么在工作单元完成时,所有的读锁和写锁都被释放。
3.3.3例程
游标程序
C Example: CURSOR.SQC #include
#ifdef DB268K
/* Need to include ASLM for 68K applications */ #include
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;
#ifdef DB268K
/* Before making any API calls for 68K environment, need to initial the Library Manager */
InitLibraryManager(0,kCurrentZone,kNormalMemory); atexit(CleanupLibraryManager); #endif
printf( \
if (argc == 1) {
EXEC SQL CONNECT TO sample; CHECKERR (\ }
else if (argc == 3) {
strcpy (userid, argv[1]); strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd; CHECKERR (\ } else {
printf (\ 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 (\
do {
EXEC SQL FETCH c1 INTO :pname, :dept; (3) if (SQLCODE != 0) break;
printf( \ pname, dept ); } while ( 1 );
EXEC SQL CLOSE c1; (4)
CHECKERR (\
EXEC SQL ROLLBACK;
CHECKERR (\
printf( \
EXEC SQL CONNECT RESET;
CHECKERR (\ return 0; }
/* end of program : CURSOR.SQC */
Java Example: Cursor.sqlj import java.sql.*; import sqlj.runtime.*; import sqlj.runtime.ref.*;
#sql iterator CursorByName(String name, short dept) ; #sql iterator CursorByPos(String, short ) ;
class Cursor { static { try
{ Class.forName (\ }
catch (Exception e)
{ System.out.println (\ Error loading DB2 Driver...\\n\ System.out.println (e); System.exit(1);
sqlwarn sqlstate CHARACTER ARRAY CHAR(5) evaluation of a column function SQLWARN3 — ‘W’, 列的个数大于宿主变量的个数 SQLWARN4 — ‘W’, UPDATE/DELETE语句不包含’WHERE’子句 SQLWARN5 — 保留 SQLWARN6 — date or timestamp value adjusted to correct an invalid data resulting from arithmetic operation SQLWARN7 — 保留 SQLWARN8 — 字符结果不能被转换,而被子串替换 SQLWARN9 — 在列函数的处理过程中,忽略了有错误的算术表达式 SQLWARNA —在转换SQLCA中的一个字符数据值时发生转换错误 交叉平台错误代码。sqlstate的值对应于sqlcode。某些sqlcodes没有对应的sqlstate,因为对于指定的错误条件没有等价的sqlstate
对于大多数应用程序开发环境,为了创建和维护一个质量合格的软件,适当的错误处理是极其重要的。从应用程序中发出的每条SQL语句可能产生一个成功条件或一个错误条件。应用程序开发人员判定SQL语句结果的主要手段是检查SQL通信区(SQLCA)的内容。SQLCA是由DB2定义的宿主语言的数据结构。它包含着在处理SQL语句期间由DB2装填的许多数据元素。
[注解]:在DB2 REXX环境中自动地提供SQLCA
开发者的应用程序必须在发出任何SQL语句之前声明SQLCA(SQL 通信区)。有以下两种在程序中定义SQLCA的方法:
? 使用EXEC SQL INCLUDE SQLCA。
? 在DB2的头文件中声明一个叫做sqlca的结构。
在表中给出的SQLCA数据结构可以作为在应用程序与DB2之间处理错误的主要手段。关键的是开发者的应用程序要在执行每条SQL语句之后核查SQLCA的内容。不能核查SQLCA的内容可能会引起无法预料的错误发生。对于可能发生的许多错误,通常系统会向用户建议相应的措施(它们可以被编码到用户的应用程序中)。例如,假设开发者试图与数据库服务器相连接并且收到一个错误信息,说尚未启动数据库管理器。应用程序可以发出DB2START命令去启动数据库管理器,然后再次试图与数据库服务器相连接。
3.4.2 WHENEVER语句
由于错误或警告的发生是不可预料的,所以我们无法象普通编程那样用条件或者循环等控制结构来实现错误处理,于是DB2提供了WHENEVER语句.
WHENEVER这一控制结构使预编译器产生的执行代码,使应用程序在遇到错误、警告或"没有行发现"时转到指定的代码段,继续执行相应的处理程序. WHENEVER对同一源程序中所有另一同类WHENEVER前的SQL执行语句均有效.
WHENEVER有三种基本形式:
1. EXEC SQL WHENEVER SQLERROR action 2. EXEC SQL WHENEVER SQLWARNING action 3. EXEC SQL WHENEVER NOT FOUND action
在这些形式中,SQLERROR指的是SQLCODE<0的情况;SQLWARNING指的是SQLWARN0 = ‘w’或者SQLCODE>0;NOT FOUND指的则是SQLCODE=+100的情况.
action可以是以下两种情况之一:
CONTINUE: 表示忽略这个异常,继续应用程序的下一步执行; Go To label: 表示发生异常时,转到label所标识的语句开始.
例子:
…
SQL statement … EXEC SQL
WHENEVER SQLERROR GO TO :A; …
SQL statement
IF SQLCODE <0 ―>A …
SQL statement
IF SQLCODE <0 ―>A … EXEC SQL
WHENEVER SQLWARNING GO TO :W; EXEC SQL
WHENEVER SQLERROR GO TO :B; …
SQL statement
IF SQLCODE < 0 ―>B IF warning ―>w … EXEC SQL
WHENEVER SQLERROR CONTINUE; SQL statement IF warning ―>W …
3.4.3 查询错误
无论何时在任何示例中输入出错时,或者如果执行 SQL 语句期间出错,则数据库 管理程序返回错误信息。错误信息由信息标识符、简要说明以及 SQLSTATE 组 成。
SQLSTATE 是 DB2 系列产品的公共错误码。 SQLSTATE 符合 ISO/ANSI SQL92 标准。
例如,如果 CONNECT 语句中用户名或口令不正确,则数据库管理程序将返回 信息标识符 SQL1403N 和 SQLSTATE 为 08004。该信息如下:
SQL1403N 提供的用户名和/或口令不正确。 SQLSTATE=08004
可以通过输入一个问号(?),然后输入信息标识符或 SQLSTATE 来 获取关于错误信息的更多信息:
? SQL1403N 或
? SQL1403 或
? 08004
注意:错误 SQL1403N 的说明中倒数第二行表明 SQLCODE为-1403。 SQLCODE 为产品特定错误码。 以 N(通知)或 C(严重)结尾的信息标识符表示一个错误,并且具有负 SQLCODE。 以 W(警告)结尾的信息标识符表示一个警告,并且具有正 SQLCODE。
3.5 复合SQL语句
3.5.1 复合SQL的定义
构建在客户/服务器体系结构上的数据库应用程序,每执行一条SQL语句就要与数据库管理器交互一次。为了减少客户与服务器之间的交互信息及次数、提高整体系统的性能,DB2在程序开发方法上提供了一种机制―复合SQL(Compound SQL)语句。
复合 SQL 允许您将几条 SQL 语句分组为单个的可执行块。包含于块中的 SQL 语句(子语句)可以单独执行;但是,通过创建和执行一个语句块,您可以减少数据库管理程序的额外开销。对于远程客户机,复合 SQL 也减少必须通过网络传送的请求的数目。
有两种类型的复合 SQL: ? 基本 (ATOMIC)
当所有子语句都成功完成时,或当一个子语句因出错而结束时,应用程序将从数据库管理程序收到一个响应。如果一个子语句因出错而结束,则将整个块视为因出错而结束,并且将回滚在此块中对数据库所做的任何更改。
? 非基本(NOT ATOMIC) 当所有子语句都完成时,应用程序将从数据库管理程序接收到一个响应。不管其前面的子语句是否成功执行,一个块中的所有子语句都要执行。仅当回滚包含非基本复合 SQL 的工作单元时,才可以回滚此语句组。
3.5.2 复合SQL的例子
我们通过一个例子来说明如何编写复合SQL语句:
EXEC SQL BEGIN COMPOUND ATOMIC STATIC UPDATE SAVINGS SET
BALANCE = BALANCE - :transfer
WHERE ATMCARD = :atmcard;
UPDATE CHECKING SET
BALANCE = BALANCE + :transfer WHERE ATMCARD = :atmcard;
INSERT INTO ATMTRANS (TTSTMP, CODE, AMOUNT) VALUES (CURRENT TIMESTAMP, :code, :transfer); COMMIT; END COMPOUND;
1. 这个例子演示了复合SQL语句的一个简单使用:将钱从银行存款帐号转到支票帐号,并将转帐记录在审计表中;
2. 关键字ATOMIC 指明:在其中的所有SQL语句都成功执行,复合SQL语句才算成功,也就是可以提交(COMMIT);如果其中有一条SQL语句失败,那么复合SQL语句中所有SQL语句对数据库所作的改变都被回滚(Roll Back); 3. 可以用关键字NOT ATOMIC替换ATOMIC。这样会忽略任何子语句的失败,数据库管理器不会回滚复合SQL语句中其他语句所作的改变。SQLCA中的信息指出有多少条语句处理成功和检测到的错误信息;
4. 关键字STATIC表示在复合SQL语句中引用的宿主变量在复合SQL语句被调用时获得的值,不会被复合SQL语句中的任何SQL语句改变。例如: EXEC SQL BEGIN COMPOUND ATOMIC STATIC UPDATE SAVINGS SET
BALANCE = BALANCE - :transfer WHERE ATMCARD = :atmcard;
SELECT ACCOUNT INTO :atmcard WHERE CARDHOLDER = ‘Cartwright’;
UPDATE CHECKING SET BALANCE = BALANCE + :transfer WHERE ATMCARD = :atmcard;
INSERT INTO ATMTRANS (TTSTMP, CODE, AMOUNT) VALUES (CURRENT TIMESTAMP, :code, :transfer);
COMMIT;
END COMPOUND;
在每一条UPDATE和INSERT语句中使用:atmcard在复合SQL运行之前获得的值,而不是对应于‘Cartwright‘的值。
5. 语句:STOP AFTER FIRST host_var STATEMENTS可以加在BEGIN COMPOUND语句中,允许程序指定复合SQL语句执行时,只执行其中的多少条。例如:
EXEC SQL BEGIN COMPOUND NOT ATOMIC STATIC STOP AFTER FIRST :nbr STATEMENTS
INSERT INTO TAB1 VALUES(:col1val1, :col2val1);
INSERT INTO TAB1 VALUES(:col1val2, :col2val2); INSERT INTO TAB1 VALUES(:col1val3, :col2val3); INSERT INTO TAB1 VALUES(:col1val4, :col2val4); INSERT INTO TAB1 VALUES(:col1val5, :col2val5); INSERT INTO TAB1 VALUES(:col1val6, :col2val6); INSERT INTO TAB1 VALUES(:col1val7, :col2val7); INSERT INTO TAB1 VALUES(:col1val8, :col2val8); END COMPOUND;
将宿主变量:nbr的值设置为希望一次插入的行数。 6. 如果复合SQL语句中包含COMMIT语句,必须放在最后一条语句的位置,即在END COMPOUND之前。即使使用STOP AFTER FIRST host_var STATEMENTS选项,并且host_var的值小于复合SQL语句中的SQL语句条数,COMMIT语句也会被执行。注意:当连接类型(CONNECT TYPE)为2时,不允许有COMMIT语句。 7. SQLSTATE和SQLCODE的值是复合SQL语句中的最后执行的语句的信息。
3.5.3复合SQL的限制
使用复合SQL语句的限制:
1. DB2 Connect只支持NOT ATOMIC类型的复合SQL语句 2. 复合SQL语句只能包含静态SQL语句
3. 复合SQL语句只能在嵌入SQL语句程序中使用 4. 下列语句不能包含在复合SQL语句中: CALL CLOSE CONNECT Compound SQL DESCRIBE DISCONNECT
EXECUTE IMMEDIATE FETCH OPEN PREPARE RELEASE ROLLBACK
SET CONNECTION
正在阅读:
第三章 静态SQL编程方法10-22
《欧也妮·葛朗台》读书笔记之人物形象分析11-01
高层建筑PLC控制的恒压供水系统的设计06-05
神奇的书包作文400字06-21
单独夫妇申请领取10-25
成长中的傻事作文500字06-27
RCM继电保护计算管理软件12-23
有一种声音在记忆深处 - 009-20
高中数学论文12-01
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 静态
- 编程
- 第三章
- 方法
- SQL
- 党建创新案例20个
- 昆明理工大学研究生省政府奖学金评选及管理办法(试行)
- 山东大学医学院遗传学专业、细胞生物学专业
- 2013年度全国煤矿安全事故案例汇编
- 2017年电大商法形成性考核册作业1参考答案
- 良乡分输站(扩建)施工组织设计 - 图文
- 新生规范教育简答题答案
- SARS传播的数学模型 - 全国数模竞赛优秀论文
- 客车违章查询系统
- 2016年 尔雅超星 社会心理学 期末考试答案
- 程序改错
- 00814自考中国古代文论选读必考试题
- 《网络安全与管理》第04章在线测试
- SWS造船涂装作业指导
- 小学科学 林良润 多管齐下,有效开展小学科学学科教学
- 新语文版九年级语文上册第22课《《论语》十则》教案
- 缅甸某水电站工程涉外突发事件应急预案
- 银行管理人员考试判断题
- 高英(现代大学英语)精读5 paraphrase 原文+译文
- 新视野大学英语视听说教程第二版第四册unit8的test的答案