共有4种构方法构造动态SQL语句:
1、方法一:
仅适用于非SELECT语句,且语句中不包含输入宿主变量。格式如下
EXEC SQL EXECUTE IMMEDIATE :host_string 或
EXEC SQL EXECUTE IMMEDIATE "UPDATE XX SET NAME=yyyy HERE ID=1"
2、方法二:
也只适用于非SELECT语句,SQL语句可包含虚拟输入宿主变量和指示器变量,但它们的个数和数据类型在预编译时必须是可知的。
处理分三步:
A、构造一个动态SQL语句。
B、用PREPARE 语句来分析和命名该动态SQL语句
C、用EXECUTE 来执行
EXEC SQL PREPARE 用于分析一个动态SQL,如
strcpy(sql_stmt,"DELETE FROM EMP WHERE JOB=:v");
EXEC SQL PREPARE stmt FROM :sql_stmt;
EXECUTE 语句格式:
EXEC SQL FOR <行数> EXECUTE <动态语句> USING <参数>
EXEC SQL EXECUTE stmt USING :job;
3、方法三:
方法三只适用于SELECT语句,语句中包含选择表项个数,和虚拟输入宿主变量个数在预编译时都是已知的,但是数据库的表、列名可能运行时指定。步骤如下:
1、定义动态脚本。
2、分析动态脚本。
3、定义游标,游标的语句就是动态分析的名。
代码例子:
strcpy(sql_stmt,"SELECT SID,ENAME FROM EMP WHERE JOB=:v");
EXEC SQL PREPARE stmt FROM :sql_stmt;
EXEC SQL DECLARE cur FOR stmt ;
然后遍历游标:
{
EXEC SQL for :n FETCH stud_cur INTO :stud_id,:stud_age,:stud_n
ame,:stud_addr;
rows = sqlca.sqlerrd[ 2 ];
printf( " rows=%d/n " ,rows);
int i;
if (sqlca.sqlcode < 0 ) {
printf( " ora err:%d " ,sqlca.sqlcode);
break ;
}
rows = sqlca.sqlerrd[ 2 ] - n * j;
for (i = 0 ;i < rows;i ++ )
{
printf( " %d--%d--%s--%s/n " ,stud_id[i],stud_age[i],stud_name
[i].arr,stud_addr[i].arr);
}
j ++ ;
printf( " currsor %d times/n " ,j);
if ((sqlca.sqlcode == 1403 ) ) break ;
}
上面遍因游标是一次取N条记录的,因为stud_id等是数组,n为数组长度
一个完整的动态游标例子
#include < string .h >
#include < stdlib.h >
EXEC SQL include sqlca;
#ifdef TRUE
#undef TRUE
#endif
#define TRUE 1
EXEC ORACLE OPTION (RELEASE_CURSOR = YES);
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR username[ 20 ];
VARCHAR password[ 20 ];
EXEC SQL END DECLARE SECTION;
void sql_error()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf( " /n Oracle error detected:/n " );
printf( " /n%.70s/n " ,sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK RELEASE;
exit( 1 );
}
void dyna_cursor()
{
EXEC SQL BEGIN DECLARE SECTION;
char * sql_str;
int stud_id;
int stud_age;
VARCHAR stud_name[ 20 ];
VARCHAR stud_addr[ 60 ];
int vage;
EXEC SQL END DECLARE SECTION;
sql_str = ( char * )malloc( 400 );
vage = 3 ;
strcpy(sql_str, " SELECT STUD_ID,STUD_NAME FROM PROC_STUD WHERE STUD_A
GE = :v1 " );
EXEC SQL PREPARE S FROM :sql_str;
EXEC SQL DECLARE C CURSOR FOR S;
printf( " please input age :/n " );
scanf( " %d " , & vage);
EXEC SQL OPEN C USING :vage;
EXEC SQL WHENEVER NOT FOUND GOTO notfound;
while (TRUE)
{
EXEC SQL FETCH C INTO :stud_id,:stud_name;
/* stud_name.arr[stud_name.len]='/0'; */
/* stud_name.len=strlen(stud_name.arr); */
printf( " %d/t%s/n " ,stud_id,stud_name.arr);
}
notfound:
printf( " /nQuery Returned %d row %s/n " ,sqlca.sqlerrd[ 2 ],sql_str);
EXEC SQL CLOSE C;
EXEC SQL COMMIT RELEASE;
printf( " Have a good day!/n " );
exit( 0 );
sqlerror:
printf( " %d %.*s/n " ,sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc);
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL CLOSE C;
EXEC SQL ROLLBACK RELEASE;
exit( 1 );
}
main()
{
strcpy(username.arr, " gdnum_true " );
strcpy(password.arr, " gdnumtrue_10 " );
username.len = strlen(username.arr);
password.len = strlen(password.arr);
EXEC SQL CONNECT :username IDENTIFIED BY :password;
printf( " sqlca.sqlcode=%d;/n " ,sqlca.sqlcode);
printf( " login user=%s/n " ,username.arr);
dyna_cursor();
exit( 0 );
}
4、方法四