20提高ESQLC程序的运行效率.docx
- 文档编号:4683966
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:14
- 大小:1,013.66KB
20提高ESQLC程序的运行效率.docx
《20提高ESQLC程序的运行效率.docx》由会员分享,可在线阅读,更多相关《20提高ESQLC程序的运行效率.docx(14页珍藏版)》请在冰豆网上搜索。
20提高ESQLC程序的运行效率
第二十章
提高ESQL/C程序的运行效率
本章讲述如何提高程序的运行效率,例如,要重复执行SQL语句时怎样改进程序。
在本材料中引入了一些动态SQL专题的内容,有关动态SQL将在AdvancedINFORMIX-ESQL/C课程中详细讨论。
可以通过编写C语句,并包括进来特殊的头文件和SQL语句,从而创建ESQL/C程序。
然后,运行esql预编译器来处理该程序,esql接受要处理的代码,读入所有的SQL语句,并把它们翻译成C的代码。
正如在前面的章节提到过的那样,嵌入的SQL语句可以是所有的可交互式的SQL语句,例如,在INFORMIX-DBAccess中使用的SQL语句。
嵌入的SQL语句也有一些是自己独有的,这些语句处理编译、游标和动态SQL。
当esql读到一条象WHENEVER的指令,它从代码中去掉该指令,并从该处开始捕获所说明的错误。
当esql读到有关游标操作的SQL语句,象OPEN等,它把这些语句简单翻译为对特定函数的调用。
当esql读到动态SQL语句,象PREPARE等,它把这些语句简单翻译为对特定函数的调用。
但是,当esql读到象INSERT、SELECT、UPDATE或DELETE之类的语句时,它在一个私有的、局部块中完成一系列的事情:
●把SQL语句存放到一个字符数组中。
●如果有的话,把所有的输入数据和输出数据有关的描述信息存储起来。
●调用一个特定的函数来处理SQL请求。
可以浏览esql产生的C代码来查看这一点。
在程序运行时,SQL语句仅是作为字符串存在于内存中的某个区域。
当esql预编译程序时,它产生一个指向该字符串的指针。
(实际上,它建立起一个字符指针数组,每个指针指向一段SQL文本。
)上面就是这样的一个存放SQL文本的例子。
在该例子中,注意到两个宿主变量被两个问号所代替(?
):
它们是实际数据的占位符。
为理解该替换,需要明白编译源代码的一个基本目的:
为数据值提供地址信息。
编写源代码时,使用符号来引用变量数据,把它们称为宿主变量。
但是,程序运行时,对此计算机所能理解的唯一事情是数据的值和地址,它并不理解对于符号的引用。
为从符号引用转换为对机器地址的访问,需要编译源程序。
从SQL语句得到的SQL文本不会有任何的符号内存引用(宿主变量)。
在翻译的第3步,这一点你马上就能看到,一个特定的函数在程序运行时把该文本传递该数据库服务器。
在运行时刻,没有诸如符号引用之类的东西,只有地址和数据的值。
如果该函数传递的是对符号的引用,象$PhoneLc10,服务器试图把它解释为某些SQL对象的名称,从而导致错误。
这就是为什么要使用问号来代替宿主变量。
在程序运行时,SQL语句仅是以字符串的形式存在于内存中的某个位置,去掉了所有的对宿主变量的引用。
为了保证这些数据值的位置不会丢失,esql把它们的地址存放到一个特定的数组中。
当我们到达第3步,即在数据库服务器执行SQL请求时,它需要这些地址。
那时,我们只要传递一个指向该数组的指针。
在SQL语句中有两类数据要引用:
送往服务器的数据,称为输入数据,以及从服务器送出来的数据,称为输出数据。
esql区分这两种数据,把它们的地址存放到不同的数组。
数据种类
特定的数组
输入数据
_sqibind
输出数据
_sqobind
在下面的INSERT语句中:
$insertintocustomer(phone,company)
values($PhoneLc10,$CompanyLc20);
VALUES子句中的两个宿主变量给服务器提供输入数据,因此它们的地址存放到_sqibind数组中。
每个SQL语句同一个特定库中的某个函数相关联,该库在使用esql时自动链接到程序中。
这些函数通过管道同数据库服务器通讯。
这些函数送给服务器两种不同的请求:
请求A:
对SQL语句进行语法分析。
请求B:
执行SQL语句。
在语法分析过程中,数据库服务器:
●检查SQL语句的语法和语义的合法性
●检查访问权限
●如果需要的话,优化查询路径
如果服务器在这一步发现错误,它返回一个错误代号给调用函数,该函数接着设置SQLCODE的值;接着执行紧跟着SQL语句的下一条语句。
在这一步没有对数据值的引用。
如果数据库服务器没有发现错误,它把“编译后的”以及优化了的SQL语句版本存放到它的数据空间里的某个结构中,并给调用函数返回一个成功完成代码0。
该函数接着发送另一个请求给服务器:
执行。
此时,服务器需要对数据值的引用,以执行SQL语句。
常常要重复执行一条或多条SQL语句。
这里是两个重复执行的例子:
●把一个UPDATE语句放到一个函数里,并在程序中的不同位置调用该函数。
●几百次的重复执行一段代码,每次从标准输入读一个记录,然后使用INSERT语句把记录插入数据库。
正如你看到的那样,嵌入的交互式SQL语句转换成的C代码,完成三项任务:
1.把SQL语句作为字符串存放。
2.如果有输入或输出数据,绑定它们。
3.调用一个函数,它(A)使得SQL语句被编译以及(B)执行“编译的”文本。
既然静态的SQL语句除了涉及到值可能有变动外,在每次执行时都没有任何的变化,一次又一次地执行产生的整段代码确实很浪费时间。
当数据的值改变时,只需要在第3B步处开始循环。
即,一旦第一步和第二步完成,而且SQL语句“编译完成”,我们仅需要一次又一次地执行SQL请求本身。
在后面讨论如何使循环更有效率。
为使SQL语句的循环更有效率,可以使用另外的两条嵌入SQL语句:
PREPARE和EXECUTE。
使用PREPAE语句显式地请求对SQL语句进行语法分析。
它的语法是:
PREPAREStatementIdSpecFROMStatementTextSpec
StatementIdSpec
同SQL语句相联系的标识符或存放有该标识符的宿主变量。
StatementTextSpec
用引号括起来的字符常数,或指向字符数组的指针。
该字符串至少存放有一条SQL语句的文本。
语法分析SQL语句成功之后,数据库服务器把SQL语句的可执行版本保存起来供以后使用。
语句保存在名字为StatementIdSpec的一个特殊结构中,以后使用该标识符来请求执行准备好的语句。
激活语句的标识符的数目只受限制于系统的可用内存的多少,内部没有加任何的限制。
语句标识符在缺省情况下作用域是全局的。
这意味着可以在一个源文件中准备一条语句,而在另一个源文件中执行它。
如果希望所有这类标识符的作用域对于准备语句的源文件来说是局部的,必须在esql命令行使用-local标志。
当为一条PREPARE语句说明语句文本时,可以在语句中提供一个字符串,或把文本存放到一个字符宿主变量中,再提供指向它的指针。
但是,这类的文本有一些限制:
●必须仅是交互式的SQL语句。
●不允许游标操作、动态SQL语句和编译指令。
例如,不能准备DECLARE或FREE语句。
另外不能使用C语句、$前缀或EXECSQL。
●不能有C的注释,只允许有SQL注释(以双短横开头或包括在花括号中)。
●所有的名称必须标识一个SQL对象:
数据库、表、字段、过程,等等。
●名称不能是对宿主变量的引用,在这里不会识别它们。
不要使用宿主变量名,而是使用占位符"?
"。
●因此,不能准备一条有INTO子句的SELECT语句。
执行PREPARE语句之后,总应该检查SQLCODE的值。
在语法分析这一步,数据库服务器检查语法、语义、权限等等,检查到的任何错误通过把SQLCODE设置为负值来报告。
准备SQL文本时两种最常见的错误是非法语法和未知SQL对象。
当SQLCODE为负值时,同时应检查sqlca结构中的两个域:
sqlerrd[4]
语句文本中错误的偏移。
sqlerrm
如果有错的话,包含有错误发生的SQL对象的名称。
如果准备的文本包含有多条语句,返回的SQLCODE负值指明文本中的第一个错误,即使有多个错误存在。
如果语法分析发现未知的SQL对象,sqlca中的sqlerrm域存放该对象的名字。
另外,由函数rgetmsg()返回的错误消息中包含有格式描述%s来代替对象的名字作为消息的一部分。
在上面的例子中使用该特点和sqlerrm来组合成一个有意义的错误消息。
一旦为执行动作准备好了SQL文本,可以使用EXECUTE语句来执行。
如果准备的文本中有?
占位符,那么必须在数据库服务器执行SQL文本之前,为它们提供值。
为执行准备好的“固定的”SQL文本,一般使用下面的语法:
EXECUTEStatementIdSpec[USINGHostVariableList]
StatementIdSpec
在先前的PREPARE语句中定义的SQL语句标识符,或存放有这类标识符的宿主变量。
HostVariableList
一个或多个宿主变量,为准备好的语句中的?
占位符提供值,绑定值时按位置顺序。
可以执行除了准备好的SELECT语句以外的任何准备好的语句,。
(但是,可以执行一个准备好的SELECTINTOTEMP语句。
这类SELECT语句不使用游标,它们把结果存放到磁盘上,而不是存放到内存中。
)
使用USING子句为准备好的语句中的?
占位符提供值,有时称之为参数化。
即,包含有?
占位符的语句称为参数化语句。
必须按位置顺序为每个占位符提供一个宿主变量,这些变量的数据类型同所准备的语句的要求要兼容。
在前面的章节中已经学习了如何设置和使用更新游标。
还学习了在DELETE或UPDATE语句中使用WHRERCURRENTOF选项来提高删除和修改操作的效率,在DELETE或UPDATE语句中使用该选项可以减少对磁盘的访问,因为它只进行一次重写操作,而不是一次读和一次重写操作。
为使利用更新游标对当前记录的修改和删除操作效率更高,可以先准备一条DELETE或UPDATE语句,再执行它们。
上面的例子定义了一个更新游标,准备了一条带有WHERECURRENTOF子句的UPDATE语句,并演示了在一个循环中执行准备好的UPDATE语句。
下面列出了修改和删除记录的不同方法,按效率逐渐减低的顺序:
●定义一个更新游标,准备一条带有WHERECURRENTOF子句的DELETE或UPDATE语句,然后重复执行准备好的语句。
●定义一个更新游标,重复执行一条固定的带有WHERECURRENTOF子句的DELETE或UPDATE语句。
●重复执行一条固定的DELETE或UPDATE语句。
程序中的每个交互式的SQL语句会产生两次分离的与数据库服务器的通讯操作:
一次请求语法分析、一次请求执行,如我们先前所见。
有时,一段SQL语句总是作为一个单元一起执行。
例如,要进行三次分开的修改,每次执行该段代码时,要同数据库服务器通讯六次。
可以通过把这些语句作为一个单元来准备,而不是分开准备,这样可以减少管道操作,从而提高性能。
上面显示的是一个关于多条语句文本的例子。
但是,象这样构造多条语句文本时,要谨慎小心。
请求的动作必须各自独立,它们不能依赖于文本中的先前的语句。
使用时要小心,因为数据库服务器不会按顺序处理请求的动作。
数据库服务器对于多条语句文本中产生的第一个错误返回出错消息,但不指明是语句序列中的哪一条语句出现了错误。
在准备多条语句文本时不能包括下面的语句:
CREATEDATEBASEDATABASESELECT
DROPDATABASECLOSEDATABASESTARTDATABASE
对于游标和准备的SQL语句都要在内存中给它们分配资源。
为释放这些资源,使用FREE语句:
FREEIdSpec
IdSpec标识要释放资源的游标或准备的语句。
游标标识符在DECLARE语句中定义,语句标识符在PREPARE语句中定义。
IdSpec可以是标识符本身或存放有标识符的宿主变量的名字。
释放内存资源的例子见上面所示。
可以使用已存在语句的标识符来重用标识符。
这样做,服务器会自动释放分配给先前语句的所有资源,并给新语句分配新的资源。
释放资源确实把空间释放回给空闲内存。
但如果需要重新执行准备的语句或重用游标,必须重新申请资源而再次花费代价。
如果希望重复执行一条进行了语法分析的语句或重新打开一个游标,那么不要释放它们!
一旦释放了一个准备好的语句,它不能再被执行,要重新执行,必须再次准备。
一旦释放了游标,它不能再打开,只能重新定义。
重新定义游标要进行游标结构的分配,而打开该游标使得服务器对相关联的SELECT或INSERT语句进行语法分析。
游标和准备的SQL语句在分配给它们的内存中有多种资源。
活动的游标标识符有一个游标结构、一个缓冲区和与之相关联的进行了语法分析的SELECT或INSERT语句。
当游标关闭时,释放缓冲区,但是,同游标标识符相关联的结构和进行了语法分析的语句不释放。
释放同静态游标相链接的标识符会把这些资源释放回空闲内存。
(对于动态游标,分配给进行了语法分析的语句的资源保留不动,仍可以访问该语句。
)
语句标识符与进行了语法分析之后的语句版本相关联。
释放语句标识符实际上也把同标识符相关联的内存释放回给空闲内存。
(对于动态游标,分配给游标的资源保留不动,仍可以访问游标。
)
下表总结了执行FREE语句时,释放的资源:
释放的内存资源
FREE语句的类型
应用程序
服务器
FREE静态游标
yes
yes
FREE准备的语句
no
yes
FREE动态游标
yes
no
不进行准备的语句要求在编写程序时,知道语句的确切格式和内容。
例如,必须在WHERE子句中确切列出让服务器检测的字段。
另外,必须在字段的选择列表中确切地列出数据库服务器应返回的字段。
如果应用程序必须动态地响应,可能有一些任务事先无法完全确定。
例如,为响应交互式用户,可能需要根据用户的输入来合成SQL语句。
动态SQL语句使得用户可以在程序执行过程中合成这一类的语句。
动态SQL语句使用的基本过程是这样的:
●把SQL语句的文本内容装配成字符串,并存放到程序变量中。
●使用PREPARE语句为执行准备该文本。
●使用EXECUTE语句执行准备好的语句。
●使用FREE语句显式地释放由准备过的语句标识符占用的资源。
INFORMIX-ESQL/C培训教材的另一本书,AdvancedINFORMIX-ESQL/C,详细讨论了动态SQL语句,包括使用未知的数据类型。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 20 提高 ESQLC 程序 运行 效率