18143453325 在线咨询 在线咨询
18143453325 在线咨询
所在位置: 首页 > 营销资讯 > 信息时代 > 动态SQL(数据库)

动态SQL(数据库)

时间:2022-12-19 10:30:02 | 来源:信息时代

时间:2022-12-19 10:30:02 来源:信息时代

    动态SQL : SQL标准提供的一种语句运行机制,它允许在SQL客户模块或嵌入式宿主程序的执行过程中执行动态生成SQL语句。
SQL标准从SQL92开始提供对动态SQL的支持。引入动态SQL的原因,是由于静态SQL语句不能提供足够的编程灵活性。在数据库应用开发中,虽然很多情况下可以把即将执行的SQL语句编码到SQL客户模块定义中,或编码到使用嵌入语法的编译单元中,但也有一些情况,写程序时SQL语句是未知的,需要通过动态SQL机制在程序执行时产生SQL语句。例如,要编写一个能随时接受用户从键盘输入的SQL语句的应用程序,而用户可能键入什么样的语句内容在编程时是不可预知的。根据上述特征,SQL语句可分为静态SQL语句和动态SQL语句。所谓静态SQL语句,是指除其引用的变量值为未知的外,语句的形式和操作对象等在编译时都已经确定的SQL语句: 而动态SQL语句是指在程序编译时尚未确定,其中有些部分需要在程序的执行过程中临时生成的SQL语句。
SQL标准提供的语句动态执行方式有两种。一种是立即执行; 一种是先准备后执行。
立即执行由立即执行语句实现。该语句的语法为: “EXECUTE IMMEDIATE SQL语句变量”。其中,“SQL语句变量”是一个字符串类型的变量,该变量的值就是要执行的SQL语句的文本。如:
EXEC SQL EXECUTE IMMEDIATE:sql_str;
执行该语句时,SQL服务器会对宿主变量sql_str包含的字符串进行解析并执行它所表示的SQL语句。如果sql_str的值为字符串“INSERT INTO T VALUES (0)”,则该语句的执行等效于: “EXEC SQL INSERT INTO T VALUES (0);”。并非所有的SQL语句都可以立即执行,当语句为查询语句或包含动态参数说明时,就必须使用先准备后执行的方式。此外,当同一条动态SQL语句在程序中需要被多次执行时,先准备后执行方式的效率更高。先准备后执行方式比立即执行方式的功能更强大,同时语法也更复杂。在这种方式下,动态SQL语句先通过准备语句进行准备,然后通过执行语句执行一次或多次,当不再需要执行该语句时,可以通过回收准备语句释放。
SQL语句中可能会使用参数,在动态执行的SQL语句中,这些参数被称为动态参数。动态参数在SQL语句中表现为问号“?”的形式。在有些情况下,产生动态执行的SQL语句的应用程序详细地知道该语句使用的动态参数所要求的特征(如数据类型、长度、精度、标度等等); 类似地,该应用程序也可能详细地知道执行该语句的返回值的特征。然而,在另一些情况下,这些信息是不可知的,只能由执行的准备语句的上下文得到。
为了给应用程序提供必要的信息,SQL标准支持应用程序通过描述语句要求SQL服务器描述准备语句。一个语句的描述信息标识了输入动态参数个数和它们的数据类型信息,或者输出参数的个数或返回值和它们的数据类型信息。这些描述信息被放在SQL描述符区中。SQL描述符区由一个或多个条目描述符区,以及包括这些条目描述符区个数计数的首部构成。SQL描述符区可通过分配描述符语句、回收描述符语句、设置描述符语句和获取描述符语句来分配和维护。
动态执行的SQL语句中最复杂的是动态选择语句。对于动态选择语句,SQL标准提供两种处理方式: 动态单行选择语句和动态游标方式。前者只在可以确定查询结果不超过一行的情况下使用,一般情况下则是通过动态声明游标语句或分配游标语句将其与一个游标相关联。标准还提供一系列对动态游标的操纵语句。动态打开语句打开游标并将动态参数与该游标绑定。动态获取语句把打开的游标定位到特定行,并获取该行中列的值。动态关闭语句关闭由动态打开语句打开的游标。“动态删除语句: 定位”用动态游标来删除行。“动态更新语句:定位”用动态游标来更新行。当语句精确格式直到执行时才可知时,“可准备动态删除语句: 定位”用动态游标来删除行。当语句精确格式直到执行时才可知时,“可准备动态更新语句: 定位”用动态游标来更新行。
下面是一个动态SQL查询的程序示例,例中有一个字符型的动态输入参数,但输出参数的个数和数据类型不定。
EXEC BEGIN DECLARE SECTION;
int i,col_num,col_type;
char sql_str[100];
EXEC SQL END DECLARE SECTION;
……
strcpy(sql_str,
"SELECT*FROM tab_1 WHERE col_1=?");
EXEC SQL PREPARE sql_stmt FROM :sql_str;
EXEC SQL DECLARE c1 CURSOR FOR sql_stmt;
EXEC SQL ALLOCATE DESCRIPTOR des_1;
/*描述动态输入参数的信息*/
EXEC SQL DESCRIBE INPUT sql_stmt
USING DESCRIPTOR des_1;
/*给描述符赋值*/
EXEC SQL SET DESCRIPTOR des_1 VALUE 1
TYPE=1,INDICATOR=0,
DATA='A00001',LENGTH=6;
EXEC SQL OPEN c1
USING DESCRIPTOR des_1;
/*描述动态输出参数的信息*/
EXEC SQL DESCRIBE OUTPUT sql_stmt
USING DESCRIPTOR des_1;
for(;;){
EXEC SQL FETCH c1
USING DESCRIPTOR des_1;
if(!strncmp(SQLSTATE,”02000”,5)) break;
EXEC SQL GET DESCRIPTOR des_1
:col num=COUNT;
for(i=1;i〈col_num;i++){
EXEC SQL GET DESCRIPTOR des_1
:i:col_type=TYPE;
/*根据返回值的数据类型进行处理*/
switch(col_type){
case 1: ……
case 2: ……
……
}
}
}
EXEC SQL CLOSE c1;
EXEC SQL DEALLOCATE PREPARE sql_stmt;
EXEC SQL DEALLOCATE DESCRIPTOR des_1;

74
73
25
news

版权所有© 亿企邦 1997-2022 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭