簡介
本系列文章比較了 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 調用向返回的結果集中添加一個新行,在返回的結果集中,列值為結果集列名的當前值
SIGNALRESIGNAL
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 過程。