2009年12月4日 星期五

Bug has Fixed when using Merge Statement with Database Link - Oracle 10g


/*
先前已經測過 Merge 的語法透過 DB2 Federation 做更新是不可行的.
Oracle 的話要上patch,聽說11g已經沒有這個bug了

My Scenario:建兩個 Database 與 兩個 Table 分別如下:
  DB1: Orion  UserName:donkey   Table: Oriontb
  DB2: Odyssey UserName:voyager  Table: Odysseytb
測試使用傳統update語法與Merge Update
*/


/* 用User:voyager登進odyssey建立測試table與資料 */

create table odysseytb
(
  col1 integer not null primary key,
  col2 varchar2(32)
);
insert into odysseytb values (1,'1 from odysseytb');
insert into odysseytb values (2,'2 from odysseytb');
commit;

 
/* 用User:donkey登進orion建立database link及測試table與資料 */

create table oriontb
(
  col1 integer not null primary key,
  col2 varchar2(32)
);
insert into oriontb values (1,'1 from oriontb');
commit;

 

1. user donkey 已經由 grant create database link to donkey 而有權限 create database link
2. 使用 odyssey 資料庫 user voyager的 權限


create database link odyssey
connect to voyager
identified by voyager
using 'odyssey'

 
/* 測試連線是否成功 */

select * from odysseytb@odyssey;

   COL1 COL2
---------- --------------------------------
     1 1 from odysseytb
     2 2 from odysseytb

 
/* 測試傳統update語法,用oriontb去update odysseytb@odyssey  */

update (select oriontb.col1,oriontb.col2,
         t.col1 link_col1,t.col2 link_col2
    from oriontb,odysseytb@odyssey t
    where oriontb.col1 = t.col1) set link_col2 = col2

已更新 1 個資料列.

select * from odysseytb@odyssey;

   COL1 COL2
---------- ---------------------------------
     1 1 from oriontb
     2 2 from odysseytb

 
/* Rollback。範例資料還需再使用 */

/* 測試傳統update語法,用odysseytb@odyssey來update oriontb */

update (select oriontb.col1,oriontb.col2,
         t.col1 link_col1,t.col2 link_col2
    from oriontb,odysseytb@odyssey t
    where oriontb.col1 = t.col1) set col2 = link_col2;

已更新 1 個資料列.

select * from oriontb;

   COL1 COL2
---------- ----------------------------------
     1 1 from odysseytb


 
/* 測試 Merge Update 語法,結果得到以下錯誤 */


merge into oriontb using odysseytb@odyssey t on (oriontb.col1 = t.col1)
when matched then
update set oriontb.col2 = t.col2;


merge into oriontb using odysseytb@odyssey t on (oriontb.col1 = t.col1)
*
ERROR 在行 1:
ORA-02064: 不支援分散式作業

 
/* 測試 Merge Insert 語法,結果得到以下錯誤 */

merge into oriontb using odysseytb@odyssey t on (oriontb.col1 = t.col1)
when not matched then insert (oriontb.col1,oriontb.col2)
values (t.col1,t.col2);

merge into oriontb using odysseytb@odyssey t on (oriontb.col1 = t.col1)
*
ERROR 在行 1:
ORA-02064: 不支援分散式作業

2009年11月23日 星期一

CTE and RECURSIVE SQL Using SQL SERVER 2005 EXPRESS


/*
大概將近十年沒使用 SQL Server 開發系統了。
一直到最近有個新案子,它的後端需要使用SQL Server 2005 Express資料庫,我才有機會和動力去摸摸它。
‧SQL Server 2005 Express 與過去幾個版本一樣,非常容易上手,
‧它的oSQL(sqlcmd)功能還算強,但還是沒有像 DB2 與 Oracle 功能來得強大。
‧它的幾個extended stored procedures一樣好用(雖然有幾個因為安全性問題被移除,迂迴一下也可以做到)
‧OPENROWSET 等這類功能做得真好
‧終於有了 CTE 與 Recursive SQL 的語法,不過語法有追隨 DB2 的嫌疑。
 而且有多此一舉的感覺...LOG下來以免被我遺忘

Scenario: 使用 Recursive 產生日曆資料
*/

/* 建立測試 Table */

CREATE TABLE D_LIST
(
 DT VARCHAR(8)
)


/*
 使用CTE搭配Recursive SQL產生2009年日曆資料
 1.將MAXRECURSION 0表示不設限,否則會有以下錯誤
   Msg 530, Level 16, State 1, Line 1
   陳述式已結束。最大遞迴 100 已在陳述式完成之前用盡。
 2.INSERT 語法擺放的位置與 DB2 CTE 不同
*/


WITH N(DT)
AS
(SELECT '20090101'
UNION ALL
SELECT CONVERT(VARCHAR(8),DATEADD(D,1,CONVERT(DATETIME,DT,112)),112)
FROM N
WHERE CONVERT(VARCHAR(4),DATEADD(D,1,CONVERT(DATETIME,DT,112)),112) = '2009'
)
INSERT INTO D_LIST
SELECT * FROM N
OPTION (MAXRECURSION 0);

2009年10月29日 星期四

Show Part of Depenencies with SYSIBM.SYSDEPENDENCIES using DB2 Express-C 9.7


/*
SYSIBM.SYSDEPENDENCIES 可以來找出 Stored Procedure 使用了哪些 Tables.
但遇到 dynamic sql 當然就沒辦法這樣找了.
*/

-- 建立測試 Tables & 資料

CREATE TABLE A1
(
  COL1 INTEGER,
  COL2 VARCHAR(32)
) IN USERSPACE1;

CREATE TABLE F1
(
  COL1 INTEGER NOT NULL PRIMARY KEY,
  COL2 VARCHAR(32)
) IN USERSPACE1;

INSERT INTO A1 VALUES (10,'測試1'),(10,'測試2'),
             (10,'測試3'),(20,'測試4'),
             (20,'測試5'),(20,'測試6'),
             (30,'測試7'),(30,'測試8'),
             (30,'測試9'),(30,'測試10'),
             (30,'測試11');

INSERT INTO F1 VALUES (10,'代碼10'),
             (20,'代碼20'),
             (30,'代碼30');


-- 建立測試 Procedure

CREATE OR REPLACE PROCEDURE SP_TEST
SPECIFIC SP_TEST
LANGUAGE SQL
BEGIN
    IF EXISTS (SELECT 1 FROM A1
          WHERE COL1 NOT IN (SELECT COL1 FROM F1)) THEN
       INSERT INTO F1
       SELECT COL1,'代碼' || RTRIM(CHAR(COL1))
       FROM A1
       WHERE COL1 NOT IN (SELECT COL1 FROM F1);
    END IF;
END


-- 檢查關聯性

SELECT T.DNAME,A.BNAME
FROM SYSCAT.PACKAGEDEP A,
   (SELECT BNAME,DNAME FROM SYSIBM.SYSDEPENDENCIES
    WHERE DSCHEMA = 'ADMINISTRATOR'
    AND DNAME = 'SP_TEST') T
WHERE BTYPE = 'T' AND PKGNAME = T.BNAME;

DNAME               BNAME
------------------------------- -----------------
SP_TEST              F1
SP_TEST              A1

  已選取 2 個記錄。


-- 再建立另一測試 Procedure

CREATE OR REPLACE PROCEDURE SP_TEST2
SPECIFIC SP_TEST2
LANGUAGE SQL
BEGIN
  DECLARE SZSTR VARCHAR(1024);
  SET SZSTR = 'INSERT INTO A1 ' ||
         'SELECT COL1,''代碼'' ||
         RTRIM(CHAR(COL1)) ' ||
         'FROM (SELECT MAX(COL1) + 10 COL1 FROM A1) T';

  EXECUTE IMMEDIATE SZSTR;
END


-- 檢查關聯性,SP_TEST2 並未被 SELECT 出來

SELECT T.DNAME,A.BNAME
FROM SYSCAT.PACKAGEDEP A,
   (SELECT BNAME,DNAME FROM SYSIBM.SYSDEPENDENCIES
    WHERE DSCHEMA = 'ADMINISTRATOR'
   ) T
WHERE BTYPE = 'T' AND PKGNAME = T.BNAME;


DNAME               BNAME
------------------------------- -----------------
SP_TEST              F1
SP_TEST              A1

  已選取 2 個記錄。



-- 只好先用 Procedure 的程式內容來查

SELECT ROUTINENAME FROM SYSIBM.SYSROUTINES
WHERE ROUTINESCHEMA = 'ADMINISTRATOR'
AND TEXT LIKE '%A1%'

ROUTINENAME
------------------------------------------------
SP_TEST
SP_TEST2

已選取 2 個記錄。


-- 案子小也就算了,大案子就沒辦法這樣查了....

2009年10月13日 星期二

Test Thesaurus Expend Search using NSE9.7


/*
1. Net Search Extender 9.7 由於DB2 9.7在權限上更加的嚴謹,所以必須給定權限才能使用
2. 中文用同義詞辭典做 extend search 是 workable 的. 建立時的編碼要注意
*/


/* grant 權限 */
grant dbadm on database to db2admns

grant dataaccess on database to db2admns

/* 讓 NSE 對 Database ORION 做 text search */
db2text enable database for text connect to orion

/* 建立測試 Table 及資料 */


CREATE TABLE HEADLINE
(
  SNO INTEGER NOT NULL PRIMARY KEY,
  TXT VARCHAR(128)
);

INSERT INTO HEADLINE VALUES
(1,'首支西班牙F1車隊成立'),
(2,'西班牙車手Pedro de la Rosa很有可能加入Campos車隊'),
(3,'西班牙車手Fernando Alonso加入Ferrari車隊'),
(4,'西班牙將減少鬥牛場次'),
(5,'F1明年將禁用輪圈整流罩'),
(6,'薪資仲裁 小小郭籌碼大增'),
(7,'一級方程式賽車世界冠軍將可能於巴西站產生'),
(8,'兩屆世界冠軍阿隆索將加入法拉利車隊'),
(9,'Kalou signs new Chelsea contract'),
(10,'Spanish olive farmers hit by price falls')


/* 建立 index 在 headline 的 txt 欄位上 */
db2text create index headline_idx for text on headline(txt)

/* refresh index */
db2text update index headline_idx for text



/*
 建立同義詞辭典,存放在sqllib\db2ext\下,名稱給定為 nsesamplethes.def
 編碼須為UTF-8 否則在編譯時給定 -ccsid 1208之後中文查仍是有問題
*/


:WORDS
  阿隆索
 .RELATED_TO F1
 .RELATED_TO 一級方程式賽車
 .RELATED_TO 西班牙
 .SYNONYM_OF Fernando Alonso
 .SYNONYM_OF Alonso

:WORDS
  西班牙
 .SYNONYM_OF Spain
 .RELATED_TO Spanish


/* 編譯同義詞辭典 */
C:\Program Files\IBM\SQLLIB\db2ext>db2extth -f nsesamplethes.def -ccsid 1208 -t thes\

同義詞辭典編譯器
CTE0001 作業順利完成。

/* 以"阿隆索"做關聯字搜尋 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes" \
db2 (續) => => expand related term of "阿隆索"') > 0

SNO     TXT
----------- --------------------------------------------------
      1 首支西班牙F1車隊成立
      2 西班牙車手Pedro de la Rosa很有可能加入Campos車隊
      3 西班牙車手Fernando Alonso加入Ferrari車隊
      4 西班牙將減少鬥牛場次
      5 F1明年將禁用輪圈整流罩
      7 一級方程式賽車世界冠軍將可能於巴西站產生
      8 兩屆世界冠軍阿隆索將加入法拉利車隊

  已選取 7 個記錄。


/* 以"阿隆索"做同義字搜尋 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes" \
db2 (續) => => expand synonym term of "阿隆索"') > 0

SNO     TXT
----------- ---------------------------------------------------
      3 西班牙車手Fernando Alonso加入Ferrari車隊
      8 兩屆世界冠軍阿隆索將加入法拉利車隊

  已選取 2 個記錄。


/* 以"西班牙"做關聯字搜尋 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes" \
db2 (續) => => expand related term of "西班牙"') > 0

SNO     TXT
----------- ----------------------------------------------------
      1 首支西班牙F1車隊成立
      2 西班牙車手Pedro de la Rosa很有可能加入Campos車隊
      3 西班牙車手Fernando Alonso加入Ferrari車隊
      4 西班牙將減少鬥牛場次
      8 兩屆世界冠軍阿隆索將加入法拉利車隊
      10 Spanish olive farmers hit by price falls

  已選取 6 個記錄。


/* 以"西班牙"做同義字搜尋 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes" \
db2 (續) => => expand synonym term of "西班牙"') > 0

SNO     TXT
----------- ----------------------------------------------------
      1 首支西班牙F1車隊成立
      2 西班牙車手Pedro de la Rosa很有可能加入Campos車隊
      3 西班牙車手Fernando Alonso加入Ferrari車隊
      4 西班牙將減少鬥牛場次

已選取 4 個記錄。

2009年9月30日 星期三

Avoid from SQL20165N using DB2 9.7 Express-C


/*
想對刪除的資料同時做搬移,但是以下語法一直有錯

INSERT INTO TEST2
SELECT * FROM OLD TABLE
(DELETE FROM TEST WHERE COL1 = 'twn-2');

Server Msg: -20165, State: 428FL, [IBM][CLI Driver][DB2/NT]
SQL20165N 不容許 FROM 子句內的 SQL 資料變更陳述式位在指定它的環境定義中。
SQLSTATE=428FL

但是山不轉,路轉。如果我用 EXPORT/LOAD 呢?
*/

/* 建立測試 Tables & Data */

Create Table TEST
(
  COL1 CHAR(5),
  COL2 CHAR(2),
  COL3 CHAR(12)
) IN USERSPACE1

INSERT INTO TEST VALUES ('kor-1','dv','200706231040');
INSERT INTO TEST VALUES ('kor-1','dv','200706231045');
INSERT INTO TEST VALUES ('kor-1','dv','200706231050');
INSERT INTO TEST VALUES ('kor-1','cu','200706231055');
INSERT INTO TEST VALUES ('kor-1','cu','200706231055');
INSERT INTO TEST VALUES ('kor-1','rv','200706220450');
INSERT INTO TEST VALUES ('kor-1','rv','200706220450');
INSERT INTO TEST VALUES ('kor-1','rv','200706220450');
INSERT INTO TEST VALUES ('kor-1','rv','200706220453');
INSERT INTO TEST VALUES ('twn-2','dv','200706220454');

-- TEST2 存放從 TEST 刪掉的資料
CREATE TABLE TEST2 LIKE TEST IN USERSPACE1;


/* DML都失敗,改測 EXPORT/LOAD */


C:\>db2 declare cur cursor for select * from old table (delete from test where c
ol1 = 'twn-2')
DB20000I SQL 指令已順利完成。

C:\>db2 load from cur of cursor insert into test2
SQL3501W 由於禁止資料庫向前回復, 所以表格常駐的表格空間將不放入備份懸置狀態。

SQL1193I 公用程式正在開始從 SQL 陳述式 " select * from old table (delete from
test where col1 = 'twn-2')" 載入資料。

SQL3500W 公用程式在 "2009-09-30 15:52:19.926580" 時開始 "LOAD" 階段。

SQL3519W 開始載入「一致點」。輸入記錄數 = "0"。

SQL3520W 成功載入「一致點」。

SQL3110N 公用程式已完成處理。自輸入檔讀取第 "1" 列。

SQL3519W 開始載入「一致點」。輸入記錄數 = "1"。

SQL3520W 成功載入「一致點」。

SQL3515W 公用程式已在 "2009-09-30 15:52:20.295444" 時完成 "LOAD" 階段。


已讀取的列數        = 1
已略過的列數        = 0
已載入的列數        = 1
已拒絕的列數        = 0
已拒絕的列數        = 0
已確定的列數        = 1

/* 看一下資料是否 LOAD 到 TEST2 去 */

C:\>db2 select * from test2

COL1 COL2 COL3
----- ---- ------------
twn-2 dv 200706220454

  已選取 1 個記錄。

2009年9月21日 星期一

Autonomous transactions - DB2 9.7 Express-C


嗯?...這個在 Oracle 不是很早就有的嗎?
既然你出了,就意思意思玩一下

註:DB2 9.7還加了幾個 FUNCTIONs 像LAST_DAY,NEXT_DAY等,
  另外,終於可以用 CREATE OR REPLACE語法、
  也可以執行 Oracle PL/SQL。但Express-C版本沒辦法測...


/* 建立測試 table */

CREATE TABLE TEST
(
  COL1 INTEGER,
  COL2 VARCHAR(32)
) IN USERSPACE1;

CREATE TABLE AUTONOMOUS_TAB
(
  SYSDT TIMESTAMP,
  STEP_DESC VARCHAR(32)
) IN USERSPACE1;



/*
 建立測試 procedure sp_inslog 記錄 log
 採Autonomous方式
 在LANGUAGE SQL下方寫上 AUTONOMOUS,告訴 DB2 這支程式用自己的 Transaction
*/


create or replace procedure sp_inslog(in insz varchar(64))
specific sp_inslog
language sql
autonomous
begin
   insert into autonomous_tab
   values (current timestamp,insz);
   commit;
end


/*
 建立測試 procedure sp_proc1
 為一般procedure,裡面呼叫 sp_inslog執行寫log工作
*/


create or replace procedure sp_proc1
specific sp_proc1
language sql
begin
  DECLARE SQLCODE INTEGER DEFAULT 0;
  DECLARE retcode INTEGER DEFAULT 0;

  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION,
                   SQLWARNING,
                   NOT FOUND
  SET retcode = SQLCODE;

  insert into test values (0,'ETL開始日期'||char(current date));
  if (retcode <> 0) and (retcode <> 100) then
    rollback;
    call sp_inslog(char(retcode) || ' 流程0執行失敗');
  else
    call sp_inslog('流程0執行成功');
  end if;

  insert into test values (1,'ETL開始時間'||char(current date));

  IF (retcode <> 0) AND (retcode <> 100) THEN
    rollback;
    call sp_inslog(char(retcode) || ' 流程1執行失敗');
  else
    call sp_inslog('流程1執行成功');
  end if;
  commit;
end

/* 測試成功的狀況 */
C:\>db2 call sp_proc1

 傳回狀態 = 0

/* 看結果 */

C:\>db2 select * from test

COL1     COL2
----------- --------------------------------
      0 ETL開始日期2009-09-21
      1 ETL開始時間2009-09-21

  已選取 2 個記錄。

C:\>db2 select * from autonomous_tab

SYSDT             STEP_DESC
-------------------------- -------------
2009-09-21-17.02.38.141000 流程0執行成功
2009-09-21-17.02.38.201000 流程1執行成功

  已選取 2 個記錄。


/*
 直接改一下 procedure sp_proc1 讓它在執行新增第二次test時失敗
*/


create or replace procedure sp_proc1
specific sp_proc1
language sql
begin
   DECLARE SQLCODE INTEGER DEFAULT 0;
   DECLARE retcode INTEGER DEFAULT 0;

   DECLARE CONTINUE HANDLER FOR SQLEXCEPTION,
                    SQLWARNING,
                    NOT FOUND
   SET retcode = SQLCODE;

   insert into test values (0,'ETL開始日期'||char(current date));
   if (retcode <> 0) and (retcode <> 100) then
      rollback;
      call sp_inslog(char(retcode) || ' 流程0執行失敗');
   else
      call sp_inslog('流程0執行成功');
   end if;

   insert into test values (1,'倉儲系統ETL開始時間'||
                  char(current timestamp));

   IF (retcode <> 0) AND (retcode <> 100) THEN
      rollback;
      call sp_inslog(char(retcode) || ' 流程1執行失敗');
   else
      call sp_inslog('流程1執行成功');
   end if;
   commit;
end

/* 測試失敗的狀況 */
C:\>db2 call sp_proc1

 傳回狀態 = 0


C:\>db2 select * from test

COL1     COL2
----------- --------------------------------

  已選取 0 個記錄。


/* autonomous_tab第一筆資料未隨著外面那層 procedure的rollback而跟著rollback */


C:\>db2 select * from autonomous_tab

SYSDT             STEP_DESC
-------------------------- --------------------------
2009-09-21-17.39.45.593000 流程0執行成功
2009-09-21-17.39.45.614000 -433 流程1執行失敗

已選取 2 個記錄。

2009年9月2日 星期三

Performance of Merge statement using DB2 Express-C 9.7


/*
Update 的語法在 Performance tuning 上被我奉為萬靈丹的 Merge
原來也有不能勝出的時候。

My Scenario:
Table t: col1 以日期帶序號為單號。 Ex:20090903001
Table t1: col1 以單號帶項次。   Ex:2009090300101
                    2009090300102
                    2009090300103
                    2009090300104
                    2009090300105
join 條件: t.col1 = substr(t1.col1,1,11),將 t 的其它欄位值更新至 t1
Merge 語法的效能就差到不行,反而是 Update 的效能超快
*/

/* 建立測試 table t 並新增資料 */

create table t
(
  col1 char(11),
  col2 char(8)
) in userspace1;

INSERT INTO T
WITH N (COL0,COL1,COL2) AS (
SELECT 1 COL0,SUBSTR(CHAR(INT(DATE(SYSDATE))),1,8) ||
        SUBSTR(CHAR_OLD(DECIMAL(1,3,0)),1,3),
        CHAR(INT(DATE(SYSDATE)))
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT N.COL0 + 1,SUBSTR(CHAR(INT(DATE(SYSDATE))),1,8) ||
          SUBSTR(CHAR_OLD(DECIMAL(N.COL0 + 1,3,0)),1,3),
          N.COL2
FROM N
WHERE N.COL0 + 1 <= 100)
SELECT COL1,COL2 FROM N;


/* 建立測試 table t1 並新增資料 */

create table t1
(
  col1 char(13),
  col2 char(8)
) in userspace1;

INSERT INTO T1(COL1)
WITH N (COL0,COL1,OCOL1) AS (
SELECT 1 COL0,COL1 || SUBSTR(CHAR_OLD(DECIMAL(1,2,0)),1,2),
     COL1 OCOL1
FROM  T
WHERE MOD(INT(RIGHT(COL1,2)),2) = 0
UNION ALL
SELECT N.COL0 + 1,RTRIM(N.OCOL1) ||
          SUBSTR(CHAR_OLD(DECIMAL(N.COL0 + 1,2,0)),1,2),
          N.OCOL1
FROM N
WHERE N.COL0 + 1 <= 5)
SELECT COL1 FROM N ORDER BY COL1;

/* 將 merge 語法存入 merge.sql */

merge into t1 using t on t.col1 = substr(t1.col1,1,11)
when matched then
update set t1.col2 = t.col2

/* 將 update 語法存入 update.sql */

update t1 set col2 = (select t.col2
             from t where t.col1 = substr(t1.col1,1,11))

/* 執行 db2expln 看 merge 的表現 */
C:\>db2expln -database ORION -g -stmtfile merge.sql -o merge.log

/* 開啟 merge.log */
C:\>notepad merge.log


Statement:
 merge into t1 using t on t.col1 =substr(t1.col1, 1, 11)
 when matched
 then
 update set t1.col2 =t.col2

Section Code Page = 1208
Estimated Cost = 3692.811523
Estimated Cardinality = 240.000000

Access Table Name = ADMINISTRATOR.T ID = 2,9479
| #Columns = 2
| Skip Inserted Rows
| Avoid Locking Committed Data
| Currently Committed for Cursor Stability
| May participate in Scan Sharing structures
| Scan may start anywhere and wrap, for completion
| Scan can be throttled in scan sharing management
| Relation Scan
| | Prefetch: Eligible
| Lock Intents
| | Table: Intent Share
| | Row : Next Key Share
Left Outer Nested Loop Join
| Access Table Name = ADMINISTRATOR.T1 ID = 2,9480
| | #Columns = 0
| | Skip Inserted Rows
| | Evaluate Block/Data Predicates Before Locking Committed Row
| | May participate in Scan Sharing structures
| | Fast scan, for purposes of scan sharing management
| | Relation Scan
| | | Prefetch: Eligible
| | Isolation Level: Read Stability
| | Lock Intents
| | | Table: Intent Exclusive
| | | Row : Update
| | Sargable Predicate(s)
| | | #Predicates = 1

Insert Into Sorted Temp Table ID = t1
| #Columns = 3
| #Sort Key Columns = 1
| | Key 1: (Ascending)
| Sortheap Allocation Parameters:
| | #Rows   = 250.000000
| | Row Width = 28
| Piped
Access Temp Table ID = t1
| #Columns = 3
| Relation Scan
| | Prefetch: Eligible
Residual Predicate(s)
| #Predicates = 4
Residual Predicate(s)
| #Predicates = 1
Establish Row Position
| Access Table Name = ADMINISTRATOR.T1 ID = 2,9480
Update: Table Name = ADMINISTRATOR.T1 ID = 2,9480
| Update Predicate(s)
| | #Predicates = 1
End of section

Optimizer Plan:
                  Rows
                 Operator
                  (ID)
                  Cost
                  240
                 UPDATE
                  ( 2)
                 3692.81
               /--/     \
            240         250
           FETCH        Table:
           ( 3)        ADMINISTRATOR
          1877.31        T1
          /   \
        240    250
       FILTER   Table:
       ( 4)    ADMINISTRATOR
      61.6852    T1
        |
       250
      FILTER
      ( 5)
      61.6458
        |
       250
      TBSCAN
      ( 6)
      61.2642
        |
       250
      SORT
      ( 7)
      61.2416
        |
       250
      NLJOIN
      ( 8)
      61.1053
     /    \---\
   100       *
   TBSCAN      |
   ( 9)      250
   15.2041    Table:
    |       ADMINISTRATOR
    100      T1
 Table:
 ADMINISTRATOR
 T

/* 執行 db2expln 看 update 的表現 */
C:\>db2expln -database ORION -g -stmtfile update.sql -o update.log

/* 開啟 update.log */
C:\>notepad update.log


Statement:
 update t1 set col2 =
   (select t.col2
   from t
   where t.col1 =substr(t1.col1, 1, 11))

Section Code Page = 1208
Estimated Cost = 1952.518555
Estimated Cardinality = 250.000000

Access Table Name = ADMINISTRATOR.T1 ID = 2,9480
| #Columns = 1
| Skip Inserted Rows
| May participate in Scan Sharing structures
| Relation Scan
| | Prefetch: Eligible
| Lock Intents
| | Table: Intent Exclusive
| | Row : Exclusive

Nested Loop Join
| Piped Inner
| Access Table Name = ADMINISTRATOR.T ID = 2,9479
| | #Columns = 1
| | Skip Inserted Rows
| | Avoid Locking Committed Data
| | Currently Committed for Cursor Stability
| | May participate in Scan Sharing structures
| | Scan may start anywhere and wrap, for completion
| | Fast scan, for purposes of scan sharing management
| | Scan can be throttled in scan sharing management
| | Relation Scan
| | | Prefetch: Eligible
| | Lock Intents
| | | Table: Intent Share
| | | Row : Next Key Share
| | Sargable Predicate(s)
| | | #Predicates = 1
Update: Table Name = ADMINISTRATOR.T1 ID = 2,9480
End of section

Optimizer Plan:
              Rows
             Operator
              (ID)
              Cost
              250
             UPDATE
              ( 2)
             1952.52
           /--/    \
        250        250
       NLJOIN      Table:
        ( 3)      ADMINISTRATOR
       61.3672     T1
      /    \
    250      1
   TBSCAN     TBSCAN
   ( 4)      ( 5)
   22.8603    15.2357
    |        |
   250       100
 Table:       Table:
 ADMINISTRATOR   ADMINISTRATOR
 T1         T



Merge 的 Estimated Cost = 3692.811523
Update 的 Estimated Cost = 1952.518555

Limitation of Using Merge in DB2 using DB2 Express-C 9.7


Merge Update 有一定的限制,例如想更新的 Table 是個 Nickname 就不行
My Scenario:
Database1: Taurus 建立 Table b1
Database2: Orion 建立 Table a1
         建立 Nickname b1 federated from Taurus

在 Database Orion 對 b1 以 Merge 方式將 a1 的值更新到 b1,則會產生錯誤
SQL0270N 不支援函數 (原因碼 = "67")。 SQLSTATE=42997

67  請勿在 MERGE 陳述式中,指定暱稱或暱稱的視圖作為目標。


My Solutions:
1. 能以傳統Update的語法做更新
2. 在 Database Taurus 上建立 nickname a1,在 Taurus 對 b1 做 merge 語法更新之。

※ 無法藉由 Wrapper Server 增加參數 DB2_TWO_PHASE_COMMIT = 'Y' 來達到目的。


/* 建立測試環境 */

C:\>db2 connect to orion

資料庫連線資訊

資料庫伺服器 = DB2/NT 9.7.0
SQL 授權 ID = ADMINIST...
本端資料庫別名 = ORION

C:\>db2 create table a1 ( col1 integer,col2 varchar(16)) in userspace1
DB20000I SQL 指令已順利完成。

C:\>db2 insert into a1 values (1,'TESTING'),(2,'PRODUCTION')
DB20000I SQL 指令已順利完成。

C:\>db2 terminate
DB20000I TERMINATE 指令已順利完成。

C:\>db2 connect to taurus

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID      = ADMINIST...
 本端資料庫別名     = TAURUS

C:\>db2 create table b1 ( col1 integer,col2 varchar(16)) in userspace1
DB20000I SQL 指令已順利完成。

C:\>db2 insert into b1(col1) values (1),(2)
DB20000I SQL 指令已順利完成。

C:\>db2 terminate
DB20000I TERMINATE 指令已順利完成。


/* 建立對應Nickname */

C:\>db2 connect to orion

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID      = ADMINIST...
 本端資料庫別名     = ORION

C:\>db2 create nickname administrator.b1 for w2taurus.administrator.b1
DB20000I SQL 指令已順利完成。

 
/* 在 Orion Database 上對 Nickname 做 Merge Update */

C:\>db2 merge into b1 using a1 on a1.col1 = b1.col1 when matched then update set
b1.col2 = a1.col2

 
/* 產生錯誤訊息 */

DB21034E 指令被當作 SQL 陳述式處理,因為它不是有效的「指令行處理器」指令。 在 SQL 處理程序期間,它已傳回:
SQL0270N 不支援函數 (原因碼 = "67")。 SQLSTATE=42997

/* 不信邪,想試試 Two phase commit */

C:\>db2 connect to orion

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID      = ADMINIST...
 本端資料庫別名     = ORION

C:\>db2 alter server w2taurus options (add DB2_TWO_PHASE_COMMIT 'Y')
DB20000I SQL 指令已順利完成。

 
/* 依舊失敗 */

C:\>db2 merge into b1 using a1 on a1.col1 = b1.col1 when matched then update set
b1.col2 = a1.col2

DB21034E 指令被當作 SQL 陳述式處理,因為它不是有效的「指令行處理器」指令。 在SQL 處理程序期間,它已傳回:
SQL0270N 不支援函數 (原因碼 = "67")。 SQLSTATE=42997

 
/* 再建在 Taurus 上試試 */

C:\>db2 connect to taurus

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID      = ADMINIST...
 本端資料庫別名     = TAURUS

C:\>db2 alter server w2orion options(add DB2_TWO_PHASE_COMMIT 'Y')
DB20000I SQL 指令已順利完成。


/* 回到 Database Orion 再試 */

C:\>db2 connect to orion

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID      = ADMINIST...
 本端資料庫別名     = ORION

C:\>db2 merge into b1 using a1 on a1.col1 = b1.col1 when matched then update set
b1.col2 = a1.col2
DB21034E 指令被當作 SQL 陳述式處理,因為它不是有效的「指令行處理器」指令。 在SQL 處理程序期間,它已傳回:
SQL0270N 不支援函數 (原因碼 = "67")。 SQLSTATE=42997

2009年8月17日 星期一

Char_Old function (Leading zeroes and a trailing decimal characters) - DB2 Express-C 9.7


/*
  Char function 是我在 DB2 8.2 算是很喜歡的 function
  一直到今天,我用 DB2 Express-C 9.7 來做資料分析時,
  才發現它已經沒有原來我想用來補零的功能...
  要改用 char_old function
*/



C:\>db2 select decimal(200,5,0) from sysibm.sysdummy1

1
-------
  200.

  已選取 1 個記錄。

 

/* 掐頭去尾的 char function */

C:\>db2 select char(decimal(200,5,0)) from sysibm.sysdummy1

1
-------
200

  已選取 1 個記錄。


/* 使用 char_old */

C:\>db2 select char_old(decimal(200,5,0)) from sysibm.sysdummy1

1
-------
00200.

  已選取 1 個記錄。

2009年8月5日 星期三

DB2 Express-C 9.7 GUI Chinese characters does not show properly


/*
  DB2 Express-C 9.7安裝後 GUI 的 menu 字體成了亂碼
  本來以為會是\IBM\SQLLIB\java\jdk\jre\lib下的fontconfig.properties.src有關
  結果,內容被我改得面目全非卻還是不見效...
  沒想到原來解法是這麼簡單
*/


/* 
 控制中心等GUI字體設定


 Reference: IBM DB2 控制中心等圖形工具在 Windows 下的字體設置
 http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0703caojx/


 點選「工具設定」後,選擇「字型」,接著
 將「功能表(M)」的字型下拉式選單設為對話,
 關閉控制中心,接著再開起即可
*/





/* 
 配置輔助程式GUI中文字體無法正常顯示


 Reference:IZ01055: DB2 MESSAGE WINDOW DOES NOT SHOW SOME OF THE
      CHINESE CHARACTERS PROPERLY
      WHEN CONFIGURATION ASSISTANT IS OPENED AS 'DB2CA'.
 http://www-01.ibm.com/support/docview.wss?uid=swg1IZ01055

 把\IBM\SQLLIB\bin\下的db2ca.bat先做個備份,接著再用以下內容取代即可

*/



set RUNTIME_FLAGS=-Xmx128m -Xms8m -Xquickstart -Xgcpolicy:optavgpause

IF "%1" == "wait" GOTO WAIT
IF "%1" == "-ic" GOTO WSWB
 db2javit -j:CC -s: -i: -l: -o:"%RUNTIME_FLAGS%" -a:"-ca %2 %3 %4 %5 %6 %7 %8"
 GOTO END

:WAIT
 db2javit -j:CC -s: -w: -i: -l: -o:"%RUNTIME_FLAGS%" -a:"-ca %3 %4 %5 %6 %7 %8 %9"
 GOTO END

:WSWB
 db2icdocs.exe
 GOTO END

:end

2009年8月4日 星期二

Grant Load authority using DB2 Express-C 9.7


/*
  好不容易終於拿到 DB2 Express-C 9.7
  灌好之後才發現原來它是這麼令人陌生...(是我假放太久了嗎?)
  一是控制中心的選單字體全成了亂碼,二是權限異動頗大
  到現在還是搞不清楚。不過先把弄出來的做一下紀錄...

  在什麼都沒設定之下執行 load,就會有以下錯誤:
  SQL0552N "ADMINISTRATOR" 沒有執行作業 "LOAD" 的專用權。 SQLSTATE=42502

  原來 LOAD 權限已經不再是預設就有的,因此權限設定上還真麻煩,
  特別是我只是單純用本機的 Administrator 去做測試
*/


/* 檢查本機使用者和群組設定 */

「開始」→「程式集」→「系統管理工具」→「電腦管理」
展開「系統工具」接著再展開「本機使用者和群組」
點選「群組」。檢查是否存在名稱為 DB2ADMNS 的群組。
再點選「使用者」。將 Administrator 「成員隸屬」的選單新增DB2ADMNS群組。


/* 建自己的 DB */

不使用「DB2安裝」所建立的DB:SAMPLE,原因是,
我還沒Try出來到底怎麼使Administrator有執行grant的專用權。
另外我也還沒辦法用localsystem account去logon。

如果我要Administrator有SECADM (Manages security within a database)的權限,
目前所能做的就是使 Administrator 成為 db 的 creator。


C:\>db2start
SQL1063N DB2START 處理成功。

C:\>db2 create database orion
DB20000I CREATE DATABASE 指令已順利完成。


C:\>db2 connect to orion

  資料庫連線資訊

 資料庫伺服器      = DB2/NT 9.7.0
 SQL 授權 ID       = ADMINIST...
 本端資料庫別名     = ORION


/* 檢查有哪些權限 */
C:\>db2 get authorizations



  現行使用者的管理權限

 直接 SYSADM 權限       = NO
 直接 SYSCTRL 權限       = NO
 直接 SYSMAINT 權限      = NO
 直接 DBADM 權限        = YES
 直接 CREATETAB 權限      = NO
 直接 BINDADD 權限       = NO
 直接 CONNECT 權限       = NO
 直接 CREATE_NOT_FENC 權限  = NO
 直接 IMPLICIT_SCHEMA 權限   = NO
 直接 LOAD 權限         = NO
 直接 QUIESCE_CONNECT 權限    = NO
 直接 CREATE_EXTERNAL_ROUTINE 權限 = NO
 直接 SYSMON 權限          = NO

 間接 SYSADM 權限        = NO
 間接 SYSCTRL 權限        = YES
 間接 SYSMAINT 權限       = YES
 間接 DBADM 權限        = NO
 間接 CREATETAB 權限      = YES
 間接 BINDADD 權限       = YES
 間接 CONNECT 權限       = YES
 間接 CREATE_NOT_FENC 權限   = NO
 間接 IMPLICIT_SCHEMA 權限   = YES
 間接 LOAD 權限         = NO
 間接 QUIESCE_CONNECT 權限   = NO
 間接 CREATE_EXTERNAL_ROUTINE 權限 = NO
 間接 SYSMON 權限          = YES


/* 自己不能grant自己 */
C:\>db2 grant load on database to administrator
DB21034E 指令被當作 SQL 陳述式處理,因為它不是有效的「指令行處理器」指令。
在SQL 處理程序期間,它已傳回:
SQL0554N 授權 ID 無法授與自身專用權或權限。 SQLSTATE=42502

/* grant權限給群組 */

C:\>db2 grant load on database to db2admns
DB20000I SQL 指令已順利完成。

C:\>db2 create table t1 (c1 integer)
DB20000I SQL 指令已順利完成。

/* 再檢查一下權限 */

C:\>db2 get authorizations

  現行使用者的管理權限

 直接 SYSADM 權限       = NO
 直接 SYSCTRL 權限       = NO
 直接 SYSMAINT 權限      = NO
 直接 DBADM 權限        = YES
 直接 CREATETAB 權限      = NO
 直接 BINDADD 權限       = NO
 直接 CONNECT 權限       = NO
 直接 CREATE_NOT_FENC 權限  = NO
 直接 IMPLICIT_SCHEMA 權限   = NO
 直接 LOAD 權限         = NO
 直接 QUIESCE_CONNECT 權限    = NO
 直接 CREATE_EXTERNAL_ROUTINE 權限 = NO
 直接 SYSMON 權限          = NO

 間接 SYSADM 權限        = NO
 間接 SYSCTRL 權限       = YES
 間接 SYSMAINT 權限      = YES
 間接 DBADM 權限        = NO
 間接 CREATETAB 權限     = YES
 間接 BINDADD 權限      = YES
 間接 CONNECT 權限       = YES
 間接 CREATE_NOT_FENC 權限   = NO
 間接 IMPLICIT_SCHEMA 權限   = YES

 間接 LOAD 權限          = YES

 間接 QUIESCE_CONNECT 權限     = NO
 間接 CREATE_EXTERNAL_ROUTINE 權限 = NO
 間接 SYSMON 權限          = YES


/* 測試load */

C:\>db2 load from t1.del of del insert into t1
SQL3501W 由於禁止資料庫向前回復, 所以表格常駐的表格空間將不放入備份懸置狀態。

SQL3109N 公用程式開始自檔案 "C:\t1.del" 載入資料。

SQL3500W 公用程式在 "2009-08-04 20:27:16.489660" 時開始 "LOAD" 階段。

SQL3519W 開始載入「一致點」。輸入記錄數 = "0"。

SQL3520W 成功載入「一致點」。

SQL3110N 公用程式已完成處理。自輸入檔讀取第 "1" 列。

SQL3519W 開始載入「一致點」。輸入記錄數 = "1"。

SQL3520W 成功載入「一致點」。

SQL3515W 公用程式已在 "2009-08-04 20:27:16.700221" 時完成 "LOAD" 階段。

已讀取的列數        = 1
已略過的列數        = 0
已載入的列數        = 1
已拒絕的列數        = 0
已拒絕的列數        = 0
已確定的列數        = 1

2009年7月2日 星期四

Use Least function - Oracle 10g


/*
  Scenario:
  User 說,正常的情況下Column A 的值要>= Column B 且
             Column B 的值要>= Column C 且
             Column C 的值要>= Column D
  User 要找出不正常的資料。

  My solution: 使用Least Function
  Least((A-B),(B-C),(C-D)) < 0
*/

/* 建立測試Table&資料 */


create table test
(
  col_id varchar2(5),
  col_a integer,
  col_b integer,
  col_c integer,
  col_d integer
);

SQL> insert into test values ('00001',4,3,2,1);
已建立 1 個資料列.
SQL> insert into test values ('00002',9,1,2,5);
已建立 1 個資料列.
SQL> insert into test values ('00003',7,5,5,5);
已建立 1 個資料列.
SQL> insert into test values ('00004',3,4,9,5);
已建立 1 個資料列.
SQL> commit;

 
/* 找非正常的資料 */


select * from test
where least((col_a-col_b),(col_b - col_c),(col_c - col_d)) < 0;

COL_ID   COL_A   COL_B    COL_C   COL_D
---------- ---------- ---------- ---------- ----------
00002         9     1      2      5
00004         3     4      9      5

2009年4月20日 星期一

Related Hints using Oracle 10g


/*
  過去,我幾乎沒有使用過 Oracle Related Hints 去改善 sql 的 performance,
  一直到我們家熊熊說,在他開發的專案裡,測試效果可以從十幾分鐘降到不到一分鐘...
*/


/* 試試 Set Autotrace On 是否可使用 */

SQL> set autotrace on

/* 假使出現以下錯誤訊息
  1.改以 dba 身份登入
  2.執行 plustrce.sql
  3.grant PLUSTRACE role
*/


SP2-0618: 找不到階段作業 ID. 請檢查是否啟用 PLUSTRACE 角色
SP2-0611: 啟動 STATISTICS 報表時發生錯誤

SQL> connect / as sysdba
已連線.

SQL> @C:\oracle\product\10.2.0\db_1\sqlplus\admin\plustrce.sql
SQL> disconnect
已切斷與 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options 的連線

SQL> grant plustrace to donkey;
順利授權.
SQL> connect donkey/donkey
已連線.
SQL> set autotrace on


/* 建立測試 table 與資料 */


create table countings
(
  col1 integer not null,
  col2 integer not null,
  col3 varchar2(32)
);

insert into countings
select x,y,to_char(x) || ' x ' || to_char(y) || ' = ' || to_char(x*y)
from
(select level x from dual connect by level <= 1000) t,
(select level y from dual connect by level <= 1000) t1;

alter table countings add constraint countings_pk primary key (col1,col2);


/* 使用 traceonly 不列出 query 資料 */
SQL> set autotrace traceonly

/* 加 Related Hints 告訴 Oracle 不要使用 index */

SQL> select /*+ full(countings) */ *
 2 from countings
 3 where col1 = 555;

已選取 1000 個資料列.

執行計畫
----------------------------------------------------------
Plan hash value: 2354059736

-------------------------------------------------------------------------------
| Id | Operation     | Name   | Rows | Bytes | Cost (%CPU)| Time   |
-------------------------------------------------------------------------------
|  0 | SELECT STATEMENT |       | 1000 | 44000 | 991  (5)| 00:00:12 |
|*  1 | TABLE ACCESS FULL | COUNTINGS | 1000 | 44000 | 991  (5)| 00:00:12 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
                 1 - filter("COL1"=555)

Note
-----
 - dynamic sampling used for this statement

統計值
----------------------------------------------------------
      7 recursive calls
      0 db block gets
     4489 consistent gets
      0 physical reads
      0 redo size
    36769 bytes sent via SQL*Net to client
     1111 bytes received via SQL*Net from client
      68 SQL*Net roundtrips to/from client
      0 sorts (memory)
      0 sorts (disk)
     1000 rows processed


/* 加 Related Hints 告訴 Oracle 使用 index */

SQL> select /*+ index(countings) */ *
 2 from countings
 3 where col1 = 555;

已選取 1000 個資料列.

執行計畫
----------------------------------------------------------
Plan hash value: 3805481017

--------------------------------------------------------------------------------------------
| Id |Operation          | Name     | Rows | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
| 0 |SELECT STATEMENT       |       | 1000 | 44000 |  10  (0)| 00:00:01 |
| 1 |TABLE ACCESS BY INDEX ROWID |COUNTINGS  | 1000 | 44000 |  10  (0)| 00:00:01 |
|* 2|INDEX RANGE SCAN       |COUNTINGS_PK | 1000 |    |  5  (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
  2 - access("COL1"=555)

Note
-----
  - dynamic sampling used for this statement

統計值
----------------------------------------------------------
      7 recursive calls
      0 db block gets
     221 consistent gets
      0 physical reads
      0 redo size
    40712 bytes sent via SQL*Net to client
     1111 bytes received via SQL*Net from client
      68 SQL*Net roundtrips to/from client
      0 sorts (memory)
      0 sorts (disk)
     1000 rows processed

2009年2月5日 星期四

Create a thesaurus to expand search terms with NSE 9.5


/*
  Net Search Extender 也可以對 Varchar 型態做 Search。
  建立詞典 Thesaurus 後,也可以藉此查出相關聯或者存在同義詞的資料出來
  ※ 中文 workable
*/

/* 建立測試 Table*/

CREATE TABLE HEADLINE
(
  SNO INTEGER NOT NULL PRIMARY KEY,
  TXT VARCHAR(128)
);

/* 新增與 Alonso,西班牙相關的資料 */

INSERT INTO HEADLINE VALUES
(1,'Focused Alonso sets sights on title')
,(2,'Renault expect to challenge again')
,(3,'Cost-cutting plan agreed for F1')
,(4,'Discovery of a Sunken Armada from the Golden Age of Piracy')
,(5,'Pasties challenge paella')
,(6,'Matador aged 11 kills six bulls')
,(7,'Fernando Alonso wins the Singapore Grand Prix');

/* 啟動 NSE Service */

db2text start

/* 建立 index 在 headline 的 txt 欄位上 */

db2text create index headline_idx for text on headline(txt)

/* refresh index */

db2text update index headline_idx for text


/* 建立詞典,存放在sqllib\db2ext\下,名稱給定為 nsesamplethes.def */


:WORDS
  Alonso
 .RELATED_TO F1
 .RELATED_TO Renault
 .RELATED_TO Spain
 .SYNONYM_OF Fernando Alonso

:WORDS
  Spain
 .RELATED_TO Matador
 .RELATED_TO paella
 .RELATED_TO Armada



/*
  Compile nsesamplethes.def
  1. 用db2extth compile
  2. 1208 為 UTF-8
  3. -t compile 產生的檔案所放置的路徑
*/


C:\Program Files\IBM\SQLLIB\db2ext>db2extth -f nsesamplethes.def -ccsid 1208 -t thes\

/* compile 詞典後產生檔案,如圖 */


/* 查詢與Alonso有關的資料 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes" \
db2 (續) => => EXPAND RELATED TERM OF "alonso"') > 0

SNO TXT
--- ---------------------------------------------
 1 Focused Alonso sets sights on title
 2 Renault expect to challenge again
 3 Cost-cutting plan agreed for F1
 7 Fernando Alonso wins the Singapore Grand Prix

  已選取 4 個記錄。

/* 查詢與Alonso同義的資料 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes"
db2 (續) => => EXPAND SYNONYM TERM OF "alonso"') > 0

SNO TXT
--- ---------------------------------------------
 1 Focused Alonso sets sights on title
 7 Fernando Alonso wins the Singapore Grand Prix

  已選取 2 個記錄。


/* 查詢與spain相關的資料 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes"
db2 (續) => => EXPAND RELATED TERM OF "spain"') > 0

SNO TXT
--- ---------------------------------------------
 1 Focused Alonso sets sights on title
 4 Discovery of a Sunken Armada from the Golden Age of Piracy
 5 Pasties challenge paella
 6 Matador aged 11 kills six bulls
 7 Fernando Alonso wins the Singapore Grand Prix

  已選取 5 個記錄。


/* 查詢與spain同義的資料 */

db2 => select sno,txt from headline \
db2 (續) => => where contains(txt,'THESAURUS "nsesamplethes"
db2 (續) => => EXPAND SYNONYM TERM OF "spain"') > 0

SNO TXT
--- ---------------------------------------------

  已選取 0 個記錄。

2009年1月12日 星期一

Meaningful numeric expression using DB2 9


/*
  在 db2 forum 看到一個問題:
  提問的人想要將 2.00000000000000E+010 轉成 readable、
  meaningful 2x10^10。
  And here is my recursive sql
  ※用 DB2 9 的 New Datatype Decfloat,
   在 decimal 型態轉 char 很方便
*/

/* using Recursive SQL,一直除10,除到 >= 1 */

WITH N(ORGVAL,RESULTVAL,DIVVAL,PLUS)
AS
(SELECT ORGVAL,ORGVAL / DIVVAL RESULTVAL,DIVVAL,1 PLUS
 FROM (SELECT DECFLOAT(2.00000000000000E+010) ORGVAL,
         10 DIVVAL
     FROM  SYSIBM.SYSDUMMY1) T
 UNION ALL
 SELECT N.ORGVAL,N.RESULTVAL / 10,DIVVAL,N.PLUS + 1
 FROM  N
 WHERE N.RESULTVAL / 10 >= 1
)
SELECT RTRIM(CHAR(RESULTVAL))||'x'||
     RTRIM(CHAR(DIVVAL))||'^'||
     RTRIM(CHAR(PLUS))
FROM  (SELECT RESULTVAL,DIVVAL,PLUS,
         ROW_NUMBER() OVER(ORDER BY PLUS DESC) OID
     FROM N) T1
WHERE OID = 1;

/* 2.00000000000000E+010的結果 */
2x10^10

/* 測試 0.125040000000000E+010 */

WITH N(ORGVAL,RESULTVAL,DIVVAL,PLUS)
AS
(SELECT ORGVAL,ORGVAL / DIVVAL RESULTVAL,DIVVAL,1 PLUS
 FROM (SELECT DECFLOAT(0.125040000000000E+010) ORGVAL,
         10 DIVVAL
     FROM SYSIBM.SYSDUMMY1) T
 UNION ALL
 SELECT N.ORGVAL,N.RESULTVAL / 10,DIVVAL,N.PLUS + 1
 FROM  N
 WHERE N.RESULTVAL / 10 >= 1
)
SELECT RTRIM(CHAR(RESULTVAL))||'x'||
     RTRIM(CHAR(DIVVAL))||'^'||
     RTRIM(CHAR(PLUS))
FROM  (SELECT RESULTVAL,DIVVAL,PLUS,
         ROW_NUMBER() OVER(ORDER BY PLUS DESC) OID
     FROM N) T1
WHERE  OID = 1;

/* 0.125040000000000E+010的結果 */
1.2504x10^9

/* 測試 1.39080000000000E+010 */

WITH N(ORGVAL,RESULTVAL,DIVVAL,PLUS)
AS
(SELECT ORGVAL,ORGVAL / DIVVAL RESULTVAL,DIVVAL,1 PLUS
 FROM (SELECT DECFLOAT(1.39080000000000E+010) ORGVAL,
         10 DIVVAL
     FROM SYSIBM.SYSDUMMY1) T
 UNION ALL
 SELECT N.ORGVAL,N.RESULTVAL / 10,DIVVAL,N.PLUS + 1
 FROM  N
 WHERE N.RESULTVAL / 10 >= 1
)
SELECT RTRIM(CHAR(RESULTVAL))||'x'||
     RTRIM(CHAR(DIVVAL))||'^'||
     RTRIM(CHAR(PLUS))
FROM  (SELECT RESULTVAL,DIVVAL,PLUS,
         ROW_NUMBER() OVER(ORDER BY PLUS DESC) OID
     FROM N) T1
WHERE  OID = 1;

/* 1.39080000000000E+010的結果 */
1.3908x10^10