DB2 V9.5版本中數(shù)據(jù)庫(kù)應(yīng)用程序移植的改進(jìn)
• 支持在過(guò)程和調(diào)用過(guò)程的應(yīng)用程序中使用 ARRAY 數(shù)據(jù)類(lèi)型。
• 支持全局變量。全局變量是已命名的內(nèi)存變量,您可以通過(guò) SQL 語(yǔ)句訪問(wèn)和修改此變量。版本 9.5 支持已創(chuàng)建的會(huì)話(huà)全局變量,這些變量與特定會(huì)話(huà)相關(guān)聯(lián)并包含該會(huì)話(huà)獨(dú)有的值。
• 支持其他供應(yīng)商的 SQL 方言。版本 9.5 包含對(duì) DECODE、NVL、LEAST 和 GREATEST 函數(shù)的支持。
數(shù)組數(shù)據(jù)類(lèi)型
在以前的DB2版本,碰到數(shù)據(jù)集合處理的程序移植,我們只能通過(guò)臨時(shí)表或游標(biāo)來(lái)處理,這是非常麻煩的。
版本 9.5 支持 ARRAY 集合數(shù)據(jù)類(lèi)型。您可以在存儲(chǔ)過(guò)程和應(yīng)用程序中對(duì)它們進(jìn)行處理,此功能使從其他數(shù)據(jù)庫(kù)供應(yīng)商移植已支持?jǐn)?shù)組的應(yīng)用程序和存儲(chǔ)過(guò)程更容易。
您可以使用數(shù)組以在應(yīng)用程序與存儲(chǔ)過(guò)程之間更有效率地傳遞數(shù)據(jù)以及存儲(chǔ)和處理 SQL 過(guò)程中的瞬態(tài)數(shù)據(jù)集合,而不必使用關(guān)系表。SQL 過(guò)程中可用的數(shù)組運(yùn)算符允許更有效率地存儲(chǔ)和檢索數(shù)據(jù)。
版本 9.5 中對(duì)數(shù)組數(shù)據(jù)類(lèi)型的支持允許您執(zhí)行以下操作:
• 根據(jù)數(shù)組創(chuàng)建用戶(hù)定義的類(lèi)型;例如,CREATE TYPE INT10 AS INTEGER ARRAY[10] 定義最多 10 個(gè)整數(shù)值的數(shù)組的類(lèi)型;
• 在存儲(chǔ)過(guò)程和應(yīng)用程序中聲明數(shù)組類(lèi)型的變量和參數(shù);
• 創(chuàng)建和處理數(shù)組值,數(shù)組處理的基本部分包括數(shù)組構(gòu)造方法、設(shè)置子下標(biāo)、元素計(jì)數(shù)和整理;
• 在 JDBC 和 CLI 應(yīng)用程序與 SQL 和 Java 存儲(chǔ)過(guò)程之間來(lái)回傳遞數(shù)組;
• 將數(shù)組轉(zhuǎn)換為表(每個(gè)表行一個(gè)數(shù)組元素)以及將聚集列轉(zhuǎn)換為數(shù)組,以便更容易在數(shù)組與 SQL 之間通過(guò)接口進(jìn)行連接;
• 使用輸入和輸出數(shù)組參數(shù)從命令行處理器調(diào)用過(guò)程。
ARRAY 數(shù)據(jù)類(lèi)型定義:
CREATE TYPE type-name AS data-type ARRAY [integer-constant]
其中:data-type 不支持LONG VARCHAR, LONG VARGRAPHIC, LOB, XML類(lèi)型, integer-constant 最大值2147483647
與ARRAY相關(guān)的函數(shù):
ARRAY_AGG 將行數(shù)據(jù)集聚集成數(shù)組
UNNEST 將數(shù)組數(shù)據(jù)轉(zhuǎn)成行數(shù)據(jù)
CARDINALITY 返回?cái)?shù)組中的元素號(hào),類(lèi)型 BIGINT
MAX_CARDINALITY 返回?cái)?shù)組中所含的最大元素號(hào),類(lèi)型 BIGINT
注意,這些函數(shù)只用于SQL procedure
SELECT T.PHONE, T.ID, T.INDEX FROM UNNEST(PHONES, IDS)
WITH ORDINALITY AS T(PHONE, ID, INDEX)
ORDER BY T.INDEX
Example 1
這個(gè)例子包含2個(gè)存儲(chǔ)過(guò)程, sum 和 main. 存儲(chǔ)過(guò)程 main 建立一個(gè)含有6個(gè)元素(integer)的數(shù)組。傳遞這個(gè)數(shù)組給存儲(chǔ)過(guò)程sum, 計(jì)算出所有元素值的和并返回給調(diào)用存儲(chǔ)過(guò)程 main. 存儲(chǔ)過(guò)程 sum 說(shuō)明了array subindexing 和CARDINALITY 函數(shù)的用法.
create type intArray as integer array[100] @
create procedure sum(in numList intArray, out total integer)
begin
declare i, n integer;
set n = CARDINALITY(numList);
set i = 1;
set total = 0;
while (i < n) do
set total = total + numList[i];
set i = i + 1;
end while;
end @
create procedure main(out total integer)
begin
declare numList intArray;
set numList = ARRAY[1,2,3,4,5,6];
call sum(numList, total);
end @
Example 2
這個(gè)例子,我們使用2個(gè)數(shù)組類(lèi)型(intArray 和 stringArray),使用一個(gè)包含列(id 和 name)的 persons 表。 存儲(chǔ)過(guò)程 processPersons 添加3個(gè)人到 persons表, 并返回person名字的數(shù)組,按id排序,名字中包含字母 'o'。 3個(gè)persons 的 id 和 name 作為數(shù)組元素(ids 和 names)添加到數(shù)組中。這些數(shù)組使用UNNEST 函數(shù),將數(shù)組數(shù)據(jù)以包含2列數(shù)據(jù)的表的表達(dá)形式表達(dá),并插入到persons 表中。最后使用ARRAY_AGG函數(shù)將數(shù)據(jù)匯集返回給輸出參數(shù)。
create type intArray as integer array[100] @
create type stringArray as varchar(10) array[100] @
create table persons (id integer, name varchar(10)) @
insert into persons values(2, 'Tom') @
insert into persons values(4, 'Jill') @
insert into persons values(1, 'Joe') @
insert into persons values(3, 'Mary') @
create procedure processPersons(out witho stringArray)
begin
declare ids intArray;
declare names stringArray;
set ids = ARRAY[5,6,7];
set names = ARRAY['Bob', 'Ann', 'Sue'];
insert into persons(id, name) (select T.i, T.n from UNNEST(ids, names) as T(i, n));
set witho = (select array_agg(name order by id)
from persons
where name like '%o%');
end @
Example 3
這個(gè)例子說(shuō)明在java代碼中如何調(diào)用含有數(shù)組參數(shù)的存儲(chǔ)過(guò)程,本例子中存儲(chǔ)過(guò)程bonus_calculate含有2個(gè)輸入?yún)?shù),一個(gè)是數(shù)組projs,一個(gè)是整形percentage
………
String sql = 'CALL bonus_calculate(?, ?)';
CallableStatement callStmt = con.prepareCall(sql);
// Create an SQL Array
projects[0] = 'AD3111';
projects[1] = 'IF1000';
projects[2] = 'MA2111';
java.sql.Array projectArray=con.createArrayOf('VARCHAR',projects);
// set IN parameters
callStmt.setArray(1, projectArray);
callStmt.setInt(2,percentage);
// call the procedure
callStmt.execute();
…………
CREATE PROCEDURE bonus_calculate (IN projs projects, IN percentage integer)
BEGIN
DECLARE emp_array employees;
DECLARE bonus_array bonus;
SELECT cast(array_agg(employee.empno) AS employees),
cast(array_agg(.10*salary) AS bonus) INTO emp_array,bonus_array
FROM vempprojact, unnest(projs) AS P(id), employee
WHERE P.id=vempprojact.projno AND employee.empno=vempprojact.empno;
INSERT INTO bonus_temp
SELECT T.empno, T.bonus
FROM unnest(emp_array, bonus_array)
WITH ORDINALITY AS T(empno,bonus, idx);
END@
全局變量
在以前的DB2版本,碰到含全局變量處理的移植程序移植,我們只能通過(guò)全局臨時(shí)表來(lái)處理,使用起來(lái)非常麻煩。
全局變量改進(jìn)了 SQL 語(yǔ)句之間的數(shù)據(jù)共享。版本 9.5 引入了全局變量的概念,它們是命名的內(nèi)存變量,可以通過(guò) SQL 語(yǔ)句訪問(wèn)和修改這些變量。全局變量使您能夠在運(yùn)行于同一會(huì)話(huà)(或連接)的不同 SQL 語(yǔ)句之間共享數(shù)據(jù),而不需要應(yīng)用程序邏輯來(lái)支持此數(shù)據(jù)傳輸。
應(yīng)用程序不再需要發(fā)出這種語(yǔ)句來(lái)將值從一個(gè)語(yǔ)句的輸出自變量(如主機(jī)變量)復(fù)制到另一個(gè)語(yǔ)句的輸入自變量。此外,包含在數(shù)據(jù)庫(kù)系統(tǒng)本身中的 SQL 語(yǔ)句(如定義觸發(fā)器和視圖的語(yǔ)句)現(xiàn)在可以訪問(wèn)此共享信息。
全局變量有助于您為數(shù)據(jù)庫(kù)本身中的數(shù)據(jù)傳輸實(shí)現(xiàn)更復(fù)雜的交互式模型,以便您不必在應(yīng)用程序或 SQL 過(guò)程中放置支持邏輯。與全局變量相關(guān)聯(lián)的已定義特權(quán)確保所傳送數(shù)據(jù)的安全性不會(huì)升高到強(qiáng)制通過(guò)應(yīng)用程序邏輯。如果安全性存在問(wèn)題,那么您可以通過(guò) GRANT 和 REVOKE 語(yǔ)句來(lái)控制對(duì)全局變量的訪問(wèn)。
存儲(chǔ)靜態(tài)的、在會(huì)話(huà)期間很少更改的或者進(jìn)行了管理控制的數(shù)據(jù)時(shí),全局變量特別有用。用于將警報(bào)發(fā)送至 DBA 的尋呼機(jī)號(hào)以及指示是啟用還是禁用某些觸發(fā)器的指示器就是這種數(shù)據(jù)的示例。
版本 9.5 支持已創(chuàng)建的會(huì)話(huà)全局變量。會(huì)話(huà)全局變量與特定會(huì)話(huà)相關(guān)聯(lián)并包含該會(huì)話(huà)獨(dú)有的值。已創(chuàng)建的會(huì)話(huà)全局變量可用于任何正在您定義該變量的數(shù)據(jù)庫(kù)上運(yùn)行的活動(dòng) SQL 語(yǔ)句。系統(tǒng)目錄包含已創(chuàng)建的會(huì)話(huà)全局變量的定義以及與這些全局變量相關(guān)聯(lián)的特權(quán)。
例子:
創(chuàng)建全局變量:
CREATE VARIABLE myjob_current varchar (10) DEFAULT ('soft-engg');
獲取全局變量信息:
SELECT substr (varschema, 1, 10) as varschema,
substr (varname, 1, 10) AS varname,
varid, substr(owner,1,10) AS owner,
ownertype, create_time,
substr(typeschema,1,10) AS typeschema,
substr(typename,1,10) AS typename, length
FROM syscat.variables
WHERE varname = 'MYJOB_CURRENT';
給用戶(hù)praveen 和 sanjay 讀和寫(xiě)權(quán)限,剝奪用戶(hù)sanjay寫(xiě)權(quán)限:
GRANT READ, WRITE ON VARIABLE myjob_current TO USER praveen, USER sanjay;
REVOKE WRITE ON VARIABLE myjob_current FROM USER sanjay;
獲取用戶(hù) praveen 和 sanjay 的全局變量權(quán)限信息:
SELECT substr (varschema, 1, 10) AS schema,
substr (varname, 1, 10) AS name,
substr(grantor,1,10) AS grantor, grantortype AS Rtype,
substr(grantee,1,10) AS grantee, granteetype AS Etype,
readauth, writeauth
FROM syscat.variableauth
WHERE varname ='MYJOB_CURRENT'; ]
在觸發(fā)器中使用全局變量,本例是設(shè)計(jì)一個(gè)disable觸發(fā)器示例:
CREATE VARIABLE disable_trigger char (1) DEFAULT ('N');
CREATE TRIGGER validate_t BEFORE INSERT ON EMPLOYEE
REFERENCING NEW AS n FOR EACH ROW
WHEN (disable_trigger = 'N' AND n.empno > '10000')
SIGNAL SQLSTATE '38000'
SET message_text = 'EMPLOYEE NUMBER TOO BIG and INVALID';
SET disable_trigger = 'Y'; 使觸發(fā)器失效
簡(jiǎn)化用戶(hù)權(quán)限檢索:
CREATE VARIABLE schema1.gv_workdept CHAR
DEFAULT ((SELECT workdept FROM employee
WHERE firstnme = SESSION_USER));
CREATE VIEW schema1.emp_filtered AS
SELECT * FROM employee
WHERE workdept = schema1.gv_workdept;
在存儲(chǔ)過(guò)程,嵌入C,java程序中都可使用全局變量。
新的函數(shù)
新的函數(shù)簡(jiǎn)化了應(yīng)用程序移植,版本 9.5 包含一些與其他數(shù)據(jù)庫(kù)供應(yīng)商使用的標(biāo)量函數(shù)同名的新標(biāo)量函數(shù)。當(dāng)您將現(xiàn)有應(yīng)用程序移植到版本 9.5 中時(shí),您可以繼續(xù)使用其他供應(yīng)商使用的函數(shù)名稱(chēng),而無(wú)需更改代碼。
提供了以下新的標(biāo)量函數(shù):
• NVL(現(xiàn)有的 COALESCE 和 VALUE 函數(shù)的同義詞)
• LEAST 或 MIN(互為同義詞)
• GREATEST 或 MAX(互為同義詞)
• DECODE(類(lèi)似于現(xiàn)有的 CASE 表達(dá)式)
