第三章静态SQL编程方法

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第三章静态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列的值输出,否则打印错误信息。/**********************************************************************************SourceFileName=static.sqc1.4****LicensedMaterials-PropertyofIBM*********************************************************************************/#includestdio.h#includestdlib.h#includestring.h#includeutil.h#ifdefDB268K/*NeedtoincludeASLMfor68Kapplications*/#includeLibraryManager.h#endifEXECSQLINCLUDESQLCA;/*:rk.1:erk.*/#defineCHECKERR(CE_STR)if(check_error(CE_STR,&sqlca)!=0)return1;intmain(intargc,char*argv[]){EXECSQLBEGINDECLARESECTION;/*:rk.2:erk.*/charfirstname[13];charuserid[9];charpasswd[19];EXECSQLENDDECLARESECTION;#ifdefDB268K/*BeforemakinganyAPIcallsfor68Kenvironment,needtoinitialtheLibraryManager*/InitLibraryManager(0,kCurrentZone,kNormalMemory);atexit(CleanupLibraryManager);#endifprintf(SampleCprogram:STATIC\n);if(argc==1){EXECSQLCONNECTTOsample;CHECKERR(CONNECTTOSAMPLE);}elseif(argc==3){strcpy(userid,argv[1]);strcpy(passwd,argv[2]);EXECSQLCONNECTTOsampleUSER:useridUSING:passwd;/*:rk.3:erk.*/CHECKERR(CONNECTTOSAMPLE);}else{printf(\nUSAGE:static[useridpasswd]\n\n);return1;}/*endif*/EXECSQLSELECTFIRSTNMEINTO:firstname/*:rk.4:erk.*/FROMemployeeWHERELASTNAME='JOHNSON';CHECKERR(SELECTstatement);/*:rk.5:erk.*/printf(Firstname=%s\n,firstname);EXECSQLCONNECTRESET;/*:rk.6:erk.*/CHECKERR(CONNECTRESET);return0;}/*endofprogram:static.sqc*/这个例程中实现了一个选择至多一行(即单行)的查询,这样的查询可以通过一条SELECTINTO语句来执行。SELECTINTO语句从数据库中的表选择一行数据,然后将这行数据的值赋予语句中指定的宿主变量(下节将要讨论宿主变量)。例如,下面的语句将姓为‘HAAS’的雇员的工资赋予宿主变量empsal:SELECTSALARYINTO:empsalFROMEMPLOYEEWHERELASTNAME='HAAS'一条SELECTINTO语句必须只能返回一行或者零行。如果结果集有多于一行,就会产生一个错误(SQLCODE–811,SQLSTATE21000)。如果查询的结果集中有多行,就需要游标(CURSOR)来处理这些行。在节3.2.3中介绍如何使用游标。静态程序是如何工作的呢?1.包括结构SQLCA。INCLUDESQLCA语句定义和声明了SQLCA结构,SQLCA结构中定义了SQLCODE和SQLSTATE域。数据库管理器在执行完每一条SQL语句或者每一个数据库管理器API调用,都要更新SQLCA结构中的SQLCODE域的诊断信息。2.声明宿主变量。SQLBEGINDECLARESECTION和ENDDECLARESECTION语句界定宿主变量的声明。有些变量在SQL语句中被引用。宿主变量用来将数据传递给数据库管理或者接收数据库管理器返回的数据。在SQL语句中引用宿主变量时,必须在宿主变量前加前缀冒号(:)。详细信息看下节。3.连接到数据库。应用程序必须先连接到数据库,才能对数据库进行操作。这个程序连接到SAMPLE数据库,请求以共享方式访问。其他应用程序也可以同时以共享访问方式连接数据库4.提取数据。SELECTINTO语句基于一个查询提取了一行值。这个例子从EMPLOYEE表中,将LASTNAME列的值为JOHNSON的相应行的FISRTNME列的值提取出来,置于宿主变量firstname中。5.处理错误。CHECKERR宏/函数是一个执行错误检查的外部函数。3.1.2创建应用程序创建应用程序的整个过程如图所示:3.1.3静态SQL的特点静态SQL编程比动态SQL编程简单些.静态SQL语句嵌入宿主语言源文件中,预编译器将SQL语句转换为宿主语言编译器能够处理的数据库运行时服务API调用。因为在捆绑应用程序时,做捆绑的人需要有一定的授权,因此最终用户不需要执行程序包里的语句的直接权限。例如,一个应用程序可以只允许某个用户更新一个表的部分数据,而不用将更新整个表的权利给予这个用户。这个功能通过限制嵌入的静态SQL语句只能更新表中的某些列或者一定范围内的值,只将程序包的执行权限给予这个用户。静态SQL语句是持久稳固的,动态SQL语句只是被缓存,直到变为无效、因为空间管理原因被清理或者数据库被关闭。如果需要,当被缓存的语句变为无效时,DB2SQL编译器隐性地重新编译动态SQL语句。静态SQL语句的主要优点是静态SQL在数据库关闭后仍然存在,而动态SQL语句在数据库关闭后就被清除了。另外,静态SQL在运行时不需要DB2SQL编译器来编译,相反,动态SQL语句需要在运行时编译(例如,使用PREPARE语句)。因为DB2缓存动态SQL语句,这些语句也不总是需要DB2编译。但是,每一次运行程序至少需要编译一次。静态SQL有性能上的优势。对简单、运行时间短的SQL程序,静态SQL语句比相同目的的动态SQL语句执行得快。因为静态SQL语句准备执行形式的开销在预编译时间,而不是在运行时。注意:静态SQL语句的性能决定于应用程序最后一次被捆绑时数据库的统计信息。然而,如果这些统计信息改变了,那么比较起来,等效的动态SQL语句的性能可能好些。在某个使用静态SQL的应用程序捆绑之后,数据库增加了一个索引,如果这个应用程序不重新捆绑,就不能利用这个索引。还有,如果在静态SQL语句中使用宿主变量,优化器也不能使用表的分布信息来优化SQL语句。3.2宿主变量和指示符变量的应用3.2.1宿主变量的声明宿主变量(Hostvariables)在主应用程序中由嵌入式SQL语句引用的变量。宿主变量是该应用程序中的程序设计变量,并且是在数据库中的表与应用程序工作区之间传送数据的主要机制。我们称之为“宿主变量”,是为了与通常方法声明的源语言变量区分开来,通常方法声明的变量不能被SQL语句引用。宿主变量在宿主语言程序模块中以一种特殊的方式声明:必须在BEGINDECLARESECTION和ENDDECLARESECTION程序节内定义。下图显示在不同编程语言中声明宿主变量的例子。语言例子源码C/C++EXECSQLBEGINDECLARESECTION;shortdept=38,age=26;doublesalary;charCH;charname1[9],NAME2[9];/*Ccomment*/shortnul_ind;EXECSQLENDDECLARESECTION;Java//NotethatJavahostvariabledeclarationsfollow//normalJavavariabledeclarationrules,andhave//noequivalentofaDECLARESECTIONshortdept=38,age=26;doublesalary;charCH;Stringname1[9],NAME2[9];/*Javacomment*/shortnul_ind;COBOLEXECSQLBEGINDECLARESECTIONEND-EXEC.01agePICS9(4)COMP-5VALUE26.01DEPTPICS9(9)COMP-5VALUE38.01salaryPICS9(6)V9(3)COMP-3.01CHPICX(1).01name1PICX(8).01NAME2PICX(8).*COBOLcomment01nul-indPICS9(4)COMP-5.EXECSQLENDDECLARESECTIONEND-EXEC.下面是引用宿主变量的例子语言例子源码C/C++EXECSQLFETCHC1INTO:cm;printf(Commission=%f\n,cm);Java#SQL{FETCH:c1INTO:cm};System.out.println(Commission=+cm);COBOLEXECSQLFETCHC1INTO:cmEND-EXECDISPLAY'Commission='cm在SQL语句中引用宿主变量时,必须加前缀—冒号(:)。冒号的作用是将宿主变量与SQL语法中的元素区分开。如果没有冒号,宿主变量会误解释为SQL语句的一部分。例如:WORKDEPT=dept将被解释为WORKDEPT列的值等于dept列的值。在宿主语言语句中,则不需要加前缀,正常引用即可。从下图中可看出如何使用宿主变量:gets(dept);CSQL提供一个值C01…WHEREWORKDEPT=:deptC01deptDB2名字空间(如表名、列名等等)不能用宿主变量指定。例如不能写如下SQL语句:SELECT:col1FROM:tabname但是,这种类型的功能可以通过采用动态SQL实现。总的来说,宿主变量有以下特点:可选的,在语句运行之前用来赋值宿主语言标号在SQL语句中,前面加冒号宿主变量与列的数据类型必须匹配对于宿主变量有以下要求:a.所有被嵌入SQL引用的宿主变量必须在BEGIN和ENDDECLARE语句界定的代码区里声明;b.宿主变量的数据类型必须与列的数

1 / 30
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功