动态SQL 在有些情况下, 在编码时SQL语句还不能完整地写出来, 而是在程序执行时才能构造出来(也就是说动态SQL语句在程序编译时语句的选择列表和确定, 变量数据大于0)。 这种在程序执行临时生成的SQL语句叫动态SQL语句. 利用动态SQL来编写Pro*C程序的方法叫动态SQL技术. 在下列情况之一不知道时, 使用动态SQL技术: a. SQL语句的文本. b. 宿主变量的个数。 c. 宿主变量的数据类型。 Oracle Pro*C 编程入门 d. 引用的数据库对象, 如列, 索引, 序列, 表, 用户名和视图. 实际上, 动态SQL在一般应用中用的相当普遍! Oracle中动态SQL可用以下两种方法实现: 一个是Oracle自己的方法, 一个是ANSI的方法. 一般建议使用Oracle的方法,但对于较复杂的应用, 可以使用ANSI的方法, 因为这样可以使自己的程序简化。 下面先说Oracle自己的方法. 5.1 Oracle方法 一般来说, 应该使用一个字符串变量来表示动态SQL语句的文本。 但该文本不包含“EXEC SQL”和分号“;”以及下列嵌入式SQL命令: ALLOCATE CLOSE DECLARE DESCRIBE EXECUTE FETCH FREE GET INCLUDE OPEN PREPARE SET WHENEVER 5.1.1 动态SQL语句的处理过程 动态SQL语句的处理过程如下: a. 构造动态SQL语句, 提示用户输入和构造一个动态SQL语句文本。 b. 分析该语句: Oracle对动态SQL语句文本进行语法检查, 并检查动态SQL语句所参照的数据库对象是否存在, 以及用户是否具有访问它所参照的对象的权限。 c. 为SQL语句结合宿主变量:在执行语句过程中, Oracle读取宿主变量地址, 并从这些变量中读取数据, 式将数据写入这此变量中。 d. 执行SQL语句, 实现数据库操作。 5.1.2 Oracle使用动态SQL的四种方法 Oracle提供了四种处理动态SQL的方法, 这四种方法从一到四依次变得复杂,从功能上说也是依次包含关系, 即前一种方法的功能可以完全由后一种方法实现。 用户可以根据每个任务的难易程度选择一种适合于自己的方法。 有关这四种方法的详细介绍请参考相关手册和DEMO程序. a. 方法一 这种方法只能执行非查询语句, 且在非查询动态SQL语句内不能包含输入宿主变量占位符。 这种方法使用EXECUTE IMMEDIATE命令立即执行动态SQL语句, 所以在每次执行时, Oracle需要对语句进行重新解释。 如: … <连接数据库> strcpy(str_sql,“DELETE FROM test001 WHERE name=’username’”); Oracle Pro*C 编程入门 EXEC SQL EXECUTE IMMEDIATE :str_sql; … b. 方法二 这种方法也只能用于执行非查询语句, 并且允许非查询动态SQL语句内包含输入宿主变量占位符, 但它要求在预编译时刻动态SQL语句内的占位符数量及输入宿主变量的数据类型必须确定。 ①. 准备阶段: 调用PREPARE语句准备需要执行的动态SQL语句, 这时Oracle对动态SQL语句进行语法分析, 检查它所参照的数据库对象等; ②. 执行阶段: 调用EXECUTE 命令执行准备好的动态SQL语句。 采用这种方式时, 动态SQL被准备好后可以被多次执行, 而不需要Oracle在 每次执行时重新解释SQL语句。 如: … <连接数据库> strcpy(str_sql,“INSERT INTO test001 values (:K1,:K2,:K3)”); EXEC SQL PREPARE test FROM :str_sql; EXEC SQL EXECUTE test USING :uname, :uaddress,:usex; … 占位符可以是随便给的一个字符, 单词等.它只起占位作用而没有实际意义. c. 方法三 这种方法可以执行包括查询语句在内的动态SQL语句, 但它要求在预编译时刻动态SQL语句内选择列表项数,输入宿主变量占位符数据以及输入宿主变量的数据类型必须确定。 方法三以游标方式执行动态SQL语句, 它对SQL语句的处理过程为: ①. 准执行PREPARE命令准备SQL语句; #实际就是把要执行的动态语句调入内存, 以 便以后对它进行操作。 ②. 执行DECLARE命令声明游标; ③. 执行OPEN打开游标; ④. 调用FETCH语句提取游标; ⑤. 调用CLOSE语句关闭游标。 动态SQL语句中的数据库对象名称和列名可以在运行时刻指定, 便此时不能以宿主变量形式指定对象名称或列名. 其实就是多了一个游标的使用。 如下面程序: <连接数据库>; strcpy(sql_stmt, "SELECT name, address, sex FROM test001"); EXEC SQL PREPARE select_stmt FROM :sql_stmt; EXEC SQL DECLARE c1 CURSOR FOR select_stmt; EXEC SQL OPEN c1; EXEC SQL WHENEVER NOT FOUND DO BREAK; while(1) Oracle Pro*C 编程入门 { EXEC SQL FETCH c1 INTO :Name, :address, :sex; printf("The name is: %s, The Address is: %s, The sex is :%s\n", Name, address, sex); } EXEC SQL CLOSE c1; d. 方法四 使用描述符方式处理动态SQL语句,它可以执行包括查询语句在内的所有动态SQL语句。 这种方式对动态SQL语句的限制最小, 它不要求在预编译时确定动动态SQL语句内的选择列表项数,库占位符数量以及宿主变量数据类型, 这些元素只要在运行时刻能够确定即可。 也就是说这种方法适合于在程序编译时对程序中的SQL语句还一无所知的情况。 方法四通过使用SQLDA结构代替宿主变量, 并通过调用DESCRIBE SELECT LIST或DESCRIBE BIND VARIABLES语句来检索选择列表项和结合变量(即宿主变量)描述信息, 从而使应用程序能够在运行时刻处理这种类型的动态SQL语句。 当SQLDA结构用于存列表信息项信息时, 它们被称做查询描述符; 当SQLDA结构用于存储结合变量信息时, 它们被称作结合描述符。 SQLDA结构的详细信息较长, 请参考相关书籍或手册。 这三种方法中前三种比较简单, 这里就不多说了, 方法四最为灵活, 功能最全, 但是也最为复杂. 使用方法共可分为以下18个步骤(请参考以下18个步骤去看例 程): ⑴. 在宿主变量声明区域声明字符串型宿主变量, 用它存储动态语句文本。 ⑵. 声明查询和结合描述符。 ⑶. 为查询和结合描述符分配内存空间; ⑷. 设置描述符能够最多描述的选择列表项和占位符数量; ⑸. 将动态语句文本拷贝到前面声明的宿主变量字符串中; ⑹. 调用PREPARE语句准备宿主变量字符串中的动态语句; ⑺. 为查询语句声明游标; ⑻. 描述结合变量,填充结合描述符; ⑼. 用DESCRIBE 语句所检索到的占位符实际数据(F)设置结合描述符中的占位符数据量, 即N元素; ⑽. 为DESCRIBE语句所检索到的结合变量分配内存, 并为各个结合变量提供数值; ⑾. 使用结合描述符打开游标; ⑿. 描述选择列表, 填充查询描述符; ⒀. 将查询描述符中的选择列表项数值设为DESCRIBE 语句所检索到的动态SQL语句中的实际选择列表项数; ⒁. 重新设置选择列有项的长度和数据类型; ⒂. 执行FETCH语句, 将数据库表中的数据提取到查询描述符所指向的数据缓冲区中; ⒃. 处理FETCH语句返回的选择列值; ⒄. 释放应用程序为选择列, 占位符, 指示符变量和描述符所申请的内存空 Oracle Pro*C 编程入门 5.2 ANSI方法 ANSI的方法如下: 5.2.1 使用ANSI方法的一些注意事项 Pro*C 应用程序的使用ANSI处理方法时, 必须将DYNAMIC 预编译选项值设置为 ANSI。 此外, 还需将TYPE_CODE选项设为ANSI。(这一点要十分注意, 因为这两 个选项不加会出现意想不到的错误,比如说: 如果不加TYPE_CODE, 程序一样可以 编译通过, 但是执行的结果却和你原来的的想法大相径庭) 5.2.2 ANSI方法和Oracle方法的不同 ANSI方法和Oracle方法相比有以下不同: ①. Oracle处理方法不支持对象类型, 游标变量, 结构数组, DML语句的RETURNING子句, 多字节字符变量 和LOB等,而ANSI处理方法支持所有的Oracle数据类型。 ②. ANSI处理方法所使用的描述符为C/C++结构变量, 它们由应用程序申请,释放和维护,而ANSI处理方法所使用的描述符则为SQL描述符, 它们由Oracle内部维护。 正是由于ANSI方法所使用的描述符是由Oracle内部维护, 所以ANSI方法比以上 方法四少了一些对于描述符的操作, 比如分配内存空间等。 5.2.3 ANSI处理方法对动态SQL语句的处理步骤 ANSI处理方法对动态SQL语句的处理步骤为: ⑴. 声明宿主变量, 包括动态SQL语句存储缓冲区; ⑵. 为输入,输出变量分配描述符; ⑶. 将动态语句文本拷贝到前面(1)中声明的宿主变量字符串中; ⑷. 调用PREPARE语句准备宿主变量字符串中的动态语句; #这一步实际上是对SQL语句进行语法分析, 检查 它所参照的数据库对象。 ⑸. 用DESCRIBE语句描述输入操作; #目的是读取动态SQL语句中的输入变量和输出变量等 描述信息,将它们存储到指定的输入描述符和输出描 述符中。 ⑹. 声明动态游标; ⑺. 用SET DESCRIPTOR 语句设置输出描述符; Oracle Pro*C 编程入门 ⑻. 打开游标; ⑼. 提取游标数据; ⑽. 处理所提取的游标数据; ⑾. 关闭游标; ⑿. 释放输入,输出描述符; 注意: 如果用ANSI方法处理非查询语句时, 就没必要申请输出描述符!以上所列的 步骤可根据各自的应用进行增删! 比如说, 像没有参数的delete, insert等语句的处理就可以简化为以下四步: a. 准备语句; b. 声明游标; c. 打开游标。 d. 关闭游标;
pro*c 动态sql
猜你喜欢
转载自m635674608.iteye.com/blog/1615624
今日推荐
周排行