在Linux/Unix下一些程式是命令列或者服務程式,一般都有一個設定檔來描述其運行規則,而這些規則通常會儲存在資料庫中,由其它應用程式來維護。這就牽涉一個問題,如何從資料庫中擷取最新的規則來驅動背景程式。同樣背景程式運行結束後,產生的結果有時需要寫回資料庫,以便其它應用程式讀取。
通過閱讀本文章,讀者能瞭解Shell指令碼和Informix互動的一些常用技巧和方法,實現諸如查詢、增加、刪除、修改資料功能,最終實現資料庫、背景程式之間的資訊互動。
1. Informix簡要介紹
Informix是IBM公司出品的關聯式資料庫管理系統(RDBMS)家族。作為一個整合解決方案,它被定位為作為IBM線上交易處理(OLTP)旗艦級資料服務系統。 IBM對Informix和DB2都有長遠的規劃,兩個資料庫產品互相吸取對方的技術優勢。目前最新版本的是Informix 11.7,這個最新的版本在未來十年對IBM Informix繼續提供力量,其引擎有效解決OLTP,決定了可以更好的支援各種規模的企業和夥伴的決策支援應用。
2.Linux/Unix Shell簡要介紹
Linux/Unix Shell也叫做命令列介面,是一種控制系統的指令碼語言。它是Linux/Unix作業系統下傳統的使用者和電腦的互動介面。使用者直接輸入命令來執行各種各樣的任務,隱藏了作業系統低層的細節。
Shell的主要功能:命令執行、輸入/輸出重新導向、環境控制、幕後處理、Shell指令碼。
3.Shell與Informix互動的基本方法
Shell通過調用dbaccess在Informix上執行各種SQL,而通過調用dbload可以將檔案載入到資料庫中。
3.1. 通過dbaccess串連資料庫
dbaccess提供了用於輸入、執行和調試結構化查詢語言 (SQL)(SQL)語句與預存程序語言(SPL)常式的使用者介面。假設聯機的資料庫伺服器包含一個名為mystores的資料庫,要使mystores資料庫成為當前資料庫,可以通過db2access mystores來啟動DB-Access.也可以通過命令dbaccess //xyz/newstores 串連到xyz資料庫伺服器上的newstores資料庫(未聯機)。
3.2. 通過dbaccess執行SQL
當從命令列調用dbaccess時,可以指定某個資料庫作為當前的資料庫、執行包含一個或多個SQL語句的檔案以及顯示多個層級的錯誤資訊。
例1:dbaccess test insert.sql
表示:在test資料庫執行名為insert.sql的檔案中SQL語句的命令。
例2:dbaccess - insert.sql
表示:在insert.sql上檔案中指定的資料庫上執行檔案中的SQL語句的命令。
下面函數被調用後,調用dbaccess來執行相關的SQL並將結果輸出到標準輸出中。
清單1
ExecuteSqlSelect()
{
sqltxt="$1";
pre_sql="output to pipe cat without headings ";
sqltxt=$pre_sql"$sqltxt";
echo "$sqltxt"|dbaccess test 2>/dev/null;
}
在清單1的代碼中,$1 表示函數的第1個參數,在這裡第1個參數為要執行的SQL語句;pre_sql變數中的代碼是用來屏蔽dbaccess執行時輸出的作業記錄資訊,如果不加此設定,不會影響函數執行結果,只是執行過程中出現很多dbaccess作業記錄資訊。
echo "$sqltxt"|dbaccess test 2>/dev/null
表示用dbaccess命令串連test資料庫,然後執行$sqltxt語句,並將錯誤輸出到/dev/null。
上面函數在Shell中調用方式如下:
User_name=`ExecuteSqlSelect "select user_name from t_test;"`;
3.3. 利用Shell調用dbaccess匯出記錄
下面函數被調用後,會執行傳入的SQL並將結果匯出到一個檔案中。
清單2
ExecuteSqlUnloadFile()
{
sqltxt="$1";
unload_file="$2";
temp_file="$3";
pre_sql="unload to $unload_file delimiter ',' ";
post_sql="";
echo $pre_sql > $temp_file;
echo "$sqltxt" >> $temp_file;
echo $post_sql >> $temp_file;
dbaccess testdb < $temp_file 2>/dev/null;
rm -f $temp_file;
}
在清單2的代碼中,$1 、$2 、$3表示函數的第1個、第2個、第3個參數。
第1個參數為SQL語句。
第2個參數為輸出檔案名稱。
第3個參數為臨時檔案名稱(執行結束會被刪除)。
unload to $unload_file delimiter ',' 表示記錄匯出時存為檔案名稱為$unload_file的檔案,在這裡記錄之間的分隔字元用逗號表示。
$temp_file檔案為臨時檔案,用來儲存SQL語句,在函數執行末尾其內容將被刪除。
dbaccess testdb < $temp_file 2>/dev/null表示用dbaccess命令串連testdb資料庫,然後執行$temp_file檔案中的SQL語句,並將錯誤輸出到/dev/null。
上面函數在Shell中調用方式如下:
ExecuteSqlUnloadFile "select c1,c2 from t_test" "t_test.dat" "t_test.tmp";
3.4. 利用dbload匯入檔案
dbload的功能是將一至多個ASCII檔案中的資料傳送到一至多個已有的表中。
文法為:dbload [-d dbname ] [-c cfilename] [-l logfile] [-e errnum] [-n nnum] [-i inum] [-s] [-p] [-r] [-k] [-X]。
其中主要選項說明如下:
-d dbname 指定接收資料的資料庫名
-c cfilename 指定指定dbload命令檔案的檔案名稱
-l logfile 指定錯誤記錄檔檔案的檔案名稱
-r 在裝入資料期間允許其他使用者修改表中資料(裝入資料期間不封鎖表)
-s 指示dbload 檢查命令檔案中語句的文法,而不插入資料
-i inum 指示dbload忽略指定數目的行數
-n nnum 指示dbload在插入指定數目的新行後提交操作
-e errnum 指定dbload 中止前可讀入的壞行數
-p 如果壞行數超過了極限,給出提示資訊,請使用者指定解決方案
例如: dbload -d testdb -c load.ctl -n 10000 -l error.log。這個命令表示將按照load.ctl控制檔案的指示,載入資料到testdb 資料庫中, 每10000條記錄提交一次,錯誤資料將寫入error.log檔案。以下是load.ctl控制檔案的內容。
清單3
FILE crm.dat DELIMITER '|' 3;
INSERT INTO data_crm_list;
清單3中的內容表示將crm.dat資料檔案載入到data_crm_list表中,分隔字元是'|', 資料欄位個數為3。
4. Shell與Informix互動執行個體
通過第三章的介紹,讀者已經基本瞭解Shell與Informix的互動方式。在本章中,作者將通過一個具體執行個體展現Shell與Informix互動過程。
4.1. 情境概述
指令碼名稱:test.sh
示範步驟:
A:先在Informix中建立2個表,分別為t_test和t_test2;
t_test表結構:
CREATE TABLE t_test
(
user_code VARCHAR(20),
user_name VARCHAR(20),
user_desc VARCHAR(50)
) t_test2表結構:
CREATE TABLE t_test2
(
user_code VARCHAR(20),
user_name VARCHAR(20),
user_desc VARCHAR(50)
) B:在t_test中插入2條記錄;
insert into t_test values('1001','test','this is a test')
insert into t_test values('1002','guess','this is a test') C:在Linux終端下執行test.sh指令碼。
運行結果:
A:指令碼會讀取t_test表中的2條記錄,並匯出為檔案t_test.dat;
B:t_test.dat檔案被匯入t_test2表中,此時t_test2記錄數和t_test一樣。
4.2. 完整代碼和注釋
#!/usr/bin/env bash
DBTOOL="dbaccess"
DBCONNT="test"
#功能說明:執行SQL並將結果匯出到一個檔案中
#參數說明:
# 第1個參數為SQL語句
# 第2個參數為輸出檔案名稱
# 第3個參數為臨時檔案名稱(執行結束會被刪除)
ExecuteSqlUnloadFile()
{
sqltxt="$1";
unload_file="$2";
temp_file="$3";
pre_sql="SET LOCK MODE TO WAIT 10 ;unload to $unload_file delimiter ',' ";
post_sql="";
echo $pre_sql > $temp_file;
echo "$sqltxt" >> $temp_file;
echo $post_sql >> $temp_file;
$DBTOOL $DBCONNT < $temp_file 2>/dev/null;
rm -f $temp_file;
}
#功能說明:執行SQL
#參數說明:
# 第1個參數為SQL語句
ExecuteSqlSelect()
{
sqltxt="$1";
pre_sql="SET LOCK MODE TO WAIT 10 ;output to pipe cat without headings ";
sqltxt=$pre_sql"$sqltxt";
echo "$sqltxt"|$DBTOOL $DBCONNT 2>/dev/null;
}
#功能說明:去掉變數的前後空白
trim()
{
echo $1 |sed 's/^ \+//'|sed 's/ \+$//'
}
#功能說明:得到t_test指定記錄中某個欄位的值
get_username_bycode()
{
user_code="$1";
EXECSQL="select user_name
from t_test
where user_code="$user_code";";
echo $EXECSQL
user_name=`ExecuteSqlSelect "$EXECSQL"`;
user_name=`trim $user_name`;
echo "user_name:["$user_name"]";
}
#功能說明:得到t_test中所有記錄,並匯出為檔案t_test.dat
get_all_username()
{
EXECSQL="select user_code,user_name,user_desc
from t_test;";
echo $EXECSQL
ExecuteSqlUnloadFile "$EXECSQL" "t_test.dat" "username.tmp";
}
#功能說明:產生入庫設定檔
#參數說明:
# 第1個參數為需入庫的表名稱
# 第2個參數為待入庫的檔案名稱
# 第3個參數為檔案分隔字元
# 第4個參數為檔案列個數
make_loader()
{
table_name=$1
data_name=$2
sep=$3
tab_num=$4
echo "file \"$data_name\" delimiter \"$sep\" $tab_num;" > $CTL_FILE;
echo "insert into $table_name;" >> $CTL_FILE;
}
#功能說明:按照入庫配置要求,將資料匯入表中
#參數說明:
# 第1個參數為bad檔案
# 第2個參數為log檔案
start_loader()
{
badfile_name=$1;
logfile_name=$2;
#這裡的10000是指多少條資料commit一次,可以根據實際情況調節大小。
dbload -d $DBCONNT -c "$CTL_FILE" -l "$badfile_name" -n 10000;
}
run()
{
#得到使用者編號為1001的使用者名稱稱
get_username_bycode "1001";
#得到t_test表中使用者編號、使用者名稱稱、使用者描述資訊,並儲存到t_test.dat檔案中
get_all_username;
#通過awk將t_test.dat最後一列轉換為大寫字母
`cat t_test.dat | awk -F',' -v OFS=',' '{print $1,$2,toupper($3)}' > t_test2.dat`
CTL_FILE="./t_test2.ctl"
#產生入庫配置
make_loader "t_test2" "./t_test2.dat" "," "3";
#執行入庫
start_loader "./t_test2.bad" "./t_test2.log";
}
#--------------------主程式--------------------
run;
4.3. 運行結果與分析
test @ dwserver : /home/test /sgy $ ls -l
總計 4
-rwxr-xr-x 1 testtest 2683 05-04 14:37 test.sh
test @ dwserver : /home/test /sgy $ ./test.sh --------執行test.sh
select user_name from t_test where user_code=1001;----49行代碼輸出
user_name:[test] ----52行代碼輸出
select user_code,user_name,user_desc from t_test; ----59行代碼輸出
DBLOAD Load Utility INFORMIX-SQL Version 10.00.UC5 ---DBLOAD運行輸出
Copyright IBM Corporation 1996, 2004 All rights reserved
Software Serial Number AAA#B000000
Table t_test2 had 2 row(s) loaded into it.
test @ dwserver : /home/test /sgy $ ls -l
總計 16
-rwxr-xr-x 1 testdba 2683 05-04 14:37 test.sh
-rw-r--r-- 1 test dba 0 05-04 14:38 t_test2.bad
-rw-r--r-- 1 test dba 59 05-04 14:38 t_test2.ctl
-rw-r--r-- 1 test dba 51 05-04 14:38 t_test2.dat
-rw-r--r-- 1 test dba 53 05-04 14:38 t_test.dat
test @ dwserver : /home/test /sgy $ head t_test2.ctl ----入庫設定檔
file "./t_test2.dat" delimiter "," 3;
insert into t_test2;
test @ dwserver : /home/test /sgy $ head t_test.dat ----匯出的t_test記錄
1001,test,this is a test
1002,guess,this is a test
test @ dwserver : /home/test /sgy $ head t_test2.dat ----經過99行awk處理後的記錄
1001,test,THIS IS A TEST
1002,guess,THIS IS A TEST 運行結束後,t_test2表中多出2條記錄,且user_desc欄位的值為大寫。
結束語
本文主要介紹了Linux/Unix下Shell如何?Informix資料庫的互動。文章首先對Informix和Shell進行了簡單介紹,然後通過介紹dbaccess和dbload兩個應用程式的用法來使讀者對Shell和Informix互動有一個基本認識。文章最後以一個完整的執行個體來展示Shell和Informix的各種互動,使讀者加深理解,在例子中會用到awk、sed來對資料格式化,這些工具的加入使得Shell處理很多應用時更加強大,所以在實際各種應用中,Shell會結合awk、sed等工具來實現對資料庫中匯出的資訊格式化,或者在檔案匯入資料庫之前對檔案中記錄進行格式化。
作者介紹
張曉丹,IBM CDL軟體工程師, 具有豐富的自動化測試經驗、RQM應用經驗、BI項目測試經驗、以及Web application開發經驗。
程平平,IBM CDL 軟體工程師,主要從事 Optim Query Tuner 產品開發工作,在Eclipse外掛程式開發有一定的經驗。
王蘋, IBM CDL 軟體工程師,主要從事 DB2 for z/OS產品功能測試工作,在資料庫應用和自動化測試載入器開發方面有一定的經驗。
本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連結:http://www.linuxidc.com/Linux/2012-06/63345.htm