WEB开发网
开发学院数据库DB2 比较 IBM DB2 和 IBM solidDB SQL 过程,第 1 部分... 阅读

比较 IBM DB2 和 IBM solidDB SQL 过程,第 1 部分: 比较结构、参数、变量、赋值、过程体、游标和动态 SQL 语句

 2009-07-23 16:14:19 来源:WEB开发网   
核心提示:简介本系列文章比较了 IBM DB2 9.5 SQL 过程语言(也称为 SQL PL)与 IBM solidDB 6.3 SQL 过程语言,DB2 和 solidDB 过程都经过一次编译和解析,比较 IBM DB2 和 IBM solidDB SQL 过程,第 1 部分: 比较结构、参数、变量、赋值、过程体、游标和动态

简介

本系列文章比较了 IBM DB2 9.5 SQL 过程语言(也称为 SQL PL)与 IBM solidDB 6.3 SQL 过程语言。DB2 和 solidDB 过程都经过一次编译和解析,然后存储到数据库中供日后执行。尽管这两种语言之间存在一定的相似性,但是也有一些比较显著的差别。

第 1 部分

SQL 过程的结构

参数和调用 SQL 过程

SQL 过程的变量和赋值

SQL 过程的过程体

SQL 过程的游标

动态 SQL 过程

第 2 部分

SQL 过程的条件语句

SQL 过程的循环语句

SQL 过程的错误处理

SQL 过程的返回结果集

有关 SQL 过程的其他内容

SQL 过程中的结构

本节介绍 DB2 和 solidDB SQL 过程在结构方面的差异。

DB2 SQL 过程的结构

DB2 SQL 过程的核心是一个复合语句(compound statement)。复合语句也称为复合块(compound block),所绑定的关键字为 BEGIN 和 END。清单 1 解释了 DB2 SQL 过程的结构化格式。

清单 1. DB2 SQL 过程的结构化格式

   
CREATE PROCEDURE procedure_name (parameters) 
LANGUAGE SQL 
BEGIN 
  Local variable declarations 
  Condition declarations            
  Cursor declarations               
  Condition handler declarations     
  Procedural body 
    Assignment, 
    flow of control, 
    looping 
    SQL statements 
    cursors 
    BEGIN 
    …           
    END 
  Other compound statements either nested or serially placed 
END 
  

SQL 过程可以包含一个或多个复合块。这些块可以被嵌套或顺序排列在 SQL 过程中。对于每一个块,对变量、条件和处理程序声明都有一个指定的顺序。这些声明必须位于 SQL 过程逻辑说明的前面。然而,游标可以在 SQL 过程体中的任何位置声明。

有两种类型的复合语句(块):原子性(atomic)和非原子性。

原子性复合语句可以看作是过程中的一个单个工作单元。如果该块中的任何语句失败,那么执行到该失败点的任何语句都将被认为是失败的,并且所有语句都将被执行回滚。换句话说,块中的语句要么全部成功,要不就全部失败。COMMIT、SAVEPOINT 和 ROLLBACK 语句是不允许的。这些语句只在非原子性 块中受支持。

非原子性语句块是默认的类型。即使块内的某个语句失败,其他语句可能会成功并被提交(或回滚),只要工作被显式提交(在过程内或过程所属的工作单元内)。

清单 2 展示了 ATOMIC 和 NOT ATOMIC 块的语法。

清单 2. 原子性和非原子性语句

   
BEGIN ATOMIC 
  … procedure code… 
END 
 
BEGIN NOT ATOMIC 
  …procedure code… 
END 
  

solidDB 过程的结构

和 DB2 过程一样,solidDB 过程也包含若干部分。包括参数部分、用于本地变量的声明部分和过程体部分。清单 3 展示了 solidDB 过程的格式。

清单 3. solidDB 过程的格式

   
"CREATE PROCEDURE procedure_name (parameter_section) 
BEGIN 
 declare_section_local_variables 
 procedure_body 
  assignment 
  flow of control 
  looping 
  cursor processing 
  error handling statements 
END"; 
  

您可以找出一些不同的地方。和 DB2 不同,solidDB 过程并没有包含多个复合语句块。相反,只在过程的开始和结束处包含了一对 BEGIN 和 END 关键字。

solidDB 过程需要将完整的定义部分放到一对双引号之中。

solidDB 过程中的事务可以在过程内部或过程外部提交或回滚。当 solidDB 过程返回到具有 autocommit on 的调用应用程序时(JDBC 或 ODBC),除非指定了回滚,否则将隐式地提交过程。

在过程内部,提交或回滚语句(以及所有其他 SQL 语句)的前面都要使用关键字 EXEC SQL。这与 DB2 SQL 过程不同,后者不需要在 SQL 语句前面使用 EXEC SQL 关键字。清单 4 展示了一个 solidDB 语法的示例。

清单 4. solidDB 语法要求使用 EXEC SQL

   
EXEC SQL COMMIT WORK; 
EXEC SQL ROLLBACK WORK; 
  

和 DB2 相同的是,可以在过程中的任意位置声明 游标,而本地变量必须声明部分中声明,声明部分在 BEGIN 之后过程逻辑之前。

参数和调用 SQL 过程

本节描述 DB2 和 solidDB SQL 过程在参数方面的不同之处。

DB2 过程的参数

参数用于将标量值传递给过程或从过程中传出。DB2 还可以以数组的方式将多组值作为单个参数传递。对于标量值,有三种类型的参数:IN、INOUT 和 OUT。清单 5 展示了一个使用所有三种类型的参数创建过程的示例。参数 p1、p2 和 p3 都各自被声明为 INTEGER(INT)。

清单 5. 使用不同 DB2 参数创建过程

   
CREATE PROCEDURE proc_name (IN p1 INT, INOUT p2 INT, OUT p3 INT) 
LANGUAGE SQL 
BEGIN 
 …. 
END@ 
  

除了 OUT 和 INOUT 参数外,DB2 还向调用程序返回结果集(包括多个行和多个列)。然而,结果集并不是使用 CREATE PROCEDURE 语句中的参数返回的。

solidDB 过程的参数

和 DB2 过程一样,solidDB 过程也有三种类型的参数:IN、OUT 和 INOUT。如果没有指定参数类型,那么默认情况下使用 IN 类型。清单 6 展示了使用 solidDB 语法的示例。

清单 6. 使用不同的 solidDB 参数创建过程

   
"CREATE PROCEDURE proc_name(p1 INTEGER = 8, OUT p3 INTEGER, INOUT p2 INTEGER) 
BEGIN 
… 
END" 
  

在过程内,输入和输出参数被作为逻辑变量处理。在参数列表中可以为 solidDB 参数指定一个默认值,如清单 6 所示。DB2 不支持在参数列表中初始化变量。

在调用为参数定义了默认值的过程时,不需要指定参数。比如,如果 proc_name 中的所有参数都指定了默认值,那么就可以使用 call proc_name; 调用命令。

您可以在调用过程时通过使用等号(=)为参数赋值,如清单 7 所示。

清单 7. 为参数赋值

   
call proc_name (p1 = 8, p2, p3); 
  

该命令将参数 p1 的值指定为 8,并为参数 p2 和 p3 指定默认值。如果参数名未在调用语句中使用,solidDB 将假设参数的顺序与 CREATE PROCEDURE 语句中的参数顺序一样。

在 solidDB 中返回值的另一种方法是通过 CREATE PROCEDURE 语句的 RETURNS 子句。RETURNS 子句一般情况下会返回一个结果集表,或者仅返回输出值。这种方法不同于 DB2 中返回结果集所使用的方法,本系列 第 2 部分 将对此加以描述。

SQL 过程的变量和赋值

本节描述 DB2 和 solidDB SQL 过程在变量和赋值方面的区别。

DB2 过程的变量和赋值

SQL 语句用于声明变量并为变量赋值。下面是一些与变量有关的语句类型:

DECLARE <variable_name datatype>

DECLARE <condition>

DECLARE <condition handler>

DECLARE CURSOR <cursor_name> FOR <SQL statement>

SET (assignment-statement)

DB2 过程中的本地变量使用 DECLARE 语句定义。此外,通过使用 DEFAULT 关键字和 DECLARE 语句,变量可以被初始化为默认值。DEFAULT 关键字在 solidDB 中不受 DECLARE 语句的支持。

通过 SET 语句执行赋值。

solidDB 过程中的变量和赋值

在 solidDB 中声明本地变量和赋值的语法与 DB2 相似:DECLARE <variable_name datatype> 。清单 8 展示了一个例子。

清单 8. 在 solidDB 上声明一个本地变量

   
"CREATE PROCEDURE …. (parameter list) 
BEGIN 
  DECLARE i INTEGER; 
  DECLARE dat DATE; 
END"; 
  

所有变量默认情况下被初始化为 NULL。要在 solidDB 中为变量赋值,可以使用 SET variable_name = expression;,或者可以使用 variable_name := expression;。清单 9 展示了一个例子。

清单 9. 在 solidDB 为变量赋值

   
SET i = i + 20; 
i := 100; 
  

表 1 展示了 DB2 中与 solidDB 对应的各种赋值方法。

表 1. 赋值方法概述

DB2solidDB解释
DECLARE v_total INTEGER DEFAULT 0; DECLARE v_total INTEGER; SET v_total = 0; or v_total := 0; DEFAULT 和 DECLARE 不受 solidDB 支持
SET v_total = v_total + 1; SET v_total = v_total + 1; or v_total := v_total + 1;  
SELECT MAX(salary) INTO v_max FROM employee; EXEC SQL c1 INTO (v_max) EXECDIRECT SELECT MAX(salary) FROM employee; EXEC SQL CLOSE c1; EXEC SQL DROP c1; 要映射到 solidDB 需要使用游标
VALUES CURRENT_DATE INTO v_date;SET v_date = {fn CURDATE()}; or v_date := CURDATE(); 对 solidDB 中标量函数调用的赋值可能需要 {fn…} 语法
SELECT CURRENT DATE INTO v_date FROM SYSIBM.SYSDUMMY1; SET v_date = {fn CURDATE()}; or v_date := {fn CURDATE()}; 伪表 sysibm.sysdummy1 在 solidDB 6.3 中不受支持
DELETE FROM T; GET DIAGNOSTICS v_rcount = ROW_COUNT; DELETE FROM T; SET v_rcount = SQLROWCOUNT; or v_rcount := SQLROWCOUNT; SQLROWCOUNT 是一个特殊变量

SQL 过程的过程体

本节介绍 DB2 和 solidDB SQL 过程体的结构差异。

DB2 SQL 过程体

SQL 过程支持以下类型的语句:

条件语句

循环语句

控制转移语句

错误管理语句

结果集操作语句

下面概述了程序体内支持的 SQL PL 语句:

条件语句:

CASE(有 2 中形式)

IF

循环语句:

FOR

LOOP

REPEAT

WHILE

控制转移语句:

CALL

GOTO

ITERATE

LEAVE

RETURN

错误管理语句:

SIGNAL

RESIGNAL

结果集操作语句:

ASSOCIATE LOCATOR(S)

ALLOCATE CURSOR

DB2 过程也支持在过程体内使用注释,注释使用两个短横线(--)标注。

solidDB 过程体

任何有效 SQL 语句,比如 CREATE TEMPORARY TABLE,都可用于 solidDB 存储过程内部,包括 DDL。CASE 语句是一个例外,因为它在过程中不受支持,但是在其他 solidDB 应用程序界面中受支持。

solidDB 过程使用的 SQL 结构类似于 DB2 过程中的 SQL 结构,包括使用两个短横线添加注释。表 2 展示了 DB2 SQL PL 语句与 solidDB 过程语句之间的映射。

表 2. SQL 过程结构概述

DB2solidDB解释
DECLARE <variable>

DEFAULT <value>

DECLARE <variable> DEFAULT 关键字在 solidDB 中不受支持
DECLARE <condition> 不支持在 DB2 中,将一个描述性的名称与错误代码关联
DECLARE <condition handler> 不受支持在 solidDB 中,EXEC SQL WHENEVER 语句是最接近的对应语句
DECLARE CURSORPREPARE CURSOR声明游标
SETSET or := 赋值语句
CASEIFCASE 在 solidDB 中不受支持
IFIFDB2 和 solidDB IF 语句是等效的
FOR (loop)不受支持类似于 PREPARE CURSOR 和 WHILE LOOP
LOOP (loop)不受支持类似于 solidDB 中的 WHILE LOOP
REPEAT (loop)不受支持类似于 solidDB 中的 WHILE LOOP
WHILE (loop)WHILE LOOP在 solidDB 中,WHILE 是唯一的循环结构
CALLCALL调用方可以是一个应用程序或另一个过程
GOTO不受支持LEAVE 是 solidDB 中最接近的对应语句
ITERATE不受支持 
LEAVE(循环或复合块)LEAVE (只用于 While loop)在 solidDB 上,在保留最内层的 WHILE 循环后继续执行
RETURN <integer>RETURN在 DB2 中,用于退出过程并返回 0 或 -1 的返回状态

在 solidDB 中,返回 OUT 和 RETURNS 参数的当前值,并退出过程

DECLARE EXIT HANDLER FOR SQLEXCEPTIONRETURN SQLERROR OF <cursor_name> 在 solidDB 中,将与游标有关的 SQLERROR 返回给调用者,然后退出过程
OPEN <cursor_name>RETURN ROW在 DB2 中,通过打开游标将行返回给应用程序,将结果集返回给调用者

在 solidDB 中,每个 RETURN ROW 调用向返回的结果集中添加一个新行,在返回的结果集中,列值为结果集列名的当前值

SIGNAL

RESIGNAL

RETURN SQLERROR <error string>在 solidDB 中,从过程返回一个用户定义的错误
ASSOCIATE LOCATOR(S)

ALLOCATE CURSOR

EXEC SQL PREPARE <cursor> CALL <procedure name>在 DB2 中,用于从 SQL 例程调用一个过程

在 solidDB 中,游标用于调用所需的过程,而 EXEC SQL FETCH <cursor> 用于接收结果

在 solidDB 过程中有两种方法可以执行 SQL:

EXECDIRECT 语法

游标语法

如果没有返回任何行,并且不需要使用变量作为参数,那么应当选用 EXECDIRECT 语法。例如,以下语句插入了一行数据:EXEC SQL EXECDIRECT INSERT INTO table1 (id, name) VALUES (1, 'Smith');

EXECDIRECT 语句还可以结合用于游标名。该语句使您能够准备并执行语句,而不需要使用单独的 PREPARE 语句。清单 10 展示了一个例子。

清单 10. 使用 EXECDIRECT 语句和游标名

   
EXEC SQL c1 USING (host_x) INTO (host_y) EXECDIRECT 
  SELECT y from foo where x = ?; 
EXEC SQL FETCH c1; 
EXEC SQL CLOSE c1; 
EXEC SQL DROP c1; 
  

在清单 10 中:

c1 是游标名

host_x 是一个变量,其值将代替 ?

host_y 是一个变量,列 y 的值将存储到这个变量中

同时注意,尽管不需要您准备游标,但您必须关闭和销毁它。

游标语法将 SQL 看作包含多个行、一个 PREPARE 语句和一个 EXECUTE 语句的结果。在 solidDB 中,在以下情况下使用游标:

处理返回多个行(SELECT)

需要使用作为参数提供的不同变量值,不断重复单个语句。其中包括 SELECT、UPDATE、INSERT 和 DELETE 语句。

SQL 过程的游标

本节描述 DB2 和 solidDB SQL 过程在使用游标方面的不同之处。

在 DB2 SQL 过程中使用游标

在一个 DB2 过程中,游标用于定义一个结果集并逐行执行逻辑。指针每次只能引用一个行,但是在需要时可以指向结果集中的其他行。要在 SQL 过程中使用游标,需完成下面的步骤:

声明一个游标,定义一个结果集。比如: DECLARE CURSOR cursor_name FOR < sql statement >;

打开游标来建立结果集。比如:OPEN cursor_name;

根据需要从游标中取出数据并放入到本地变量中,每次取出一个行。例如:FETCH FROM cursor_name INTO variable ;

完成后关闭游标。例如:CLOSE cursor_name ;

在 solidDB SQL 过程中使用游标

要使用游标返回多个行,需要执行以下步骤:

准备游标(定义)

执行游标(执行语句)

为选择过程调用获得游标(逐行取回结果)

使用完后关闭游标(仍然支持它重新执行)

从内存中销毁游标(删除它)

现在详细解释这些步骤。

使用 EXEC SQL PREPARE cursor_name SQL_statement; 准备游标

通过准备游标,分配内存空间以容纳语句的一行结果集,语句被解析并优化,如清单 11 所示。

清单 11. 准备游标的示例

    
EXEC SQL PREPARE sel_tables 
   SELECT table_name FROM sys_tables 
      WHERE table_name LIKE 'SYS%'; 
  

这个语句准备名为 sel_tables 的游标,但是它并没有执行它所包含的语句。

使用 EXEC SQL EXECUTE cursor_name USING (var1 [var2…]), [ INTO ( var1 [, var2...] ) ]; 执行游标

成功准备好一条语句后,就可以执行该语句。执行将可能的输入和输出变量绑定到该语句,然后返回实际的语句。

可选的 INTO 部分将语句的结果数据绑定到变量。INTO 关键字后的圆括号中列出的变量在运行 SELECT 或 CALL 语句时使用。SELECT 或 CALL 语句产生的结果列在执行语句时被绑定到这些变量。可选的 USING 子句将数据绑定到 SQL 语句,比如 WHERE 子句中的语句。清单 12 展示了一个执行语句。

清单 12. 包括执行语句的示例代码

    
EXEC SQL PREPARE sel_tables 
  SELECT table_name FROM sys_tables 
      WHERE table_name LIKE 'SYS%'; 
EXEC SQL EXECUTE sel_tables INTO (tab); 
  

语句现在被执行,产生的表名在后续的 Fetch 语句中被返回给变量 tab。

使用 EXEC SQL FETCH cursor_name; 获得游标

当 SELECT 或 CALL 语句被准备并执行时,它已经准备好获取。其他语句,比如 UPDATE、INSERT 和 DELETE,则不需要获取,因为不会产生结果集。

在执行语句时,示例命令从游标中获取单个行,放到与 INTO 关键字绑定在一起的变量中。

清单 13 展示了完整的示例代码。

清单 13. 包含获取语句的示例代码

    
EXEC SQL PREPARE sel_tables 
 SELECT table_name FROM sys_tables 
  WHERE table_name LIKE 'SYS%'; 
EXEC SQL EXECUTE sel_tables INTO (tab); 
EXEC SQL FETCH sel_tables; 
  

运行该示例后,变量 tab 包含找到的第一个满足 WHERE 子句的表的名称。获取游标 sel_tables 的后续调用获得后面的行。

要获取所有表名,使用了一个循环结构,如清单 14 所示。

清单 14. 循环结构示例

    
WHILE expression LOOP 
  EXEC SQL FETCH sel_tables; 
END LOOP 
        

使用 EXEC SQL CLOSE cursor_name; 关闭游标

关闭游标并不会从内存中删除实际的游标定义。可以在需要时再次运行。

使用 EXEC SQL DROP cursor_name; 销毁游标

可以从内存中销毁游标,这将释放所有资源。

表 3 比较了在获取行时的游标处理步骤。

表 3. 游标处理概览

DB2solidDB
DECLARE cursor_name CURSOR FOR < sql statement >; EXEC SQL PREPARE cursor_name SQL_statement ;
OPEN cursor_name;EXEC SQL EXECUTE cursor_name[ INTO

( var1 [, var2...] ) ];

FETCH FROM cursor_name INTO variable ; EXEC SQL FETCH cursor_name ;
CLOSE cursor_name ; EXEC SQL CLOSE cursor_name ;
 EXEC SQL DROP cursor_name ;

表 4 展示了 DB2 和 solidDB 如何使用游标获取行。

表 4. 使用游标获取行

DB2solidDB
CREATE PROCEDURE sum_salaries (OUT sum 
   INTEGER) 
 LANGUAGE SQL 
 BEGIN 
  DECLARE p_sum INTEGER; 
  DECLARE p_sal INTEGER; 
  DECLARE c CURSOR FOR SELECT SALARY 
      FROM EMPLOYEE; 
  DECLARE SQLSTATE CHAR(5) DEFAULT 
      ’00000’; 
  SET p_sum = 0; 
  OPEN c; 
  FETCH FROM c INTO p_sal; 
  WHILE(SQLSTATE = ’00000’) 
  DO 
    SET p_sum = p_sum + p_sal; 
    FETCH FROM c INTO p_sal; 
  END WHILE; 
  CLOSE c; 
  SET sum = p_sum; 
END@ 
  

“CREATE PROCEDURE sum_salaries (OUT sum 
      INTEGER) 
BEGIN 
  DECLARE p_sum INTEGER; 
  DECLARE p_sal INTEGER; 
  EXEC SQL PREPARE c  
    SELECT SALARY FROM EMPLOYEE; 
  p_sum := 0; 
  EXEC SQL EXECUTE c INTO (p_sal); 
  EXEC SQL FETCH c; 
  WHILE (SQLSUCCESS) LOOP 
     p_sum := p_sum + p_sal; 
     EXEC SQL FETCH c ; 
   END LOOP; 
   EXEC SQL CLOSE c; 
   EXEC SQL DROP c; 
   sum := p_sum; 
 END”;      
  

为了实现动态的游标,solidDB 在执行时使用参数标记来将值绑定到实际参数值。问号(?)被用做参数标记。清单 15 展示了一个例子。

清单 15. 使用参数标记的示例代码

   
EXEC SQL PREPARE sel_tabs 
   SELECT table_name FROM sys_tables 
    WHERE table_name LIKE ? AND table_schema LIKE ?; 
  

执行语句使用 USING 关键字将变量绑定到参数标记,例如 EXEC SQL EXECUTE sel_tabs USING ( var1, var2 ) INTO (tabs);

通过这种方法,单个游标可以被多次使用,而不需要重新准备游标。由于准备游标涉及解析和优化语句,因此通过使用可重用游标显著提升了性能。

只有 USING 列表接受变量;因此不能直接传递数据。例如,如果需要对表执行一个插入操作,其中表的某个列值应当始终为 status = 'NEW',那么该语句将出现错误: EXEC SQL EXECUTE ins_tab USING (nr, desc, dat, 'NEW');

正确的做法是在准备部分定义一个常量值,如清单 16 所示。

清单 16. 定义常量值

   
EXEC SQL PREPARE ins_tab 
 INSERT INTO my_tab (id, descript, in_date, status) 
       VALUES (?,?,?,'NEW'); 
EXEC SQL EXECUTE ins_tab USING (nr, desc, dat); 
  

如前所述,在 solidDB 过程中,只要 SQL 语句(比如 INSERT、UPDATE 或 DELETE)包含参数形式的变量,都应该使用游标处理语法。相比之下,DB2 中的变量不需要进行游标处理就可以作为参数使用。

表 5 展示了一个 DB2 过程示例,该过程被转换为一个使用插入和游标处理的 solidDB 过程。

表 5. 结合使用游标和插入

DB2solidDB
CREATE PROCEDURE p2 
LANGUAGE SQL 
BEGIN 
  DECLARE id INT; 
  CREATE TABLE table1 (id_col INT); 
  INSERT INTO table1 (id_col) VALUES(1); 
  SET id = 2; 
  INSERT INTO table1 (id_col) VALUES(id); 
  WHILE id <= 10 DO 
     INSERT INTO table1(id_col) 
       VALUES(id); 
     SET id = id + 1; 
  END WHILE; 
 END@   
  

"CREATE PROCEDURE p2 
 BEGIN 
   DECLARE id INT; 
   EXEC SQL EXECDIRECT create table 
       table1(id_col INT); 
   EXEC SQL EXECDIRECT insert into table1 
      (id_col) values (1); 
   EXEC SQL PREPARE cursor1 
      INSERT INTO table1 (id_col) 
         values (?); 
   id := 2; 
   WHILE id <= 10 LOOP 
     EXEC SQL EXECUTE cursor1 USING 
         (id); 
     id := id + 1; 
   END LOOP; 
   EXEC SQL CLOSE cursor1; 
   EXEC SQL DROP cursor1; 
END";

清单 17 展示了一个 solidDB 过程,它对 SELECT、UPDATE 或 INSERT 使用游标处理,并且游标指向 DELETE>。该过程将新数据行与现有数据行合并在一起。新的数据和现有数据根据 row_type 和 row_id 的键值进行匹配。当实现一个匹配后,将使用新的价格值更新现有价格值。接下来,从新的数据中删除匹配的行,这样只保留未匹配的行。未匹配的新行被插入到现有表中。

清单 17. solidDB UPDATE、INSERT 和 DELETE 处理

   
"CREATE PROCEDURE merge_rows RETURNS (new_rows INT, updated_rows INT) 
BEGIN 
 DECLARE v_row_type int; 
 DECLARE v_row_id int; 
 DECLARE v_price float; 
 
 new_rows := 0; 
 updated_rows := 0; 
 
 EXEC SQL PREPARE select_cursor 
 SELECT n.row_type , n.row_id , n.price 
   FROM new_rows n, old_rows o 
     WHERE n.row_type = o.row_type AND n.row_id = o.row_id;  
 EXEC SQL PREPARE update_cursor UPDATE old_rows SET price = ? WHERE row_type = ? 
              AND row_id = ?;  
        EXEC SQL EXECUTE select_cursor INTO ( v_row_type, v_row_id, v_price); 
        EXEC SQL FETCH select_cursor; 
        WHILE SQLSUCCESS LOOP 
 EXEC SQL EXECUTE update_cursor USING ( v_price ,v_row_type, v_row_id); 
 EXEC SQL EXECDIRECT DELETE FROM new_rows 
  WHERE CURRENT OF select_cursor;  
        updated_rows := updated_rows + 1; 
 EXEC SQL FETCH select_cursor; 
 END LOOP; 
    EXEC SQL CLOSE select_cursor; 
 EXEC SQL DROP select_cursor; 
            ….. 
 EXEC SQL PREPARE insert_cursor INSERT INTO old_rows (row_type , row_id , price) 
   (SELECT * FROM new_rows); 
    EXEC SQL EXECUTE insert_cursor; 
 new_rows := SQLROWCOUNT; 
 EXEC SQL CLOSE insert_cursor; 
           …. 
 EXEC SQL EXECDIRECT DROP TABLE new_rows; 
 EXEC SQL COMMIT WORK; 
END"; 
      

动态 SQL 过程

目前为止,本文已经比较了使用静态 SQL 编写的 DB2 SQL 过程和 solidDB 过程。如果使用静态 SQL 编写 DB2 过程,那么在运行过程之前要先准好好 SQL。准备好的 SQL 被作为编译 SQL 存储在数据库的包对象中。编译后的代码在运行时调用。

DB2 SQL 过程也可以使用动态 SQL 编写。当使用动态 SQL 时,将在调用过程中的语句时准备 SQL。表 6 比较了使用动态 SQL 编写的 solidDB 过程和 DB2 过程:

表 6. 比较 DB2 动态 SQL 和 solidDB 过程

DB2solidDB
CREATE PROCEDURE create_table 
    (IN new_name VARCHAR(10)) 
LANGUAGE SQL 
 BEGIN 
  DECLARE stmt VARCHAR(1000);   
  SET stmt = '';   
  SET stmt = 'CREATE TABLE '||new_name|| 
   '( empno CHAR(6) NOT NULL, '|| 
   'firstnme VARCHAR(12) NOT NULL, '|| 
   'midinit CHAR(1) NOT NULL, '|| 
   'lastname VARCHAR(15) NOT NULL )';   
  EXECUTE IMMEDIATE stmt;   
END@ 
  

“CREATE PROCEDURE create_table (IN new_name 
     VARCHAR(10)) 
BEGIN 
  DECLARE stmt VARCHAR(1000); 
  SET stmt = ‘’; 
  SET stmt = ‘CREATE TABLE ’ + new_name + 
    ‘(empno CHAR(6) NOT NULL,’ + 
    ‘firstnme VARCHAR(12) NOT NULL,’ + 
    ‘midinit CHAR(1) NOT NULL,’ + 
     ‘ lastname VARCHAR(15) NOT NULL)’; 
  EXEC SQL EXECDIRECT stmt;   
END”; 
COMMIT WORK; 
  

注意:solidDB 支持在 SELECT 列表中使用的连接操作符 ( || )。例如,SELECT ‘a' || ‘b', col1 FROM…

DB2 的 EXECUTE IMMEDIATE 语句在运行时准备并执行 SQL,并且它等效于 solidDB 的 EXECDIRECT 语句。DB2 也支持 PREPARE 和 EXECUTE 语句。通过使用独立的 PREPARE 和 EXECUTE 语句,可以只准备一次 SQL 语句,然后多次执行它。这消除了重复准备相同语句的开销。由于 solidDB 过程并不支持静态 SQL,因此 DB2 动态 SQL 过程与 solidDB 过程更加类似。

结束语

不管您目前学习的 SQL 过程是 DB2 还是 solidDB,您现在都拥有了学习另一种过程的好起点。阅读本系列的 第 2 部分 进一步学习 SQL 过程。

Tags:比较 IBM DB

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接