第三章静态SQL编程方法_第1页
第三章静态SQL编程方法_第2页
第三章静态SQL编程方法_第3页
第三章静态SQL编程方法_第4页
第三章静态SQL编程方法_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第三章 静态SQL应用编程静态SQL语句,是指嵌入在宿主语言中的SQL语句在预编译时完全知道。这是相对于动态SQL而言的,动态SQL语句的语法在运行时才知道。注意:解释语言中不支持静态SQL语句,例如REXX只支持动态SQL语句。一条SQL语句的结构在预编译时完全清楚,才被认为是静态的。例如,语句中涉及到的表(TABLES)和列的名字,在预编译时,必须完全知道,只能在运行时指定的是语句中引用的宿主变量的值。然而,宿主变量的信息,如数据类型,也必须在预编译时确定。当静态SQL语句被准备时,SQL语句的可执行形式被创建,存储在数据库中的程序包里。SQL语句的可执行形式可以在预编译时创建或者在捆绑时

2、创建。不论哪种情况,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*/#

3、include #include #include #include util.h#ifdef DB268K/* Need to include ASLM for 68K applications */#include #endifEXEC 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

4、:erk. */ char firstname13; char userid9; char passwd19; 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( Sample C program:

5、 STATICn ); if (argc = 1) EXEC SQL CONNECT TO sample; CHECKERR (CONNECT TO SAMPLE); else if (argc = 3) strcpy (userid, argv1); strcpy (passwd, argv2); EXEC SQL CONNECT TO sample USER :userid USING :passwd; /* :rk.3:erk. */ CHECKERR (CONNECT TO SAMPLE); else printf (nUSAGE: static userid passwdnn); r

6、eturn 1; /* endif */ EXEC SQL SELECT FIRSTNME INTO :firstname /* :rk.4:erk. */ FROM employee WHERE LASTNAME = JOHNSON; CHECKERR (SELECT statement); /* :rk.5:erk. */ printf( First name = %sn, firstname ); EXEC SQL CONNECT RESET; /* :rk.6:erk. */ CHECKERR (CONNECT RESET); return 0;/* end of program :

7、static.sqc */这个例程中实现了一个选择至多一行(即单行)的查询,这样的查询可以通过一条SELECT INTO语句来执行。SELECT INTO 语句从数据库中的表选择一行数据,然后将这行数据的值赋予语句中指定的宿主变量(下节将要讨论宿主变量)。例如,下面的语句将姓为HAAS的雇员的工资赋予宿主变量empsal: SELECT SALARY INTO :empsal FROM EMPLOYEE WHERE LASTNAME=HAAS 一条SELECT INTO语句必须只能返回一行或者零行。如果结果集有多于一行,就会产生一个错误(SQLCODE 811,SQLSTATE 21000)。

8、如果查询的结果集中有多行,就需要游标(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语句中被引用。宿主变量用来将数据传递给数据库管理或者接收数

9、据库管理器返回的数据。在SQL语句中引用宿主变量时,必须在宿主变量前加前缀冒号(:)。详细信息看下节。3.连接到数据库。应用程序必须先连接到数据库,才能对数据库进行操作。这个程序连接到SAMPLE数据库,请求以共享方式访问。其他应用程序也可以同时以共享访问方式连接数据库 4.提取数据。SELECT INTO语句基于一个查询提取了一行值。这个例子从EMPLOYEE表中,将LASTNAME列的值为JOHNSON的相应行的FISRTNME列的值提取出来,置于宿主变量 firstname中。 5.处理错误。CHECKERR 宏/函数是一个执行错误检查的外部函数。3.1.2 创建应用程序创建应用程序的整

10、个过程如图所示:3.1.3 静态SQL的特点静态SQL编程比动态SQL编程简单些. 静态SQL语句嵌入宿主语言源文件中,预编译器将SQL语句转换为宿主语言编译器能够处理的数据库运行时服务API调用。因为在捆绑应用程序时,做捆绑的人需要有一定的授权,因此最终用户不需要执行程序包里的语句的直接权限。例如,一个应用程序可以只允许某个用户更新一个表的部分数据 ,而不用将更新整个表的权利给予这个用户。这个功能通过限制嵌入的静态SQL语句只能更新表中的某些列或者一定范围内的值,只将程序包的执行权限给予这个用户。静态SQL语句是持久稳固的,动态SQL语句只是被缓存,直到变为无效、因为空间管理原因被清理或者数

11、据库被关闭。如果需要,当被缓存的语句变为无效时,DB2 SQL编译器隐性地重新编译动态SQL语句。静态SQL语句的主要优点是静态SQL在数据库关闭后仍然存在,而动态SQL语句在数据库关闭后就被清除了。另外,静态SQL在运行时不需要DB2 SQL编译器来编译,相反,动态SQL语句需要在运行时编译(例如,使用PREPARE语句)。因为DB2缓存动态SQL语句,这些语句也不总是需要DB2编译。但是,每一次运行程序至少需要编译一次。静态SQL有性能上的优势。对简单、运行时间短的SQL程序,静态SQL语句 比相同目的的动态SQL语句执行得快。因为静态SQL语句准备执行形式的开销在预编译时间,而不是在运行

12、时。注意:静态SQL语句的性能决定于应用程序最后一次被捆绑时数据库的统计信息。 然而,如果这些统计信息改变了,那么比较起来,等效的动态SQL语句的性能可能好些。在某个使用静态SQL的应用程序捆绑之后,数据库增加了一个索引,如果这个应用程序不重新捆绑,就不能利用这个索引。还有,如果在静态SQL语句中使用宿主变量,优化器也不能使用表的分布信息来优化SQL语句。3.2 宿主变量和指示符变量的应用3.2.1 宿主变量的声明宿主变量(Host variables) 在主应用程序中由嵌入式SQL语句引用的变量。宿主变量是该应用程序中的程序设计变量,并且是在数据库中的表与应用程序工作区之间传送数据的主要机制

13、。我们称之为“宿主变量”,是为了与通常方法声明的源语言变量区分开来,通常方法声明的变量不能被SQL语句引用。宿主变量在宿主语言程序模块中以一种特殊的方式声明:必须在BEGIN DECLARE SECTION和END DECLARE SECTION程序节内定义。下图显示在不同编程语言中声明宿主变量的例子。语言例子源码C/C+EXEC SQL BEGIN DECLARE SECTION; short dept=38, age=26; double salary; char CH; char name19, NAME29; /* C comment */ short nul_ind; EXEC SQ

14、L END DECLARE SECTION;Java/ Note that Java host variable declarations follow/ normal Java variable declaration rules, and have/ no equivalent of a DECLARE SECTIONshort dept=38, age=26; double salary; char CH; String name19, NAME29; /* Java comment */ short nul_ind;COBOLEXEC SQL BEGIN DECLARE SECTION

15、 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 01 nul-ind PIC S9(4) COMP-5. EXEC SQL END DECLARE SECTION END-EXEC.下面是引用宿主变量的例子语言例子源码C/C+EXEC SQL FETCH C1 INTO :cm;

16、printf( Commission = %fn, cm );Java#SQL FETCH :c1 INTO :cm ; System.out.println(Commission = + cm);COBOLEXEC SQL FETCH C1 INTO :cm END-EXEC DISPLAY Commission = cm在SQL语句中引用宿主变量时,必须加前缀冒号(:)。冒号的作用是将宿主变量与SQL语法中的元素区分开。如果没有冒号,宿主变量会误解释为SQL语句的一部分。例如: WORKDEPT = dept将被解释为WORKDEPT列的值等于dept列的值。在宿主语言语句中,则不需要加前

17、缀,正常引用即可。从下图中可看出如何使用宿主变量:DB2名字空间(如表名、列名等等)不能用宿主变量指定。例如不能写如下SQL语句: SELECT :col1 FROM :tabname但是,这种类型的功能可以通过采用动态SQL实现。总的来说,宿主变量有以下特点:l 可选的,在语句运行之前用来赋值l 宿主语言标号在SQL语句中,前面加冒号l 宿主变量与列的数据类型必须匹配l 对于宿主变量有以下要求:a. 所有被嵌入SQL引用的宿主变量必须在BEGIN和END DECLARE语句界定的代码区里声明;b. 宿主变量的数据类型必须与列的数据类型匹配,而且尽量避免数据转换和截取;c. 宿主变量名不能以E

18、XEC、SQL、sql开头;d. 宿主变量应该被看作是模块程序的全局变量,而不是定义所在函数的局部变量;e. 在界定区外定义的变量不能与界定区内定义的变量同名;f. 在一个源文件中,可以有多个界定区;g. BEGIN DECLARE SECTION语句可以在程序中宿主语言规则允许变量声明的任何位置出现,宿主变量定义区以END DECLARE SECTION语句结束;h. BEGIN DECLARE SECTION和END DECLARE SECTION语句必须成对出现,并且不能嵌套;i. 宿主变量声明可以使用SQL INCLUDE语句指定。另外,一个宿主变量声明区不能含有除宿主变量声明以外的语

19、句。3.2.2 宿主变量的使用下面我们通过几个例子来说明宿主变量的用法:1 在INSERT语句中的使用l SQL语句 INSERT INTO TEMPL (EMPNO, LASTNAME) VALUES (, JONES)l 嵌入程序的SQL语句EXEC SQL INSERT INTO TEMPL (EMPNO, LASTNAME) VALUES (:empno, :name);第一条SQL语句可以在CLP中发出,它也可以嵌入程序中,但是它每一次只能插入一行值,如果要插入不同的值就要重新输入,程序也要修改。第二条SQL语句只能嵌入程序中,每一次执行需要用户通过其它代码指定新值给宿主变量empn

20、o和name,宿主变量的作用是将用户指定的值传递给VALUES子句。可以实现输入多行值(循环或多次运行程序)。2 在SET和WHERE子句中的使用l SQL语句 UPDATE TEMPL SET SALARY = SALARY *1.05 WHERE JOBCODE = 54l 嵌入程序的SQL语句EXEC SQL UPDATE TEMPL SET SALARY = SALARY * :percent WHERE JOBCODE = :code; 3 用宿主变量提取值。在程序中执行一个SELECT语句时,必须提供一个存储区域来接收返回的数据,而且对于被选择(selected)的每一列,都要定义

21、一个宿主变量。语法为:SELECT INTO :hostvaribale 。例子:EXEC SQL SELECT LASTNAME, WORKDEPT INTO :name, :deptno FROM TEMPL WHERE EMPNO = :empid;例子中定义了三个宿主变量,从表TEMPL中选择符合条件EMPNO=:empid的两列:LASTNAME和WORKDEPT,结果存放到宿主变量name和deptno中。此形式的用法要保证只能返回单行数据,如果返回多行数据库,则不能使用这种方法。后面会介绍如果使用游标(cursor)处理多行的返回结果集。从上面的例子可将宿主变量分为两类:l 输入

22、宿主变量输入宿主变量规定需要在语句执行期间从应用程序传递给数据库管理器的值。例如,在下面的SQL语句中将使用一个输入宿主变量: SELECT name FROM candidate WHERE name = l 输出宿主变量输出宿主变量规定需要在语句执行期间从数据库管理器传递给应用程序的值。例如,在下面的SQL语句中将使用一个输出宿主变量:SELECT INTO FROM candidateWHERE name = HUTCHISON 3.2.3 指示符变量的声明在实际中,有些对象的值未知,我们用空值表示。当我们选择数据时,如果是空值,宿主变量的内容将不会被改变,是随机的。DB2数据库管理器提

23、供了一个机制去通知用户返回数据是空值,这个机制就是指示符变量。指示符(indicator)变量是一种特殊的宿主变量类型,它用来表示列的空值或非空值。当这些宿主变量作为输入进入数据库中时,应当在执行SQL语句之前由应用程序对它们设置值。当这些宿主变量作为数据库的输出使用时,这些指示符由应用程序定义,但由DB2更新和将它们返回。然后,在结果被返回时,应用程序应当检查这些指示符变量的值。 看下面一条SQL语句: SELECT COLA INTO :a:aind其中a是宿主变量,aind是指示符变量。如果COLA列的值不为空,DB2将aind的值设置为非负(通常为0);如果COLA列的值为空,DB2将

24、aind的值设置为负数(通常为-1);如果DB2试图提示一个空值的存在,但是程序没有提供指示符,将会产生错误,SQLCODE等于-305。指示符变量的定义:指示符变量的定义与宿主变量的定义方法相同,都需要在BEGIN DECLARE SECTION和END DECLARE SECTION之间定义,并且数据类型与SQL数据类型SMALLINT对应,在C语言中为SHORT类型。例子: CREATE TABLE TEMPL ( EMPNO CHAR(6) NOT NULL, LASTNAME VARCHAR(2) NOT NULL, JOBCODE CHAR(2), WORKDEPT CHAR(3)

25、, NOT NULL, PHONENO CHAR(10)EXEC SQL SELECT JOBCODE, WORKDEPT, PHONENO INTO :jc:jci, :dpt, :pho:phoi FROM TEMPL WHERE EMPNO = :id;EMPNO(6)LASTNAME(20)JOBCODE0-99WORKDEPT(3)PHONENO(10)JOHNSONSCOTTMILLIGAN54?C01C01C01 ?3.2.4 指示符变量的使用指示符逻辑例子1: EXEC SQL SELECT PHONENO, SEX INTO :phoneno:phoneind, :sex F

26、ROM TEMPL WHERE EMPNO = :eno; if (phoneind 0) null_phone(); else good_phone(); 在这个例子里,DB2维护指示符变量,应用程序在SQL语句执行后,询问指示符变量的值,调用相应的处理函数指示符逻辑例子2: if (some condition) phoneind = -1; else phoneind = 0; EXEC SQL UPDATE TEMPL SET NEWPHONE = :newphoneno :phoneind WHERE EMPNO = :eno;在这个例子里,应用程序维护指示符变量。应用程序根据条件设

27、置指示符变量phoneind的值。如果DB2发现指示符的值为负数,那么给定行集合中的列被设置为空值,宿主变量的值被忽略;如果指示符的值为正数或者为零,宿主变量中的值被使用。在嵌入SQL语句中可以使用关键字NULL。下面是不使用指示符变量的一个UPDATE语句例子:if ( some condition) EXEC SQL UPDATE TEMPL SET PHONENO = NULL WHERE EMPNO = :eno ;else EXEC SQL UPDATE TEMPL SEST PHONENO = :newphone WHERE EMPNO = :eno ;但是,这种写法有缺点:如果U

28、PDATE语句需要修改,就要修改两处代码。如何设置指示符变量:谁维护指示符变量SQL语句类型宿主变量:cd指示符变量:cdi列JOBCODEDB2SELECT/FETCH60不改变0060NULL应用程序UPDATE/INSERT50N/A0050NULL注解:DB2在执行SELECT和FETCH语句的过程中设置指示符变量的值,应用程序应该在执行SELECT和FETCH语句后检查它们的值。应用程序在执行UPDATE和INSERT语句之前设置指示符变量的值来指示DB2是否在数据库中放置一个空值(NULL)。上表的第一行:在一条SELECT或者FETCH语句中,如果列(JOBCODE)中的值不为空

29、,值被设置到宿主变量(:cd)中,指示符变量(:cdi)的值为零;如果列中的值为空,指示符变量的值将为负数,宿主变量的值不改变。上表的第一行:在一条UPDATE或者INSERT语句中,如果指示符变量(:cdi)中的值不为负数,宿主变量(:cd)中的值被放到相应的列中;如果指示符变量中的值为负数,宿主变量中的值被忽略,相应的列被设置为空(NULL)。指示符变量在数值转换方面的应用:当宿主变量的数据类型与相应列的数据类型不兼容或者不能转换时,DB2也通过指示符变量通知应用程序。数值转换由数据库管理器处理,能转换时自动完成,对程序透明;如果列中的值不能存储到宿主变量中时(例如,列的数据类型为DECI

30、MAL(15),值的长度为12个数字,不能存储到INTEGER类型的宿主变量中),指示符变量的值为-2。指示符变量在截取方面的应用:在SQL语句执行后,如果指示符变量的值为正数,说明发生了数据截取:如果是时间数据类型的秒部分被截取,那么指示符变量中的值为截取的秒数对于其他数据类型,指示符变量表示数据库中列的数据原始长度,通常为字节数(数据库尽可能返回更多的数据)。例子:定义宿主变量和指示符变量:EXEC SQL BEGIN DECLARE SECTION;char too_little5;short iv1;EXEC SQL END DECLARE SECTION;表BANK_ITEMS:IT

31、EM#QTYDESCRIPTION1013000PASSBOOKS200100CHECKBOOKS执行的SQL语句: SELECT DESCRIPTION INTO :too_little:iv FROM BANK_ITEMS WHERE ITEM# = 200结果: :too_little中的值为CHECK,:iv1中的值为103.3 使用游标处理多行结果集为了使应用程序能够提取多行结果集,SQL使用了一种机制,叫做游标(cursor)。为了理解游标的概念,我们假设数据库管理器创建了一个结果表(result table),里面包含有执行一条SELECT语句所提取的所有行。通过标识或指向这个表

32、的“当前行”,游标使得结果表中的行对应用程序可用。当一个是拥游标时,应用程序可以顺序从结果表中提取每一行,直到产生一个数据结束条件,这个条件就是NOT FOUND条件,SQLCA中的SQLCODE为+100(SQLSTATE为02000)。执行SELECT语句的结果集,可能有零行、一行或者更多行,决定于有多少行符合搜索的条件。处理一个游标涉及到以下几个步骤:1 使用DECLARE CURSOR语句声明一个游标2 使用OPEN语句执行查询和创建结果表3 使用FETCH语句每次提取一行结果4 使用DELETE或UPDATE语句处理行(如果需要)5 使用CLOSE语句终止(关闭)游标一个应用程序中,

33、可以使用多个游标,但是每一个游标要有自己的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=

34、:host_var;Java (SQLJ)#sql iterator cursor1(host_var data type);#sql cursor1 = SELECT PNAME, DEPT FROM STAFF WHERE JOB=:host_var ;COBOLEXEC SQL DECLARE C1 CURSOR FOR SELECT NAME, DEPT FROM STAFF WHERE JOB=:host-var END-EXEC.FORTRANEXEC SQL DECLARE C1 CURSOR FOR+ SELECT NAME, DEPT FROM STAFF + WHERE J

35、OB=:host_var注解:DECLARE语句的在程序中位置是任意的,但是它必须在第一次使用游标的位置之前。 3.3.2游标与工作单元的考虑COMMIT或者ROLLBACK操作的动作随游标的不同而不同,依赖于游标的定义。1 只读游标(Read Only Cursors)如果一个游标被确定为只读的,并且使用可重复读隔离级(isolation level),那么系统表仍会收集和维护工作单元需要的可重复读锁。因此,即使只读游标,应用程序周期性地发出COMMIT语句还是很重要的。2 有WITH HOLD选项如果应用程序通过发出一条COMMIT语句来完成一个工作单元,除了声明时有WITH HOLD选项

36、的游标,所有游标将自动地被数据库管理器关闭。 用WITH HOLD声明的游标维护它访问的跨多个工作单元的资源。用WITH HOLD声明的游标受到的影响依赖于工作单元如何结束。 如果工作单元使用一条COMMIT语句结束,已打开的定义为WITH HOLD的游标将保持打开状态。游标的位置在结果集的下一个逻辑行之前。另外,参考用WITH HOLD定义的已准备好的语句也会被保留。紧跟COMMIT语句后面, 只有与一个某个特定游标相关联的FETCH和CLOSE请求才有效。UPDATE WHERE CURRENT OF和DELETE WHERE CURRENT OF 语句仅仅对在同一个工作单元中提取的行有效

37、。如果程序包在工作单元期间被重新绑定,那么所有保持的游标都会被关闭。 如果工作单元使用一条ROLLBACK语句结束,所有打开的游标被关闭,所有在工作单元中获得的锁被释放,以及所有依赖于这个工作单元的已准备好的语句被删除。 举个例子,假设TEMPL表中有1000条记录。要更新所有雇员的工资,应该每更新100行就要发出一条COMMIT语句。A. 使用WITH HOLD选项声明游标: EXEC SQL DECLARE EMPLUPDT CURSOR WITH HOLD FOR SELECT EMPNO, LASTNAME, PHONENO, JOBCODE, SALARY FROM TEMPL FO

38、R UPDATE OF SALARYB. 打开游标,每一次从结果表中提取一行数据: 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 EMPL

39、UPDT在一条COMMIT语句发出之后,在更新其它行之前必须发出FETCH语句。如果应用程序使用了用WITH HOLD声明的游标或者执行了多个工作单元并且有一个用WITH HOLD声明的游标跨工作单元处于打开状态,那么在程序中应该加入代码检测和处理SQLCODE为-501(SQLSTATE为24501)的错误,这个错误由FETCH或者CLOSE语句返回。如果应用程序的程序包由于其依赖的表被删除而变得无效,程序包会自动被重新绑定。这种情况下,FETCH或CLOSE语句返回SQLCODE 501(SQLSTATE 24501),因为 数据库管理器关闭游标。在此情形下,处理SQLCODE 501(S

40、QLSTATE 24501)的方法决定于是否要从游标提取行数据。l 如果要从游标提取行,打开游标,然后运行FETCH语句。注意,OPEN语句使得游标重定位到开始处。原来的位置信息丢失。l 如果不准备从游标提取行,那么不要对游标发出任何SQL请求。WITH RELEASE 选项:当应用程序用WITH RELEASE选项关闭一个游标时,DB2试图去释放游标持有的所有读锁(READ locks)。游标只继续持有写锁(WRITE locks)。如果应用程序没有用RELEASE选项关闭游标,那么在工作单元完成时,所有的读锁和写锁都被释放。3.3.3例程游标程序C Example: CURSOR.SQC#

41、include #include #include #include util.h #ifdef DB268K/* Need to include ASLM for 68K applications */#include #endif 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 pname10; short d

42、ept; char userid9; char passwd19; 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( Sample C program: CURSOR n ); if (ar

43、gc = 1) EXEC SQL CONNECT TO sample; CHECKERR (CONNECT TO SAMPLE); else if (argc = 3) strcpy (userid, argv1); strcpy (passwd, argv2); EXEC SQL CONNECT TO sample USER :userid USING :passwd; CHECKERR (CONNECT TO SAMPLE); else printf (nUSAGE: cursor userid passwdnn); return 1; /* endif */ EXEC SQL DECLA

44、RE 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 Clerkn, pname, dept ); while ( 1 ); EXEC SQL CLOSE c

45、1; (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 */Java Example: Cursor.sqljimport java.sql.*;import sqlj.runtime.*;import sqlj.runti

46、me.ref.*; #sql iterator CursorByName(String name, short dept) ;#sql iterator CursorByPos(String, short ) ; class Cursor static try Class.forName (COM.ibm.db2.jdbc.app.DB2Driver).newInstance (); catch (Exception e) System.out.println (n Error loading DB2 Driver.n); System.out.println (e); System.exit

47、(1); public static void main(String argv) try System.out.println ( Java Cursor Sample); String url = jdbc:db2:sample; / URL is jdbc:db2:dbname Connection con = null; / Set the connection if (argv.length = 0) / connect with default id/password con = DriverManager.getConnection(url); else if (argv.len

48、gth = 2) String userid = argv0; String passwd = argv1; / connect with user-provided username and password con = DriverManager.getConnection(url, userid, passwd); else throw new Exception(Usage: java Cursor username password); / Set the default context DefaultContext ctx = new DefaultContext(con); De

49、faultContext.setDefaultContext(ctx); / Enable transactions con.setAutoCommit(false); / Using cursors try CursorByName cursorByName; CursorByPos cursorByPos; String name = null; short dept=0; / Using the JDBC ResultSet cursor method System.out.println(nUsing the JDBC ResultSet cursor method); System.out.println( with a bind by name cursor .n); #sql cursorByName = SELECT name, dept FROM staff WHERE job=Mgr FOR UPDATE OF job ; (1) while (cursorByName.next() (2) name = cursorByN();

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论