標籤:des style http io os 使用 java ar strong
命令列處理器是 DB2 的介面,它最佳地體現了 DB2 的威力,以及 DB2 的簡單性和通用性。作者通過例子對其進行了詳細的論述。
0 評論:
Blair Adamache, DB2 Technology Development, IBM
關閉 [x]
Blair Adamache 是 IBM 多倫多實驗室裡的一名有 17 年工作經驗的老員工。他擁有修辭學(Rhetoric)的碩士學位,但是承諾只將自己的能力應用於好的服務。Blair 當前的職責是管理 DB2 服務小組,這個小組負責確保客戶能夠繼續享用資料庫業內最好的軟體支援。Blair 有多年的和使用者打交道的經驗,涉及營銷、服務、開發和管理。他是"DB2 Fundamentals Certification for Dummies (Hungry Minds)"的技術編輯,"The Complete DB2 Reference (McGraw Hill)"的合著者之一,並且為 IBM DB2 開發人員園地撰寫過許多文章。因為技術問題而找 Blair 的最好方式就是發郵件至 comp.databases.ibm-db2。
2003 年 6 月 01 日
- 內容
- 何時使用 DB2 命令列處理器
- 驗證安裝情況和判定問題所在
- 協助
- 指令碼編寫
- 編寫 DDL 指令碼
- 原型
- 何時使用 DB2 Command Center
- CLP 設計
- 命令視窗與 Windows 上的 CLP 的比較
- 何時不使用 命令列處理器
- 一個需要避免的典型例子(或者說不值得拷貝的例子)
- 這個例子做些什麼
- 評論
何時使用 DB2 命令列處理器
IBM DB2 命令列處理器聽起來沒什麼特別之處,但實際上它是 DB2 的介面,它最佳地體現了DB2的威力,以及 DB2 的簡單性和通用性。命令列並不可愛(實際上,Windows 上的 DB2 曾得到一個“強大但是不可愛”的名聲。那是 DB2 在 NT 上初次發布的時候,當時還沒有 ControlCenter 可用)。命令列使我們想起了 UNIX 上的 Telnet,還有 1981 年開始使用的 DOS 命令。但是,如果您的 SQL 命令夠強大—— 或者您想通過輸入一個快速命令來驗證 DB2 的安裝情況——那麼命令列是理想的,而且通常比通過像 PowerBuilder 或者Access 這樣的前端提交請求要來得快。CLP 是通往每一個 DB2 編程介面的直接路徑。它使得任何可以程式化地調用的東西能夠通過介面來調用——或者在一個簡單的指令碼(就像我們曾在 DOS 中編寫過的 .BAT 檔案)中調用。像 MVS 上的SPUFI、VM 上的 ISQL 以及 VSE 上的 SQLDBSU 這些類似的工具都十分耐用,這使得我們深信 CLP 必定可以使用很長一段時間。
本文將向您展示如何使用命令列處理器(簡稱 CLP)來為您帶來好處。如果對某些工作原理還不夠明了的話,可以參考手冊( DB2 Command Reference),這個手冊用一整章介紹 CLP 的使用。
回頁首
驗證安裝情況和判定問題所在
當我第一次在 OS/2 上安裝 DB2 時(在此一年前 DB2 已經可以在 NT 上使用了),我已經在很多其他的作業系統(DOS,VM,VSE,MVS™,AS/400®)上使用過 SQL Database 管理器了。成功地安裝完之後,我開始閱讀 about 資訊,這時我被“cataloging nodes and databases(編目節點和資料庫)”這件事給弄糊塗了。catalog 這個詞與過去惹人喜愛的 SYSCAT 和 SYSIBM 目錄相比有著動詞化的意味。有時候,我會對著 DB2 大聲埋怨:“我不想編目任何東西,我只是想通過運行一個SELECT語句來確保我正確地安裝了DB2。”幾個小時之後,我冷靜下來,瞭解到只有建立了一個資料庫之後 DB2 才會有資料庫目錄;您不需要在本地機器上將節點和資料庫編目——只有在一個串連到伺服器的客戶機上時才需要編目。建立樣本資料庫非常容易——運行 db2sampl 就可以了。在驗證安裝情況時,命令列處理器 正是我所需要的工具,這時可以運行: DB2 SELECT COUNT(*) FROM SYSCAT.TABLES
在 UNIX 和 OS/2 上,您只需使用一個常見的作業系統提示符,並在任何 DB2 命令或者 SQL 陳述式前面加上"DB2" 。在 Windows 上,事情要麻煩一些,這在後面會解釋,不過您可以通過輸入 DB2CMD 來建立一個適合 DB2 命令、SQL 和 作業系統命令(例如 dir 和 ren)的提示符。您甚至可以混合使用 SQL、DB2 命令和作業系統參數,例如用 |more 來滾動螢幕,用大於符號(>)來向檔案輸送內容: DB2 select * from employee>c:\\tmp\\emp.out |more
注意:對於那些對 DB2 和作業系統都有意義的符號,比如 Windows 上的大於符號(>),作業系統會最先給予解釋。SELECT * FROM EMPLOYEE WHERE SALARY >9999 語句會將錯誤訊息輸送到一個名為 9999 的檔案。要劃清這些特殊符號的界限;您應該輸入: SELECT * FROM EMPLOYEE WHERE SALARY ">" 9999
雖然您的使用者可能永遠不會使用 CLP 來訪問他們的資料,對於 DBA 或者應用程式的編程人員來說, CLP 在工具箱中是最基本的工具:它就像是在所有場合都適用的燕尾服。對於關鍵應用來說,往往資料庫是關鍵之處,如果某個地方出錯的話,問題的判定會比較困難。在大型主機/微電腦領域中,問題可能出在應用程式中,也可能出在軟體系統中,但是問題總可以界定在一台電腦以內。而在客戶機-伺服器領域中,問題可能隱藏在客戶機系統軟體中(作業系統,資料庫客戶機,或者通訊協定),可能隱藏在客戶機應用程式代碼中,可能隱藏在伺服器應用程式代碼中(如果您正在使用觸發器,使用者定義的函數,或者預存程序),還可能隱藏在伺服器上的其他地方。3-層應用程式套件括 Web 服務器、瀏覽器和第三層的硬體。CLP 在這裡有什麼用呢?答案就是,它可以將應用程式從這一架構中分割出來。如果您發現一個問題,那麼可以將故障請求翻譯成簡單的 SQL,然後從以下機器上的 CLP 運行該 SQL:
- 伺服器
- 客戶機
- Web 服務器
根據哪裡沒問題,哪裡有故障,您就可以判定是 DB2 本身有故障(很可能在通過 CLP 提交 SQL的伺服器上出故障的形式與客戶機應用程式出故障的形式是一樣的),還是問題出在通訊上(請求在 客戶機出了故障,而在伺服器上沒有問題),或者問題是出在 Web 服務器上(問題只出在最遠的地方)。
回頁首
協助
CLP 也是一個到 DB2 協助的介面。如果您收到一條訊息,而又不知道應該採取怎樣的適當步驟,那麼在 CLP 中輸入:
C:\\SQLLIB>db2 ? sql0100 |more
FETCH、UPDATE 或 DELETE 語句的輸出中應該有 SQL0100W No 這樣一行;否則查詢的結果就是一個空表。
解釋:下面的情況中有一種情況為真:
- No 這一行符合在 UPDATE 或 DELETE 語句中指定的搜尋條件。
- SELECT 語句的結果是一個空表。
- 當遊標定位到了結果表的最後一行記錄時,會執行一條 FETCH 語句。
- 在 INSERT 語句中使用的 SELECT 的結果為空白。
這裡沒有檢索、更新或者刪除資料。
使用者響應:不需要動作。處理可以繼續。
sqlcode: +100
sqlstate: 02000
您可以看看在 Messages 手冊中的相同的協助,包括為避開問題而建議採用並且可以採用的動作。CLP 還將提供用於 DB2 命令的文法(作為例子,可以試試 DB2 ? backup)。
回頁首
指令碼編寫
您可以使用 CLP 運行指令碼,任何可以以常規操作處理的方式啟動並執行公用程式(例如每夜啟動並執行 LOAD、RUNSTATS 或者 BACKUP 命令),都可以是一個 CLP 指令碼。CLP 的一些選項可以指定輸入檔案(-f),一個用於訊息的輸出檔案(-z),是否能夠回送關於什麼要在螢幕上啟動並執行資訊(-v),是否能夠設定一個語句終止符(-t),如果設定了這個選項,指令碼就可以包含多個 DB2 命令 和 SQL 陳述式。通常我會這樣運行指令碼:DB2 -tvf filename.ddl -t,後面加上預設的終止符(;),-v 選項允許回送檔案的內容到螢幕(這樣就可以檢查我告訴了 DB2 要做些什麼),-f 選項告訴 CLP 使用一個輸入檔案。通過 DB2 ? options可以得到關於所有選項的協助:
C:\\SQLLIB>db2 ? options
db2 [option ...] [db2-command | sql-statement |
[? [phrase | message | sqlstate | class-code]]]
option: -a, -c, -e{c|s}, -finfile, -lhistfile, -n, -o, -p, -rreport, -s, -t,
-td;, -v, -w, -x, -zoutputfile.
選項 |
描述 |
預設設定 |
-a |
顯示 SQLCA |
OFF |
-c |
自動認可 |
ON |
-e |
顯示 SQLCODE/SQLSTATE |
OFF |
-f |
從輸入檔案讀內容 |
OFF |
-l |
曆史檔案中的日誌記錄命令 |
OFF |
-n |
刪除換行字元 |
OFF |
-o |
顯示輸出 |
ON |
-p |
顯示 db2 互動性命令 |
ON |
-r |
將輸出報告儲存到檔案 |
OFF |
-s |
出現命令錯誤時停止執行 |
OFF |
-t |
設定語句終止符 |
OFF |
-v |
回送當前命令 |
OFF |
-w |
顯示 FETCH/SELECT 警告訊息 |
ON |
-x |
省略欄位標題的列印 |
OFF |
-z |
將所有輸出儲存到輸出檔案 |
OFF |
在 DB2 ControlCenter 中的指令碼中心那裡提供了更加進階的指令碼編寫,包括時間安排(scheduling),並且可以使用日誌來查看發生過什麼事情。在原型(prototyping)模式下,CLP 只是一種啟動程式的快速方式。注意上述輸出中的 -x 選項:我們添加了這個能力,以便可以在 DB2 v7 的 fixpak 1 中不輸出資料行標題。如果客戶要求輸出資料行標題,他們可能是關心欄位標題,因為他們希望輸出好看一些(或者要將輸出作為另一個程式的輸入)。對於我來說,這意味著人們現在 將 CLP 不僅僅用於原型。
回頁首
編寫 DDL 指令碼
如果對於每個產品和開發資料庫您都遵循這個簡單的規則,那麼您將對我感激不盡:您可以將所有用於建立或更改資料庫物件的 DDL 儲存在一個檔案中。更令人振奮的是,可以用一個編輯器將 DDL 輸入到一個檔案中,然後通過提交這個檔案給 CLP 來運行這個檔案。如果您不採納上述建議,那麼用於在一個資料庫中重新建立視圖、檢查約束、SQL 過程以及觸發器的語句的文本也可以這樣擷取:
select text from syscat.views
select text,tabname from syscat.checks
select text from syscat.procedures
select text from syscat.triggers
您也可以通過使用 -e 選項(或者對於特定的表使用 -t 選項和 -e 選項)運行 db2look 來收集將大部分的這些資訊。 DB2 Command Reference 為 db2look 編寫了文檔。不過,預先將這樣的資訊儲存在一個用於提交 DDL 的檔案中,比在一個依賴於另一個資料庫的模式的新項目中途匆忙地重新建立它要更顯得專業些。
回頁首
原型
您不必將所有的 DML(SELECT,INSERT,UPDATE,DELETE)儲存在一個檔案中。畢竟,這些 DML 將會處在您所編寫的程式中,並且可以通過使用像監視器和 DB2 Query Patroller 這樣的 DB2 工具動態地捕獲。不過,在將 SQL 輸入到一個應用程式之前,您可以先使用 CLP 對其進行原型實驗,看看自己是否對結果滿意(並且可以檢查文法)。使用 -a 選項來查看 SQL Communications Area (SQLCA)。例如,如果語句沒有對任何東西進行更新,或許在文法上這條語句是對的,但是沒有任何記錄行符合更新條件是由於採用了限制性非常強的 where 子句造成的。在這種情況下,您會得到一個值為 100 的 SQLCODE:
C:\\sqllib>db2 -a update employee set salary=5 where salary "<" -5
SQLCA Information
sqlcaid : SQLCA sqlcabc: 136 sqlcode: 100 sqlerrml: 0
sqlerrmc:
sqlerrp : SQLRIEXU
sqlerrd : (1) -31743 (2) 1 (3) 0
(4) 0 (5) 0 (6) 0
sqlwarn : (1) (2) (3) (4) (5) (6)
(7) (8) (9) (10) (11)
sqlstate: 02000
回頁首
何時使用 DB2 Command Center
DB2 Command Center 是一個圖形化的命令列(對於那些偏愛形而上學邏輯的讀者來說,這是一種似是而非的說法,而不是簡單的自相矛盾)。任何命令或者 SQL 陳述式,甚至是作業系統命令,都可以通過 Command Center 提交。雖然 CLP 直接調用 DB2 編程介面,但是 Command Center 要經由 DB2 的 Call Level Interface (即 CLI,這基本上是 ODBC 的一個超集)。這意味著當有故障發生時,您可能會得到一條 CLI 錯誤訊息,而不是一個 SQLCODE。這還意味著如果您懷疑某個地方有 CLI bug,您可以試著通過 CLP 提交 SQL 到 Command Center。如果在 CLP 部分是成功的,而在 Command Center 部分是失敗的,那麼問題顯然就出在 CLI 那一部分。在 DB2 中,這一點很重要,因為對 DB2 的所有 ODBC、Java、JDBC 和 SQLJ 訪問都要經由 CLI。由於這個原因,Command Center 是用 Java 編寫的。比起 CLP,Command Center 有以下優點:
- 可以在作業系統命令提示字元的邊界外部水平地和垂直地滾動:這包括針對您提交的命令和 SELECT 語句的結果的獨立選項卡(或頁面)。
- 對剪下和粘貼的完全剪貼簿支援。
- 可以訪問 Script Center (在 ControlCenter 中)和 Visual Explain (以便圖形化地顯示對 SQL 陳述式的訪問計劃——這是查看哪些索引得到使用的最佳方式)。可以高亮顯示 SQL,通過點擊 Access Plan 可以可視化地解釋一條 SQL 陳述式。
- 能夠更容易地通過用滑鼠拓展或者收縮可見地區來顯示(或隱藏)多個列。
- 提供了一個下拉式的菜單,用於檢索和編輯先前提交的命令(而不是依賴於作業系統的命令,比如 Windows 和 OS/2 作業系統中的向上箭頭和向下箭頭)。
- 在會話中提交的命令和結果的更好的記錄——這有利於將互動體驗轉變成指令碼(或者取得所有 CREATE TABLE 語句並將其存入一個檔案中)。
- 支援所有的 CLP 選項(例如顯示 SQLCA)。
因為介面各異,其中有些微妙之處需要知道。接下來的語句在 Command Center 中和在 CLP 中將得到迥然不同的結果:
create user temporary tablespace usetemp
pagesize 4k managed by system using (‘C:\\usetemp‘);
declare global temporary table t1 (col1 int) not logged;
select count(*) from session.t1;
這與 DB2 對用於使用者聲明的暫存資料表的會話所有權的處理方式有關。對於在 Command Center 中啟動的每個 Java 進程,所有權並不是一成不變的。上面的 select count(*) 語句在 CLP 中將獲得成功,但是在 Command Center 中卻不能找到 session.t1。
回頁首
CLP 設計
DB2 Command Reference 在第 2 章中解釋了 CLP 設計。CLP 設計由兩個過程組成:
- 一個前端進程(或者是在 Windows 和 OS/2 上的線程),用於處理與作業系統命令提示字元的通訊。
- 一個後端進程,用於處理與資料庫的通訊。這確保了在您串連到 DB2 之後,如果用 Control-C 或 Control-Break 中止來自一個大型選擇(例如 SELECT * FROM SYSCAT.TABLES)的輸出,那麼輸出會順利地被中止,而不會斷開到 DB2 的串連。
回頁首
命令視窗與 Windows 上的 CLP 的比較
那麼,為什麼 DB2 要求您用 Windows 上的 DB2CMD.EXE(或者用 DB2 Command Window,或者用 DB2 Command Line Processor,又或者用開始菜單)啟動一個 CLP 呢?在 UNIX 和 OS/2 上,前端進程和後端進程之間的連結非常簡單:如果父進程死亡,則其所有子進程都將被作業系統終止。在 Windows 上,父線程在死亡時並不會終止其子線程。這裡我們不去冒險產生 Windows 上的大量 phantom 線程,而是決定用一個 cookie 來為 Windows 上的 CLP 連結前端線程和後端線程。這要求 CLP 要通過 DB2CMD.EXE 來啟動。這樣做確保了如果殺死了父線程,那麼子線程也不會保留下來,從而避免了資源的浪費。不必擔心叫做"DB2 Command Processor"的特定選項。它會建立像這樣的一個特殊的提示符:
db2 =>
這樣,您就不必在所有發送到 DB2 的指令之前都加上 DB2。另一方面,現在您必須在作業系統命令之前加上一個驚歎號(!),就像在 Command Center 中一樣。
回頁首
何時不使用 命令列處理器
對於用於檢查文法和您希望使用者看到的結果的原型 SQL 來說,CLP 很有用。但是,由於 CLP 是如此的多用,能夠提供到每條 DB2 SQL 陳述式、命令以及編程介面的訪問途徑,所以通常來講,比起動態 SQL(例如那些通過 ODBC 提供的動態 SQL)來 CLP 會產生更大的開銷。為了對效能進行原型實驗,可以使用 db2batch,這在 DB2 Command Reference中有文檔說明。
回頁首
一個需要避免的典型例子(或者說不值得拷貝的例子)
下面是一個簡單的例子,其中充斥著許多壞的編程習慣,這個例子展示了為什麼 CLP 對於應用程式邏輯來說不是很好。對於簡單的指令碼編寫,下面的例子可以更加強大,甚至可以處理一些出錯的情況,如果它是用 PERL 編寫的話。不過,對於我來說,編寫和做一些有用的工作是十分有趣的。先決條件:
- 已經建立了樣本資料庫。
- 從 DIR 命令得到的輸出與我測試時所在的系統(帶有 ServicePak 5 的 NT 4.0,以及 Windows 2000)相匹配。
- 您正處在 Windows 上的一個 DB2 Command Window 中。
回頁首
這個例子做些什麼
是不是曾經碰到過用完了磁碟空間的情況。下面的例子捕獲在 C:\\ 上的一個遞迴的目錄清單的輸出,為每個大小為 1 MB 或大於 1 MB 的檔案匯入一行,並列出 C: 盤中 10 個最大的檔案。不要刪除 PAGEFILE.SYS!只能刪除那些明確知道是垃圾的檔案(例如 C:\\TEMP 中大型的 .PDF 檔案)。 這個例子中有什麼好的地方?
- 它可以協助我清理我的硬碟。
- 它可以在兩種系統上工作(我成功地完成了系統測試並發布了它!)
這個例子有什麼不好的地方?
在開發人員園地即將發布的一個 500 頁的讀我檔案(readme)中,您將看到對這個例子的缺點的文檔說明。
仔細研究這個例子: (我是這樣啟動並執行:db2 -tvf dirpub)
!dir c:\\*.* /s>dir.out;
connect to sample;
create table dirlist (size_in_mb int not null, name char(21) not null
CONSTRAINT CHECKBYTES CHECK (name not like ‘ bytes%‘));
import from c:dir.out of asc method l (28 30, 40 60)
commitcount 1000 replace into dirlist;
select * from dirlist order by size_in_mb desc
fetch first 10 rows only;
第 1 行將 C: 上所有檔案的列表發送到 dir.out。
第 2 行串連到樣本資料庫。
第 3 行建立一個帶有兩列的表:一列是以 MB 為單位的每個檔案的大小,一列是每個檔案的檔案名稱中的前 21 個字元。既然在 Windows 告訴您關於目錄的資訊時會顯示短語"bytes",那麼我們使用一個檢查約束來消除這些不需要的行。
第 4 行將檔案 dir.out 中的行匯入表 dirlist 中。我們假設以 MB 為單位的檔案大小是從第 28 列到第 30 列的一個整數,並將從第 40 列到第 60 列的內容拿來作為檔案名稱。我們每 1000 行提交一次,並且替換 dirlist 的內容,以防多次運行這種提交。
第 5 行獲得 10 個最大的檔案的檔案名稱。
所以,用 5 行代碼,我們就可以清理一個硬碟分區(或者至少查看出哪些檔案佔用了所有的空間)。處理出錯情況,允許搜尋其他磁碟機,以及刪除輸出中的系統檔案,這些功能能夠輕鬆地將這個小小的程式擴充成數百行,我不 想編寫這麼多的代碼。畢竟,CLP 的精神就是“快而髒(quick and dirty)”,即花費的精力中有 20% 滿足了 80% 的需求。如果您小心地應用這個 80/20 法則,令使用者感到滿意,您就總能接到更多的項目。
【轉】DB2 的命令列處理器和指令碼編寫