程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> 比較 IBM DB2 和 IBM solidDB SQL 過程,第 1 部分: 比較結構、參數、變量、賦值、過程體、游標和動態 SQL 語句

比較 IBM DB2 和 IBM solidDB SQL 過程,第 1 部分: 比較結構、參數、變量、賦值、過程體、游標和動態 SQL 語句

編輯:DB2教程

簡介

本系列文章比較了 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. 賦值方法概述

DB2 solidDB 解釋 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 過程結構概述

DB2 solidDB 解釋 DECLARE <variable>

DEFAULT <value>

DECLARE <variable> DEFAULT 關鍵字在 solidDB 中不受支持 DECLARE <condition> 不支持 在 DB2 中,將一個描述性的名稱與錯誤代碼關聯 DECLARE <condition handler> 不受支持 在 solidDB 中,EXEC SQL WHENEVER 語句是最接近的對應語句 DECLARE CURSOR PREPARE CURSOR 聲明游標 SET SET or := 賦值語句 CASE IF CASE 在 solidDB 中不受支持 IF IF DB2 和 solidDB IF 語句是等效的 FOR (loop) 不受支持 類似於 PREPARE CURSOR 和 WHILE LOOP LOOP (loop) 不受支持 類似於 solidDB 中的 WHILE LOOP REPEAT (loop) 不受支持 類似於 solidDB 中的 WHILE LOOP WHILE (loop) WHILE LOOP 在 solidDB 中,WHILE 是唯一的循環結構 CALL CALL 調用方可以是一個應用程序或另一個過程 GOTO 不受支持 LEAVE 是 solidDB 中最接近的對應語句 ITERATE 不受支持   LEAVE(循環或復合塊) LEAVE (只用於 While loop) 在 solidDB 上,在保留最內層的 WHILE 循環後繼續執行 RETURN <integer> RETURN 在 DB2 中,用於退出過程並返回 0 或 -1 的返回狀態

在 solidDB 中,返回 OUT 和 RETURNS 參數的當前值,並退出過程

DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN 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. 游標處理概覽

DB2 solidDB 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. 使用游標獲取行

DB2 solidDB 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. 結合使用游標和插入

DB2 solidDB 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 過程

DB2 solidDB 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 過程。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved