2009 年 2 月 10 日
本文主要介紹如何使用 IBM Data Studio 開發(fā)數(shù)據(jù)庫存儲過程和 Data Web Services 。 IBM Data Studio 對數(shù)據(jù)庫開發(fā)提供了完備的支持,同時提供了把存儲過程發(fā)布成 Web Services 的工具。通過本文,讀者可以學(xué)習(xí)到如何安裝 IBM Data Studio,如何簡單高效地開發(fā)和調(diào)試數(shù)據(jù)庫應(yīng)用程序以及如何把它們發(fā)布成 Web Services 。
IBM Data Studio 是一款免費(fèi)的基于 Eclipse 的用于數(shù)據(jù)庫開發(fā)的工具。 IBM Data Studio 包含了開發(fā)數(shù)據(jù)庫存儲過程的所有功能,同時提供了對 DB2 v9 的 XML 功能的支持。
本文將通過一個開發(fā)實(shí)例介紹 IBM Data Studio 是如何幫助我們進(jìn)行存儲過程開發(fā)的。
在開始使用 IBM Data Studio 之前,讓我們先來了解一下本文的項(xiàng)目實(shí)例。該項(xiàng)目實(shí)例是一個簡化版的軟件開發(fā)管理系統(tǒng)。系統(tǒng)主要管理 User Story 和 Work Item 的信息。 User Story 就是以用戶的角度編寫的業(yè)務(wù)需求,是軟件需要實(shí)現(xiàn)的功能。我們需要記錄 User Story 的具體內(nèi)容和其狀態(tài)。這里的狀態(tài)是指該 User Story 是在草擬狀態(tài)還是完成狀態(tài)。 Work Item 用于記錄軟件開發(fā)的過程。 Work Item 可以是根據(jù)某個 User Story 編寫的詳細(xì)設(shè)計,也可以是一個編碼任務(wù),或者是一個 bug 報告。我們需要記錄其狀態(tài)(未分配,處理中和完成等),結(jié)對編程人員的 Email 等信息。
本系統(tǒng)應(yīng)該實(shí)現(xiàn)如下功能 ( 未列出所有功能 ):
為此我們設(shè)計了相應(yīng)的數(shù)據(jù)庫表:USER_STORY 和 WORK_ITEM 。它們的詳細(xì)定義如下表所示:
列名稱 | 類型 | 說明 |
---|---|---|
id | INTEGER | 表主鍵。 |
author | VARCHAR | 編寫人的 Email 地址。 |
status | CHAR | 表示 User Story 的狀態(tài),可以是草擬,完成等值。 |
txt | VARCHAR | User Story 的具體內(nèi)容 |
列名稱 | 類型 | 說明 |
---|---|---|
id | INTEGER | 表主鍵。 |
user_story_id | INTEGER | 記錄該 Work Item 對應(yīng)的 User Story 。 |
type | CHAR | 類型,分為:詳細(xì)設(shè)計,編碼任務(wù),bug 報告。 |
status | CHAR | 狀態(tài),分為: 未分配,處理中,完成等。 |
txt | VARCHAR | Work Item 的具體說明。 |
primaryStaff | VARCHAR | 首席工作人員 Email 地址 |
secondaryStaff | VARCHAR | 結(jié)對的開發(fā)人員 Email 地址 |
為了實(shí)現(xiàn)系統(tǒng)的功能,我們還需要下列存儲過程 :
![]() ![]() |
![]()
|
“工欲善其事,必先利其器”。現(xiàn)在我們明確了需求,為了開發(fā)出優(yōu)秀的軟件,我們還需要一個開發(fā)工具。 IBM Data Studio 就是一款非常好的存儲過程開發(fā)工具,我們可以從 IBM 官方網(wǎng)站上下載其安裝包。安裝完畢后啟動 IBM Data Studio,可以看到 IBM Data Studio 的界面主要由四個區(qū)域組成:
創(chuàng)建數(shù)據(jù)庫項(xiàng)目
首先創(chuàng)建一個數(shù)據(jù)庫連接:
默認(rèn)情況下 IBM Data Studio 不會記錄連接數(shù)據(jù)庫的用戶密碼,為了避免每次連接數(shù)據(jù)庫時都輸入密碼,我們可以修改相應(yīng)設(shè)置,把數(shù)據(jù)庫的用戶和密碼存儲在電腦中:
接著,我們創(chuàng)建一個數(shù)據(jù)庫項(xiàng)目。
展開 Sample 項(xiàng)目,我們可以看到在項(xiàng)目的根目錄下有五個文件夾,分別用來存放 SQL 文件,存儲過程源文件,UDF 源文件,Web Service 文件和 XML 文件。
創(chuàng)建完項(xiàng)目,我們就可以開始開發(fā)數(shù)據(jù)庫對象了,也就是要編寫建表語句和存儲過程。為了規(guī)范我們編寫的代碼和提高我們編碼的效率,我們首先要設(shè)置一下模板。
在 IBM Data Studio 中可以很方便地定義 SQL 模板:
從下圖我們可以看到,IBM Data Studio 給我們提供了一些通用的模板。
這里我們再定義一些我們項(xiàng)目中使用的模板。
下面是我們定義的模板的具體內(nèi)容:
DROP TABLE ${table_name} @ ---------------------------------------------------------------------------------- -- -- Table_Name: ${table_name} -- File Name: ${table_name}.SQL -- Author: ${user} -- Date: ${date} -- -- Abstract: -- -- -- MAINTENANCE LOG -- who date comment -- --- -------- --------------------------------------------------------------- ----------------------------------------------------------------------------------- CREATE TABLE ${table_name} ( ) @ --Primary Key ALTER TABLE ${table_name} ADD CONSTRAINT ${table_name}_PK PRIMARY KEY (${pk} ) @ |
DROP SPECIFIC PROCEDURE ${spName} @ CREATE PROCEDURE ${spName} ( OUT poGenStatus INTEGER , IN ${piArgu} VARCHAR(8) ) SPECIFIC ${spName} RESULT SETS 0 LANGUAGE SQL ------------------------------------------------------------------------------ -- -- Procedure Name : ${spName} -- Specific Name: ${spName} -- File Name: ${spName}.SQL -- Author: ${user} -- Date: ${date} -- -- Abstract: ${description} -- -- -- Sample Calls: -- call ${spName} (?,'${piArgu}') -- -- MAINTENANCE LOG -- who date comment -- --- -------- ------------------------------------------------------------ -- ${user} ${date} Initial version -- ------------------------------------------------------------------------------- BEGIN NOT ATOMIC ------------------------------------------------------------- -- Variables declarations ------------------------------------------------------------- -- Generic Variables DECLARE SQLCODE INTEGER DEFAULT 0; DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; -- Generic handler variables DECLARE hSqlcode INTEGER DEFAULT 0; DECLARE hSqlstate CHAR(5) DEFAULT '00000'; -- error variables DECLARE ERR_MISSING_INPUT INTEGER DEFAULT 34100; DECLARE ERR_GENERAL_SQL INTEGER DEFAULT 1; DECLARE ERR_RECORD_EXISTS INTEGER DEFAULT 4; DECLARE ERR_ROW_NOT_FOUND INTEGER DEFAULT 5000; -- Local Variables DECLARE vCurrentTimestamp TIMESTAMP; ------------------------------------------------------------- -- CONDITION declaration ------------------------------------------------------------- -- (80100~80199) SQLCODE & SQLSTATE DECLARE sqlReset CONDITION FOR SQLSTATE '80100'; ------------------------------------------------------------- -- CURSOR declaration ------------------------------------------------------------- ------------------------------------------------------------- -- EXCEPTION HANDLER declaration ------------------------------------------------------------- -- Handy Handler DECLARE CONTINUE HANDLER FOR sqlReset BEGIN NOT ATOMIC SET hSqlcode = 0; SET hSqlstate = '00000'; SET poGenStatus = 0; END; -- Generic Handler DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN NOT ATOMIC -- Capture SQLCODE & SQLSTATE SELECT SQLCODE, SQLSTATE INTO hSqlcode, hSqlstate FROM SYSIBM.SYSDUMMY1; -- Use the poGenStatus variable to tell the procedure what type -- of error occurred. In some cases, it can be assigned to the -- poGenStatus variable to be returned to the client. CASE hSqlstate WHEN '02000' THEN --row not found SET poGenStatus=5000; WHEN '42724' THEN --missing llsp SET poGenStatus=3; ELSE IF (hSqlCode < 0) THEN --trap only errors, not warnings SET poGenStatus=2; END IF; END CASE; END; ------------------------------------------------------------- -- Initialization ------------------------------------------------------------- -- reset all output parameters to NULL SET poGenStatus = 0; SET ${piArgu} = RTRIM(COALESCE(${piArgu}, '')); -------------------- -- data validation -------------------- IF (${piArgu} = '') THEN SET poGenStatus = ERR_MISSING_INPUT; RETURN poGenStatus; END IF; SET vCurrentTimestamp = CURRENT TIMESTAMP; RETURN poGenStatus; END @ |
現(xiàn)在我們開始編寫代碼。右鍵單擊SQL Scripts文件夾,在彈出菜單中選擇New > SQL or Xquery Script。輸入名稱 USER_STORY,然后單擊Finish。在打開的 USER_STORY.SQL 中,單擊右鍵選擇Content Assist,然后選擇 create table 模板。模板的內(nèi)容被插入到文件中,需要修改的內(nèi)容被高亮顯示。我們依次修改表名和列的信息。在我們修改 SQL 文件的時候,IBM Data Studio 還在有語法錯誤的語句下面顯示一條紅線,真是太棒了!
修改后的代碼如下:
-- <ScriptOptions statementTerminator="@" /> DROP TABLE USER_STORY @ ---------------------------------------------------------------------------------- -- -- Table_Name: USER_STORY -- File Name: USER_STORY.SQL -- Author: will -- Date: Sep 9, 2008 -- -- Abstract: -- -- -- MAINTENANCE LOG -- who date comment -- --- -------- --------------------------------------------------------------- ----------------------------------------------------------------------------------- CREATE TABLE USER_STORY ( id INTEGER NOT NULL, -- 表主鍵。 author VARCHAR(80), -- 編寫人的 Email 地址。 status CHAR(10), -- 表示 User Story 的狀態(tài),可以是草擬,完成等值。 txt VARCHAR(500) --User Story 的具體內(nèi)容 ) @ --Primary Key ALTER TABLE USER_STORY ADD CONSTRAINT USER_STORY_PK PRIMARY KEY (ID ) @ |
編寫完建表文件后,我們需要把它裝載到數(shù)據(jù)庫中。
由于我們在 USER_STORY.SQL 文件中使用 @ 符號作為分隔符。所以,我們需要在 IBM Data Studio 中把 @ 指定成分隔符。在工作區(qū),單擊右鍵,在彈出菜單中選擇Set Statement Terminator,然后輸入 @ 。
下面,我們開始執(zhí)行我們編寫的 USER_STORY.SQL 文件。右鍵單擊工作區(qū),選擇Run SQL。我們可以在Data Output視圖中看到 Run successful 的消息。
我們來查詢一下 USER_STORY 表里數(shù)據(jù)。新建一個 query.sql 文件。在 query.sql 文件里鍵入 SELECT * FROM, 這時我突然忘記了表的名字(有時候,因?yàn)楸砻L,我們很容易不記得其名字),IBM Data Studio 可以幫助我們找到我們想要的表。首先鍵入 U (我記得表是以 U 開頭的),然后單擊右鍵選擇Content Assist或者使用快捷鍵 Alt+/ 。哦,IBM Data Studio 把所有以 U 開頭的表都列在了彈出框里。我們選擇 USER_STORY 這個表。然后,我們象執(zhí)行 USER_STORY.SQL 一樣執(zhí)行該語句,可以在 Data Output 視圖中看到,目前表里沒有任何數(shù)據(jù)。
在Content Assist和模板的幫助下,我們很方便的完成了項(xiàng)目所需要的表和存儲過程。雖然 IBM Data Studio 也提供了創(chuàng)建存儲過程的向?qū)?,不過我更傾向于模板加手動修改源文件的方式編寫存儲過程。您可以選擇您自己喜歡的方式去編寫存儲過程。
有時候,我們需要看一下數(shù)據(jù)庫中某個存儲過程的源代碼。我們可以在Database Explorer中,依次打開[database name]> Schemas > Stored Procedures。右鍵單擊存儲過程,在彈出菜單中選擇Open > With SQL Editor。然后存儲過程的源代碼就在 IBM Data Studio 中打開了。
我們已經(jīng)編寫完所有的存儲過程了,測試人員正在對這些存儲過程進(jìn)行測試,初步結(jié)論是這些存儲過程運(yùn)行正常。我們非常高興,認(rèn)為開發(fā)工作應(yīng)該是完成了??墒钦?dāng)我們暗自高興的時候,測試人員來找我們了。他們說,新增 User Story 這塊功能突然出問題了,這塊功能在前幾天的測試都是正常的。這就奇怪了,我們最近沒有更新過代碼,為什么原來可以使用的功能突然就不能用了呢? 大家一邊看著代碼,一邊皺眉---代碼應(yīng)該沒有問題啊。
幸好,IBM Data Studio 為我們提供了非常優(yōu)秀的調(diào)試功能,我們可以像調(diào)試 Java 程序那樣調(diào)試存儲過程。 在 IBM Data Studio 中針對存儲過程設(shè)置斷點(diǎn),單步執(zhí)行,查看存儲過程運(yùn)行時的某些變量值都變得非常簡單。
現(xiàn)在我們就開始調(diào)試出問題的存儲過程 I_USER_STORY 。
通過單步執(zhí)行,我們很快的就找到了出錯的代碼:
DECLARE vMaxId SMALLINT; ... SELECT MAX(ID)+1 INTO vMaxId FROM USER_STORY; |
原來,我們把 vMaxId 聲明成 SMALLINT, 然而隨著表 USER_STORY 中數(shù)據(jù)的增加,MAX(ID) 很快就超過了 SMALLINT 的最大值,這時我們再把 MAX(ID) 賦值給 vMaxId,就會出現(xiàn)溢出的錯誤。看來 I_USER_SOTRY 中有一個 bug 。我們應(yīng)當(dāng)把 vMaxId 聲明成 INTEGER 而不是 SMALLINT 。我們把修改后的代碼重新部署到數(shù)據(jù)庫中后,測試人員高興的告訴我們,新增 User Story 又重新可用了。
多虧 IBM Data Studio 的調(diào)試功能,使得我們很快的找到并修改了 bug 。
我們的系統(tǒng)順利的通過了功能測試,接下來我們要面臨性能測試的考驗(yàn)了。
在性能測試時,測試人員抱怨說,在查詢 Work Item 的時候,系統(tǒng)的性能特別差。為了解決性能問題,IBM Data Studio 為我們提供了 Visual explain 。 Visual explain 可以幫助我們編寫出高效率的 SQL 語句。這對于存儲過程的性能調(diào)優(yōu)非常重要。 IBM Data Studio 可以為我們提供圖形化的執(zhí)行計劃:在 SQL 編輯器中選中你需要分析的 SQL 語句,單擊右鍵,選擇Visual Explain,然后我們就得到了如下圖所示的 SQL 執(zhí)行計劃。
通過查看 Visual Explain,我們得出結(jié)論:由于 WORK_ITEM 表中的數(shù)據(jù)太多,對全表掃描花費(fèi)太多的時間,我們應(yīng)該建立合適的索引來提高性能。建立完索引后,我們再次執(zhí)行 Visual Explain 。現(xiàn)在,其性能就提高了很多。
當(dāng)然,本文中的例子只有兩個表,略顯簡單。在實(shí)際項(xiàng)目中,我們往往需要查詢多個表,查詢條件也會非常復(fù)雜。通過 Visual Explain 我們可以獲得 SQL 語句是否使用了索引,是否對某個表進(jìn)行了多次掃描等信息。這些信息對優(yōu)化我們的 SQL 語句非常有用。
我們的系統(tǒng)經(jīng)過嚴(yán)格的測試后,終于上線了。用戶對我們的系統(tǒng)非常滿意。但是他們提出了一個要求,希望我們的系統(tǒng)可以跟他們另外的一個業(yè)務(wù)系統(tǒng)進(jìn)行集成。那個業(yè)務(wù)系統(tǒng)需要獲得 Work Item 的信息,但是它不能直接調(diào)用我們的存儲過程。經(jīng)過討論,我們決定把我們的存儲過程發(fā)布成 Web Service,以方便其業(yè)務(wù)系統(tǒng)的訪問。
使用 IBM Data Studio,我們可以很方便的把存儲過程發(fā)布成 Web Service 。
下面我們把這個 Web Service 到出為 war 包。
![]() ![]() |
![]()
|
文中的例子雖然簡單,但是包含了開發(fā)存儲的各個方面??梢钥闯?IBM Data Studio 對存儲過程的開發(fā)的支持是非常全面的。
IBM Data Studio 還提供了很多有用的功能,例如:通過圖形方式生成 SELECT 語句,可以生成存儲過程的 Unit Test 程序等等。相信讀者在使用 IBM Data Studio 的過程中會不斷發(fā)現(xiàn)一些非常有用的功能。希望本文能促使您開始使用 IBM Data Studio,并且享受 IBM Data Studio 給我們帶來的開發(fā)存儲過程的便利。
![]() ![]() |
![]()
|
描述 | 名字 | 大小 | 下載方法 |
---|---|---|---|
本文用到的 SQL 腳本示例 | sample.zip | 10KB | HTTP |
![]() | ||||
![]() | 關(guān)于下載方法的信息 | ![]() |
![]() | ||
| ![]() | 常偉是一位工作在 IBM CSDL 的軟件工程師,具有四年的 j2ee 開發(fā)經(jīng)驗(yàn)和三年的 DB2 存儲過程開發(fā)經(jīng)驗(yàn),目前從事企業(yè)電子商務(wù)應(yīng)用的開發(fā)。您可以通過 changwei@cn.ibm.com 和他聯(lián)系。 |