一、構造字符串
直接構造
STR_ZERO=hello
STR_FIRST="i am a string"
STR_SECOND='success'
重復多次
#repeat the first parm($1) by $2 times
strRepeat()
{
local x=$2
if [ "$x" == "" ]; then
x=0
fi
local STR_TEMP=""
while [ $x -ge 1 ];
do
STR_TEMP=`printf "%s%s" "$STR_TEMP" "$1"`
x=`expr $x - 1`
done
echo $STR_TEMP
}
舉例:
STR_REPEAT=`strRepeat "$USER_NAME" 3`
echo "repeat = $STR_REPEAT"
二、賦值與拷貝
直接賦值
與構造字符串一樣
USER_NAME=terry
從變量賦值
ALIASE_NAME=$USER_NAME
三、聯接
直接聯接兩個字符串
STR_TEMP=`printf "%s%s" "$STR_ZERO" "$USER_NAME"`
使用printf可以進行更復雜的聯接
四、求長
獲取字符串變量的長度:${#string}
求字符數(char)
COUNT_CHAR=`echo "$STR_FIRST" | wc -m`
echo $COUNT_CHAR
求字節數(byte)
COUNT_BYTE=`echo "$STR_FIRST" | wc -c`
echo $COUNT_BYTE
求字數(word)
COUNT_WORD=`echo "$STR_FIRST" | wc -w`
echo $COUNT_WORD
五、比較
相等比較 str1 = str2
不等比較 str1 != str2
舉例:
if [ "$USER_NAME" = "terry" ]; then
echo "I am terry"
fi
小于比較
#return 0 if the two string is equal, return 1 if $1 < $2, else 2strCompare() { local x=0 if [ "$1" != "$2" ]; then x=2 localTEMP=`printf "%s\n%s" "$1" "$2"` local TEMP2=`(echo "$1"; echo "$2") |sort` if [ "$TEMP" = "$TEMP2" ]; then x=1 fi fi echo $x }
六、測試
判空 -z str
判非空 -n str
是否為數字
# return 0 if the string is num, otherwise 1
strIsNum()
{
local RET=1
if [ -n "$1" ]; then
local STR_TEMP=`echo "$1" | sed 's/[0-9]//g'`
if [ -z "$STR_TEMP" ]; then
RET=0
fi
fi
echo $RET
}
舉例:
if [ -n "$USER_NAME" ]; then
echo "my name is NOT empty"
fi
echo `strIsNum "9980"`
七、分割
以符號+為準,將字符分割為左右兩部分
使用sed
舉例:
命令 date --rfc-3339 seconds 的輸出為
2007-04-14 15:09:47+08:00
取其+左邊的部分
date --rfc-3339 seconds | sed 's/+[0-9][0-9]:[0-9][0-9]//g'
輸出為
2007-04-14 15:09:47
取+右邊的部分
date --rfc-3339 seconds | sed 's/.*+//g'
輸出為
08:00
以空格為分割符的字符串分割
使用awk
舉例:
STR_FRUIT="Banana 0.89 100"
取第3字段
echo $STR_FRUIT | awk '{ print $3; }'
八、子字符串
字符串1是否為字符串2的子字符串
# return 0 is $1 is substring of $2, otherwise 1
strIsSubstring()
{
local x=1
case "$2" in
*$1*) x=0;;
esac
echo $x
}
Shell字符串截取
一、Linux shell 截取字符變量的前8位,有方法如下:
1.expr substr “$a” 1 8
2.echo $a|awk ‘{print substr(,1,8)}’
3.echo $a|cut -c1-8
4.echo $
5.expr $a : ‘\(.\\).*’
6.echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字符串截取
1、第一種方法:
- ${varible##*string} 從左向右截取最后一個string后的字符串
- ${varible#*string}從左向右截取第一個string后的字符串
- ${varible%%string*}從右向左截取最后一個string后的字符串
- ${varible%string*}從右向左截取第一個string后的字符串
“*”只是一個通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2、第二種方法:${varible:n1:n2}:截取變量varible從n1開始的n2個字符,組成一個子字符串。可以根據特定字符偏移和長度,使用另一種形式的變量擴展,來選擇特定子字符串。試著在 bash 中輸入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
這種形式的字符串截斷非常簡便,只需用冒號分開來指定起始字符和子字符串長度。
三、按照指定要求分割:
比如獲取后綴名
ls -al | cut -d “.” -f2
shell (bash) 比較運算符
運算符 |
描述 |
示例 |
文件比較運算符 |
-efilename |
如果filename存在,則為真 |
[ -e /var/log/syslog ] |
-dfilename |
如果filename為目錄,則為真 |
[ -d /tmp/mydir ] |
-ffilename |
如果filename為常規文件,則為真 |
[ -f /usr/bin/grep ] |
-Lfilename |
如果filename為符號鏈接,則為真 |
[ -L /usr/bin/grep ] |
-rfilename |
如果filename可讀,則為真 |
[ -r /var/log/syslog ] |
-wfilename |
如果filename可寫,則為真 |
[ -w /var/mytmp.txt ] |
-xfilename |
如果filename可執行,則為真 |
[ -L /usr/bin/grep ] |
filename1-ntfilename2 |
如果filename1比filename2新,則為真 |
[ /tmp/install/etc/services -nt /etc/services ] |
filename1-otfilename2 |
如果filename1比filename2舊,則為真 |
[ /boot/bzImage -ot arch/i386/boot/bzImage ] |
字符串比較運算符[size=-1](請注意引號的使用,這是防止空格擾亂代碼的好方法) |
-zstring |
如果string長度為零,則為真 |
[ -z "$myvar" ] |
-nstring |
如果string長度非零,則為真 |
[ -n "$myvar" ] |
string1=string2 |
如果string1與string2相同,則為真 |
[ "$myvar" = "one two three" ] |
string1!=string2 |
如果string1與string2不同,則為真 |
[ "$myvar" != "one two three" ] |
算術比較運算符 |
num1-eqnum2 |
等于 |
[ 3 -eq $mynum ] |
num1-nenum2 |
不等于 |
[ 3 -ne $mynum ] |
num1-ltnum2 |
小于 |
[ 3 -lt $mynum ] |
num1-lenum2 |
小于或等于 |
[ 3 -le $mynum ] |
num1-gtnum2 |
大于 |
[ 3 -gt $mynum ] |
num1-genum2 |
大于或等于 |
[ 3 -ge $mynum ] |
posted @
2011-03-04 18:13 xzc 閱讀(9091) |
評論 (2) |
編輯 收藏
#!/sbin/sh
######################################
## 名稱: infuser_load.sh
## 描述: 通用接口文件 導入數據庫
## 參數: owner table_name
## 作者: xxx
## 日期: 2011-03-04
######################################
##owner
owner=$1
##table_name
table_name=$2
##batchId
batchId=$3
##day_id
day_id=$4
##日期[YYYYMMDD]
DAYID=`date +'%Y%m%d'`
##月份[YYYYMM]
MONTHID=`date +'%Y%m'`
##shell文件目錄
sh_dir=/inffile/shell/
cd ${sh_dir}
##load文件###########################
##file_name
file_name=`sqlplus -s infuser/xxx@DATACK <<EOF
set heading off feedback off pagesize 0 verify off echo off
select replace(replace(to_char(file_name), '@DAYID@', '${DAYID}'), '@MONTHID@', '${MONTHID}')
from datackdb.inf_file_def
where owner = '${owner}'
and table_name = '${table_name}'
and state = '00A'
and rownum <= 1;
exit
EOF`
#echo "${file_name}"
##ctl_file
ctl_file=`sqlplus -s infuser/xxx@DATACK <<EOF
set heading off feedback off pagesize 0 verify off echo off
select replace(replace(to_char(ctl_file), '@DAYID@', '${DAYID}'), '@MONTHID@', '${MONTHID}')
from datackdb.inf_file_def
where owner = '${owner}'
and table_name = '${table_name}'
and state = '00A'
and rownum <= 1;
exit
EOF`
#echo "${ctl_file}"
infile=""
for fname in $file_name
do
if [ -r ${fname} ]
then
infile=$infile"INFILE '${fname}'\n"
fi
done
#是否包含@INFILE@字符串的判斷
if echo "$ctl_file"|grep -q "@INFILE@"
then
#分隔符前字符串
echo "${ctl_file%%@INFILE@*}" >${table_name}.ctl
#文件名
echo "${infile}" >>${table_name}.ctl
#分隔符后字符串
echo "${ctl_file##*@INFILE@}" >>${table_name}.ctl
else
echo "${ctl_file}" >${table_name}.ctl
fi
#導入數據
sqlldr infuser/infuser@DATACK control=${table_name}.ctl direct=y errors=1000
#刪除控制文件
#rm ${table_name}.ctl
#rm ${table_name}.log
##寫消息
sqlplus infuser/infuser@DATACK <<EOF
insert into datackdb.inf_data_msg (OWNER, TABLE_NAME, FWF_NO, LAN_ID, DAY_ID, STATE, STATE_DATE, COMMENTS)
values ('${owner}', '${table_name}', '${batchId}', -1, '${day_id}', '00A', sysdate, '');
exit
EOF
date +'%Y-%m-%d %T' >>param.txt
echo "$0 $*" >>param.txt
echo "$0 $* -- 成功"
posted @
2011-03-04 15:23 xzc 閱讀(552) |
評論 (0) |
編輯 收藏
#! /bin/bash
var1="hello"
var2="he"
#方法1
if [ ${var1:0:2} = $var2 ]
then
echo "1:include"
fi
#方法2
echo "$var1" |grep -q "$var2"
if [ $? -eq 0 ]
then
echo "2:include"
fi
#方法3
echo "$var1" |grep -q "$var2" && echo "include" ||echo "not"
#方法4
[[ "${var1/$var2/}" != "$var2" ]] && echo "include" || echo "not"
其他方法:
expr或awk的index函數
${var#...}
${var%...}
${var/.../...}
posted @
2011-03-04 15:16 xzc 閱讀(26435) |
評論 (1) |
編輯 收藏
shell判斷文件,目錄是否存在或者具有權限
www.firnow.com 時間 : 2009-03-04 作者:匿名 編輯:sky 點擊: 1632 [ 評論 ]
-
-
shell判斷文件,目錄是否存在或者具有權限
#!/bin/sh
myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"
#這里的-x 參數判斷$myPath是否存在并且是否具有可執行權限
if [ ! -x "$myPath"]; then
mkdir "$myPath"
fi
#這里的-d 參數判斷$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi
#這里的-f參數判斷$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi
#其他參數還有-n,-n是判斷一個變量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi
#兩個變量判斷是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 not eq $var2'
fi
posted @
2011-03-04 15:14 xzc 閱讀(1376) |
評論 (1) |
編輯 收藏
shell字符串的截取的問題:
一、Linux shell 截取字符變量的前8位,有方法如下:
1.expr substr “$a” 1 8
2.echo $a|awk ‘{print substr(,1,8)}’
3.echo $a|cut -c1-8
4.echo $
5.expr $a : ‘\(.\\).*’
6.echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字符串截取
1、第一種方法:
${varible##*string} 從左向右截取最后一個string后的字符串
${varible#*string}從左向右截取第一個string后的字符串
${varible%%string*}從右向左截取最后一個string后的字符串
${varible%string*}從右向左截取第一個string后的字符串
“*”只是一個通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2、第二種方法:${varible:n1:n2}:截取變量varible從n1到n2之間的字符串。
可以根據特定字符偏移和長度,使用另一種形式的變量擴展,來選擇特定子字符串。試著在 bash 中輸入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
這種形式的字符串截斷非常簡便,只需用冒號分開來指定起始字符和子字符串長度。
三、按照指定要求分割:
比如獲取后綴名
ls -al | cut -d “.” -f2
應用心得:
$MYVAR="12|dadg"
echo ${MYVAR##*|} #打印分隔符后的字符串
dafa
echo ${MYVAR%%|*} #打印分隔符前的字符串
12
posted @
2011-03-04 15:09 xzc 閱讀(3604) |
評論 (1) |
編輯 收藏
awk內置字符串函數詳解(轉)
awk提供了許多強大的字符串函數,見下表:
awk內置字符串函數
gsub(r,s) 在整個$0中用s替代r
gsub(r,s,t) 在整個t中用s替代r
index(s,t)
返回s中字符串t的第一位置
length(s)
返回s長度
match(s,r)
測試s是否包含匹配r的字符串
split(s,a,fs) 在fs上將s分成序列a
sprint(fmt,exp) 返回經fmt格式化后的exp
sub(r,s)
用$0中最左邊最長的子串代替s
substr(s,p) 返回字符串s中從p開始的后綴部分
substr(s,p,n)
返回字符串s中從p開始長度為n的后綴部分
詳細說明一下各個函數的使用方法。
gsub函數有點類似于sed查找和替換。它允許替換一個字符串或字符為另一個字符串或字符,并以正則表達式的形式執行。第一個函數作用于記錄$0,第二個gsub函數允許指定目標,然而,如果未指定目標,缺省為$0。
index(s,t)函數返回目標字符串s中查詢字符串t的首位置。length函數返回字符串s字符
長度。match函數測試字符串s是否包含一個正則表達式r定義的匹配。split使用域分隔符fs將
字符串s劃分為指定序列a。sprint函數類似于printf函數(以后涉及),返回基本輸出格式fmt的
結果字符串exp。sub(r,s)函數將用s替代$0中最左邊最長的子串,該子串被(r)匹配。
sub(s,p)返回字符串s在位置p后的后綴。substr(s,p,n)同上,并指定子串長度為n。
現在看一看awk中這些字符串函數的功能。
1.gsub
要在整個記錄中替換一個字符串為另一個,使用正則表達式格式,/目標模式/,替換模式
/。例如改變學生序號4842到4899:
$ awk 'gsub('4842/, 4899) {print $0}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26
2.index
查詢字符串s中t出現的第一位置。必須用雙引號將字符串括起來。例如返回目標字符串
Bunny中ny出現的第一位置,即字符個數。
$ awk 'BEGIN {print index("Bunny", "ny")} grade.txt
4
3.length
返回所需字符串長度,例如檢驗字符串J.Troll返回名字及其長度,即人名構成的字符個
數。
$ awk '$1=="J.Troll" {print length($1) " "$1}' grade.txt
7 J.Troll
還有一種方法,這里字符串加雙引號。
$ awk 'BEGIN {print length("A FEW GOOD MEN")}'
14
4.match
match測試目標字符串是否包含查找字符的一部分。可以對查找部分使用正則表達式,返
回值為成功出現的字符排列數。如果未找到,返回0,第一個例子在ANCD中查找d。因其不
存在,所以返回0。第二個例子在ANCD中查找D。因其存在,所以返回ANCD中D出現的首位
置字符數。第三個例子在學生J.Lulu中查找u。
$ awk '{BEGIN {print match("ANCD", /d/)}'
0
$ awk '{BEGIN {print match("ANCD", /C/)}'
3
$ awk '$1=="J.Lulu" {print match($1, "u")} grade.txt
4
5.split
使用split返回字符串數組元素個數。工作方式如下:如果有一字符串,包含一指定分隔
符-,例如AD2-KP9-JU2-LP-1,將之劃分成一個數組。使用split,指定分隔符及數組名。此
例中,命令格式為("AD2-KP9-JU2-LP-1",parts_array,"-"),split然后返回數組下標數,這
里結果為4。
還有一個例子使用不同的分隔符。
$ awk '{BEGIN {print split("123#456#678", myarray, "#")}'
3
這個例子中,split返回數組myarray的下標數。數組myarray取值如下:
Myarray[1]="123"
Myarray[2]="456"
Myarray[3]="789"
6.sub
使用sub發現并替換模式的第一次出現位置。字符串STR包含‘popedpopopill’,執行下
列sub命令sub(/op/,"op",STR)。模式op第一次出現時,進行替換操作,返回結果如下:
‘pOPedpopepill’。
假如grade.txt文件中,學生J.Troll的記錄有兩個值一樣,“目前級別分”與“最高級別分”。只
改變第一個為29,第二個仍為24不動,操作命令為sub(/26/,"29",$0),只替換第一個出現
24的位置。
$ awk '$1=="J.Troll" sub(/26/, "29", $0)' grade.txt
L.Troll 07/99 4842 Brown-3 12 29 26
L.Transley 05/99 4712 Brown-2 12 30 28
7.substr
substr是一個很有用的函數。它按照起始位置及長度返回字符串的一部分。例子如下:
$ awk '$1=="L.Transley" {print substr($1, 1,5)}' grade.txt
L.Tan
上面例子中,指定在域1的第一個字符開始,返回其前面5個字符。
如果給定長度值遠大于字符串長度, awk將從起始位置返回所有字符,要抽取L.Tansley的姓,只需從第3個字符開始返回長度為7。可以輸入長度99,awk返回結果相同。
$ awk '{$1=="L.Transley" {print substr($1, 3,99)}' grade.txt
Transley
substr的另一種形式是返回字符串后綴或指定位置后面字符。這里需要給出指定字符串及其返回字串的起始位置。例如,從文本文件中抽取姓氏,需操作域1,并從第三個字符開始:
$ awk '{print substr($1, 3)}' grade.txt
Troll
Transley
還有一個例子,在BEGIN部分定義字符串,在END部分返回從第t個字符開始抽取的子串。
$ awk '{BEGIN STR="A FEW GOOD MEN"} END {print substr(STR,7)) grade.txt
GOOD MEN
8.從shell中向awk傳入字符串
awk腳本大多只有一行,其中很少是字符串表示的,這一點通過將變量傳入awk命令行會變得很容易。現就其基本原理講述一些例子。
使用管道將字符串stand-by傳入awk,返回其長度。
$ echo "Stand-by" | awk '{print length($0)}'
8
設置文件名為一變量,管道輸出到awk,返回不帶擴展名的文件名。
$ STR="mydoc.txt"
$ echo $STR | awk '{print subst($STR, 1, 5)}'
mydoc
設置文件名為一變量,管道輸出到awk,只返回其擴展名。
$ STR="mydoc.txt"
$ echo $STR | awk '{print substr($STR, 7)}'
txt
posted @
2011-03-03 17:18 xzc 閱讀(1587) |
評論 (2) |
編輯 收藏
作者:北南南北
來自:LinuxSir.Org
摘要: 本文講述幾種常用文件內容的查看工具,比如cat、more、less、head、tail等,把這些工具最常用的參數、動作介紹給新手,能讓新手在短短的幾分鐘內上手運用。此文獻給面對黑色的控制臺不知所措的弟兄。
目錄
+++++++++++++++++++++++++++++++++++++
正文
+++++++++++++++++++++++++++++++++++++
1、cat 顯示文件連接文件內容的工具;
cat 是一個文本文件查看和連接工具。查看一個文件的內容,用cat比較簡單,就是cat 后面直接接文件名。
比如:
[root@localhost ~]# cat /etc/fstab
為了便于新手弟兄靈活掌握這個工具,我們多說一點常用的參數;
1.0 cat 語法結構;
cat [選項] [文件]...
選項
-A, --show-all 等價于 -vET
-b, --number-nonblank 對非空輸出行編號
-e 等價于 -vE
-E, --show-ends 在每行結束處顯示 $
-n, --number 對輸出的所有行編號
-s, --squeeze-blank 不輸出多行空行
-t 與 -vT 等價
-T, --show-tabs 將跳格字符顯示為 ^I
-u (被忽略)
-v, --show-nonprinting 使用 ^ 和 M- 引用,除了 LFD 和 TAB 之外
--help 顯示此幫助信息并離開
1.1 cat 查看文件內容實例;
[root@localhost ~]# cat /etc/profile 注:查看/etc/目錄下的profile文件內容;
[root@localhost ~]# cat -b /etc/fstab 注:查看/etc/目錄下的profile內容,并且對非空白行進行編號,行號從1開始;
[root@localhost ~]# cat -n /etc/profile 注:對/etc目錄中的profile的所有的行(包括空白行)進行編號輸出顯示;
[root@localhost ~]# cat -E /etc/profile 注:查看/etc/下的profile內容,并且在每行的結尾處附加$符號;
cat 加參數-n 和nl工具差不多,文件內容輸出的同時,都會在每行前面加上行號;
[root@localhost ~]# cat -n /etc/profile
[root@localhost ~]# nl /etc/profile
cat 可以同時顯示多個文件的內容,比如我們可以在一個cat命令上同時顯示兩個文件的內容;
[root@localhost ~]# cat /etc/fstab /etc/profile
cat 對于內容極大的文件來說,可以通過管道|傳送到more 工具,然后一頁一頁的查看;
[root@localhost ~]# cat /etc/fstab /etc/profile | more
1.2 cat 的創建、連接文件功能實例;
cat 有創建文件的功能,創建文件后,要以EOF或STOP結束;
[root@localhost ~]# cat > linuxsir.org.txt << EOF 注:創建linuxsir.org.txt文件;
> 我來測試 cat 創建文件,并且為文件輸入內容; 注:這是為linuxsir.org.txt文件輸入內容;
> 北南南北 測試; 注:這是為linuxsir.org.txt文件輸入內容;
> EOF 注:退出編輯狀態;
[root@localhost ~]# cat linuxsir.org.txt 注:我們查看一下linuxsir.org.txt文件的內容;
我來測試 cat 創建文件,并且為文件輸入內容;
北南南北 測試;
cat 還有向已存在的文件追加內容的功能;
[root@localhost ~]# cat linuxsir.txt 注:查看已存在的文件linuxsir.txt 內容;
I am BeiNanNanBei From LinuxSir.Org . 注:內容行
我正在為cat命令寫文檔
[root@localhost ~]# cat >> linuxsir.txt << EOF 注:我們向linuxsir.txt文件追加內容;
> 我來測試cat向文檔追加內容的功能; 注:這是追回的內容
> OK?
> OK~
> 北南 呈上
> EOF 注:以EOF退出;
[root@localhost ~]# cat linuxsir.txt 注:查看文件內容,看是否追回成功。
I am BeiNanNanBei From LinuxSir.Org .
我正在為cat命令寫文檔
我來測試cat向文檔追加內容的功能;
OK?
OK~
北南 呈上
cat 連接多個文件的內容并且輸出到一個新文件中;
假設我們有sir01.txt、sir02.tx和sir03.txt ,并且內容如下;
[root@localhost ~]# cat sir01.txt
123456
i am testing
[root@localhost ~]# cat sir02.txt
56789
BeiNan Tested
[root@localhost ~]# cat sir03.txt
09876
linuxsir.org testing
我想通過cat 把sir01.txt、sir02.txt及sir03.txt 三個文件連接在一起(也就是說把這三個文件的內容都接在一起)并輸出到一個新的文件sir04.txt 中。
注意:其原理是把三個文件的內容連接起來,然后創建sir04.txt文件,并且把幾個文件的內容同時寫入sir04.txt中。特別值得一提的是,如果您輸入到一個已經存在的sir04.txt 文件,會把sir04.txt內容清空。
[root@localhost ~]# cat sir01.txt sir02.txt sir03.txt > sir04.txt
[root@localhost ~]# more sir04.txt
123456
i am testing
56789
BeiNan Tested
09876
linuxsir.org testing
cat 把一個或多個已存在的文件內容,追加到一個已存在的文件中
[root@localhost ~]# cat sir00.txt
linuxsir.org forever
[root@localhost ~]# cat sir01.txt sir02.txt sir03.txt >> sir00.txt
[root@localhost ~]# cat sir00.txt
linuxsir.org forever
123456
i am testing
56789
BeiNan Tested
09876
linuxsir.org testing
警告:我們要知道>意思是創建,>>是追加。千萬不要弄混了。造成失誤可不是鬧著玩的;
2、more 文件內容或輸出查看工具;
more 是我們最常用的工具之一,最常用的就是顯示輸出的內容,然后根據窗口的大小進行分頁顯示,然后還能提示文件的百分比;
[root@localhost ~]# more /etc/profile
2.1 more 的語法、參數和命令;
more [參數選項] [文件]
參數如下:
+num 從第num行開始顯示;
-num 定義屏幕大小,為num行;
+/pattern 從pattern 前兩行開始顯示;
-c 從頂部清屏然后顯示;
-d 提示Press space to continue, 'q' to quit.(按空格鍵繼續,按q鍵退出),禁用響鈴功能;
-l 忽略Ctrl+l (換頁)字符;
-p 通過清除窗口而不是滾屏來對文件進行換頁。和-c參數有點相似;
-s 把連續的多個空行顯示為一行;
-u 把文件內容中的下劃線去掉
退出more的動作指令是q
2.2 more 的參數應用舉例;
[root@localhost ~]# more -dc /etc/profile 注:顯示提示,并從終端或控制臺頂部顯示;
[root@localhost ~]# more +4 /etc/profile 注:從profile的第4行開始顯示;
[root@localhost ~]# more -4 /etc/profile 注:每屏顯示4行;
[root@localhost ~]# more +/MAIL /etc/profile 注:從profile中的第一個MAIL單詞的前兩行開始顯示;
2.3 more 的動作指令;
我們查看一個內容較大的文件時,要用到more的動作指令,比如ctrl+f(或空格鍵) 是向下顯示一屏,ctrl+b是返回上一屏; Enter鍵可以向下滾動顯示n行,要通過定,默認為1行;
我們只說幾個常用的; 自己嘗試一下就知道了;
Enter 向下n行,需要定義,默認為1行;
Ctrl+f 向下滾動一屏;
空格鍵 向下滾動一屏;
Ctrl+b 返回上一屏;
= 輸出當前行的行號;
:f 輸出文件名和當前行的行號;
v 調用vi編輯器;
! 命令 調用Shell,并執行命令;
q 退出more
當我們查看某一文件時,想調用vi來編輯它,不要忘記了v動作指令,這是比較方便的;
2.4 其它命令通過管道和more結合的運用例子;
比如我們列一個目錄下的文件,由于內容太多,我們應該學會用more來分頁顯示。這得和管道 | 結合起來,比如:
[root@localhost ~]# ls -l /etc |more
3、less 查看文件內容 工具;
less 工具也是對文件或其它輸出進行分頁顯示的工具,應該說是linux正統查看文件內容的工具,功能極其強大;您是初學者,我建議您用less。由于less的內容太多,我們把最常用的介紹一下;
3.1 less的語法格式;
less [參數] 文件
常用參數
-c 從頂部(從上到下)刷新屏幕,并顯示文件內容。而不是通過底部滾動完成刷新;
-f 強制打開文件,二進制文件顯示時,不提示警告;
-i 搜索時忽略大小寫;除非搜索串中包含大寫字母;
-I 搜索時忽略大小寫,除非搜索串中包含小寫字母;
-m 顯示讀取文件的百分比;
-M 顯法讀取文件的百分比、行號及總行數;
-N 在每行前輸出行號;
-p pattern 搜索pattern;比如在/etc/profile搜索單詞MAIL,就用 less -p MAIL /etc/profile
-s 把連續多個空白行作為一個空白行顯示;
-Q 在終端下不響鈴;
比如:我們在顯示/etc/profile的內容時,讓其顯示行號;
[root@localhost ~]# less -N /etc/profile
3.2 less的動作命令;
進入less后,我們得學幾個動作,這樣更方便 我們查閱文件內容;最應該記住的命令就是q,這個能讓less終止查看文件退出;
動作
回車鍵 向下移動一行;
y 向上移動一行;
空格鍵 向下滾動一屏;
b 向上滾動一屏;
d 向下滾動半屏;
h less的幫助;
u 向上洋動半屏;
w 可以指定顯示哪行開始顯示,是從指定數字的下一行顯示;比如指定的是6,那就從第7行顯示;
g 跳到第一行;
G 跳到最后一行;
p n% 跳到n%,比如 10%,也就是說比整個文件內容的10%處開始顯示;
/pattern 搜索pattern ,比如 /MAIL表示在文件中搜索MAIL單詞;
v 調用vi編輯器;
q 退出less
!command 調用SHELL,可以運行命令;比如!ls 顯示當前列當前目錄下的所有文件;
就less的動作來說,內容太多了,用的時候查一查man less是最好的。在這里就不舉例子了;
4、head 工具,顯示文件內容的前幾行;
head 是顯示一個文件的內容的前多少行;
用法比較簡單;
head -n 行數值 文件名;
比如我們顯示/etc/profile的前10行內容,應該是:
[root@localhost ~]# head -n 10 /etc/profile
5、tail 工具,顯示文件內容的最后幾行;
tail 是顯示一個文件的內容的前多少行;
用法比較簡單;
tail -n 行數值 文件名;
比如我們顯示/etc/profile的最后5行內容,應該是:
[root@localhost ~]# tail -n 5 /etc/profile
posted @
2011-01-18 14:43 xzc 閱讀(1153) |
評論 (4) |
編輯 收藏
Oracle中不同啟動和關閉方式的區別
Oracle數據庫提供了幾種不同的數據庫啟動和關閉方式,本文將周詳介紹這些啟動和關閉方式之間的區別連同他們各自不同的功能。
一、啟動和關閉Oracle數據庫
對于大多數Oracle DBA來說,啟動和關閉Oracle數據庫最常用的方式就是在命令行方式下的Server Manager。從Oracle 8i以后,系統將Server Manager的任何功能都集中到了SQL*Plus中,也就是說從8i以后對于數據庫的啟動和關閉能夠直接通過SQL*Plus來完成,而不再另外需要Server Manager,但系統為了保持向下兼容,依舊保留了Server Manager工具。另外也可通過圖像用戶工具(GUI)的Oracle Enterprise Manager來完成系統的啟動和關閉,圖像用戶界面Instance Manager很簡單,這里不再詳述。
要啟動和關閉數據庫,必須要以具備Oracle 管理員權限的用戶登陸,通常也就是以具備SYSDBA權限的用戶登陸。一般我們常用INTERNAL用戶來啟動和關閉數據庫(INTERNAL用戶實際上是SYS用戶以SYSDBA連接的同義詞)。Oracle數據庫的新版本將逐步淘汰INTERNAL這個內部用戶,所以我們最好還是配置DBA用戶具備SYSDBA權限。
二、數據庫的啟動(STARTUP)
啟動一個數據庫需要三個步驟:
1、 創建一個Oracle實例(非安裝階段)
2、 由實例安裝數據庫(安裝階段)
3、 打開數據庫(打開階段)
在Startup命令中,能夠通過不同的選項來控制數據庫的不同啟動步驟。
1、STARTUP NOMOUNT
NOMOUNT選項僅僅創建一個Oracle實例。讀取init.ora初始化參數文檔、啟動后臺進程、初始化系統全局區(SGA)。Init.ora文檔定義了實例的配置,包括內存結構的大小和啟動后臺進程的數量和類型等。實例名根據Oracle_SID配置,不一定要和打開的數據庫名稱相同。當實例打開后,系統將顯示一個SGA內存結構和大小的列表,如下所示:
SQL> startup nomount
ORACLE 例程已啟動。
Total System Global Area 35431692 bytes
Fixed Size 70924 bytes
Variable Size 18505728 bytes
Database Buffers 16777216 bytes
Redo Buffers 77824 bytes
2、STARTUP MOUNT
該命令創建實例并且安裝數據庫,但沒有打開數據庫。Oracle系統讀取控制文檔中關于數據文檔和重作日志文檔的內容,但并不打開該文檔。這種打開方式常在數據庫維護操作中使用,如對數據文檔的更名、改變重作日志連同打開歸檔方式等。在這種打開方式下,除了能夠看到SGA系統列表以外,系統還會給出"數據庫裝載完畢"的提示。
3、STARTUP
該命令完成創建實例、安裝實例和打開數據庫的任何三個步驟。此時數據庫使數據文檔和重作日志文檔在線,通常還會請求一個或是多個回滾段。這時系統除了能夠看到前面Startup Mount方式下的任何提示外,還會給出一個"數據庫已打開"的提示。此時,數據庫系統處于正常工作狀態,能夠接受用戶請求。
假如采用STARTUP NOMOUNT或是STARTUP MOUNT的數據庫打開命令方式,必須采用ALTER DATABASE命令來執行打開數據庫的操作。例如,假如您以STARTUP NOMOUNT方式打開數據庫,也就是說實例已創建,但是數據庫沒有安裝和打開。這是必須運行下面的兩條命令,數據庫才能正確啟動。
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;
而假如以STARTUP MOUNT方式啟動數據庫,只需要運行下面一條命令即能夠打開數據庫:
ALTER DATABASE OPEN.
4、其他打開方式
除了前面介紹的三種數據庫打開方式選項外,更有另外其他的一些選項。
(1) STARTUP RESTRICT
這種方式下,數據庫將被成功打開,但僅僅允許一些特權用戶(具備DBA角色的用戶)才能夠使用數據庫。這種方式常用來對數據庫進行維護,如數據的導入/導出操作時不希望有其他用戶連接到數據庫操作數據。
(2) STARTUP FORCE
該命令其實是強行關閉數據庫(shutdown abort)和啟動數據庫(startup)兩條命令的一個綜合。該命令僅在關閉數據庫碰到問題不能關閉數據庫時采用。
(3) ALTER DATABASE OPEN READ ONLY;
該命令在創建實例連同安裝數據庫后,以只讀方式打開數據庫。對于那些僅僅提供查詢功能的產品數據庫能夠采用這種方式打開。
三、數據庫的關閉(SHUTDOWN)
對于數據庫的關閉,有四種不同的關閉選項,下面對其進行一一介紹。
1、SHUTDOWN NORMAL
這是數據庫關閉SHUTDOWN命令的確省選項。也就是說假如您發出SHUTDOWN這樣的命令,也即是SHUTDOWN NORNAL的意思。
發出該命令后,任何新的連接都將再不允許連接到數據庫。在數據庫關閉之前,Oracle將等待現在連接的任何用戶都從數據庫中退出后才開始關閉數據庫。采用這種方式關閉數據庫,在下一次啟動時無需進行任何的實例恢復。但需要注意一點的是,采用這種方式,也許關閉一個數據庫需要幾天時間,也許更長。
2、SHUTDOWN IMMEDIATE
這是我們常用的一種關閉數據庫的方式,想很快地關閉數據庫,但又想讓數據庫干凈的關閉,常采用這種方式。
當前正在被Oracle處理的SQL語句立即中斷,系統中任何沒有提交的事務全部回滾。假如系統中存在一個很長的未提交的事務,采用這種方式關閉數據庫也需要一段時間(該事務回滾時間)。系統不等待連接到數據庫的任何用戶退出系統,強行回滾當前任何的活動事務,然后斷開任何的連接用戶。
3、SHUTDOWN TRANSACTIONAL
該選項僅在Oracle 8i后才能夠使用。該命令常用來計劃關閉數據庫,他使當前連接到系統且正在活動的事務執行完畢,運行該命令后,任何新的連接和事務都是不允許的。在任何活動的事務完成后,數據庫將和SHUTDOWN IMMEDIATE同樣的方式關閉數據庫。
4、SHUTDOWN ABORT
這是關閉數據庫的最后一招,也是在沒有任何辦法關閉數據庫的情況下才不得不采用的方式,一般不要采用。假如下列情況出現時能夠考慮采用這種方式關閉數據庫。
1、 數據庫處于一種非正常工作狀態,不能用shutdown normal或shutdown immediate這樣的命令關閉數據庫;
2、 需要立即關閉數據庫;
3、 在啟動數據庫實例時碰到問題;
任何正在運行的SQL語句都將立即中止。任何未提交的事務將不回滾。Oracle也不等待現在連接到數據庫的用戶退出系統。下一次啟動數據庫時需要實例恢復,因此,下一次啟動可能比平時需要更多的時間。
表1能夠清楚地看到上述四種不同關閉數據庫的區別和聯系。
關閉方式 A I T N
允許新的連接 × × × ×
等待直到當前會話中止 × × × √
等待直到當前事務中止 × × √ √
強制CheckPoint,關閉任何文檔 × √ √ √
其中:A-Abort I-Immediate T-Transaction N-Nornal
pl/sql developer的Commander Windows下執行shutdown命令報“ORA-00900: 無效 SQL 語句”,
但在服務器本地sqlplus下卻可以執行關閉數據庫命令,PL/SQL DEVELOPER只支持部分的sql*plus命令?
另外在數據庫unmount(instance 已經啟動)的情況下,PL/SQL DEVELOPER無法連接上,
報“ORA-12528: TNS:監聽程序:所有適用例程都無法建立新連接”。
在instance已經啟動但數據庫還沒mount的情況下PL/SQL DEVELOPER等客戶端都無法連接到實例上
如何查看Oracle當前數據庫實例名
數據庫實例名在編程的很多地方都需要用到,配置數據庫的jdbc:oracle:thin:@192.168.2.1:1521:WW ,還有sqlPlus的連接字符串中也需要用到 conn sys/password@WW as sysdba; 如何查看當前數據庫實例名呢?方式有三:
·使用SQL語句:select instance_name from v$instance;
·使用show命令:show parameter instance
·查看參數文件:查看init.ora文件
posted @
2011-01-04 10:32 xzc 閱讀(2458) |
評論 (0) |
編輯 收藏
[摘要] 在實際的應用中,有時候工作數據庫需要重新啟動。本文介紹了一個特別實用的操作步驟,希望對大家有所幫助。
[關鍵字]
Oracle 重啟
在實際的應用中,有時候工作數據庫需要重新啟動。本文介紹了一個特別實用的操作步驟,希望對大家有所幫助。
1. 停應用層的各種程序
2. 停Oralce的監聽進程
$ lsnrctl stop
3. 在獨占的系統用戶下,備份控制文件:
$ sqlplus "/as sysdba"
SQL> alter database backup controlfile to trace;
4. 在獨占的系統用戶下,手工切換重作日志文件,確保當前已修改過的數據存入文件:
SQL> alter system switch logfile;
5. 在獨占的系統用戶下,運行下面SQL語句,生成殺數據庫用戶連接的kill_all_session.sql文件:
SQL> set head off;
SQL> set feedback off;
SQL> set newpage none;
SQL> spool ./kill_session.sql
SQL> select 'alter system kill session ''' sid ',' serial# ''';' from v$session where username is not null;
SQL> spool off;
6. 在獨占的系統用戶下,執行殺數據庫用戶連接的kill_session.sql文件
SQL> @./kill_session.sql
7. 在獨占的系統用戶下,用immediate方式關閉數據庫:
SQL> shutdown immediate;
或者
SVRMGRL> shutdown immediate;
8. 啟動oralce的監聽進程
$ lsnrctl start
9. 進入獨占的系統用戶下,啟動Oralce數據庫
$ sqlplus /nolog
SQL> connect / as sysdba
SQL> startup;
或者
$ svrmgrl
SVRMGRL> connect internal;
SVRMGRL> startup;
10.啟動應用層的各種程序
posted @
2011-01-04 10:10 xzc 閱讀(758) |
評論 (3) |
編輯 收藏
轉自:http://www.javaeye.com/topic/321719
方案理念--四化理念
- 數據規格化
- 處理自動化
- 信息集中化
- 操作人性化
架構
通過視圖實現來至兩個不同數據庫的表的結構完全一致, 在結構完全相同的兩個表之間進行數據同步, 問題變得相當簡單. 同步代碼如下.
ETL
---初始同步
delete from ods_table;
insert into v_table
select * from db_table;
commit;
---新增同步
insert into v_table
select * from db_table t
where t.id not in (select id from v_table);
commit;
---變更同步
update ods_table t
set t.c_number = (select db.c_number from db_table db where db.id = t.id)
where t.c_number != (select db.c_number from db_table db where db.id = t.id);
commit;
實現兩個表結構完全一致的方法如下
---建表
CREATE SEQUENCE SEQ_ETL_INCREASE_ID
INCREMENT BY 1
START WITH 1
NOCACHE;
/*==============================================================*/
/* Table: ETL_TABLES */
/*==============================================================*/
CREATE TABLE ETL_TABLES (
"ID" NUMBER DEFAULT -1 NOT NULL,
"TABLE_NAME" VARCHAR2(100) NOT NULL,
"TABLE_TYPE" VARCHAR2(30) NOT NULL,
"TABLE_ROOT_IN" VARCHAR2(30),
"TABLE_NEED_CREATE_VIEW" NUMBER DEFAULT 1,
"TABLE_CREATE_VIEW_NAME_PREFIX" VARCHAR2(30) DEFAULT 'v',
"DB_LINK_NAME" VARCHAR2(100),
"CURRENT_VERSION" NUMBER DEFAULT 1 NOT NULL,
"VERSION_HISTORY" VARCHAR2(3000) DEFAULT 'init input' NOT NULL,
"DEVELOP_DATE" DATE DEFAULT SYSDATE NOT NULL,
"DEVELOP_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"LAST_MAINTAIN_DATE" DATE DEFAULT SYSDATE NOT NULL,
"LAST_MAINTAIN_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"MEMO" VARCHAR2(500),
"STATUS" NUMBER DEFAULT 1,
CONSTRAINT PK_ETL_TABLES PRIMARY KEY ("ID")
);
COMMENT ON TABLE ETL_TABLES IS
'此表用于維護ETL涉及到所有表, 包括:
1, db---業務系統數據庫
2, ods---操作數據數據庫
3, dw---數據倉庫';
/*==============================================================*/
/* Table: ETL_VIEWS */
/*==============================================================*/
CREATE TABLE ETL_VIEWS (
"ID" NUMBER DEFAULT -1 NOT NULL,
"VIEW_NAME" VARCHAR2(100) NOT NULL,
"VIEW_TYPE" VARCHAR2(30) NOT NULL,
"VIEW_ROOT_IN" VARCHAR2(30),
"VIEW_SELECT" VARCHAR2(4000) NOT NULL,
"VIEW_FROM" VARCHAR2(600) NOT NULL,
"VIEW_WHERE" VARCHAR2(2000),
"VIEW_ORDER_BY" VARCHAR2(600),
"VIEW_GROUP_BY" VARCHAR2(600),
"VIEW_HAVING" VARCHAR2(600),
"VIEW_DB_LINK_NAME" VARCHAR2(100),
"CURRENT_VERSION" NUMBER DEFAULT 1 NOT NULL,
"VERSION_HISTORY" VARCHAR2(3000) DEFAULT 'init input' NOT NULL,
"DEVELOP_DATE" DATE DEFAULT SYSDATE NOT NULL,
"DEVELOP_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"LAST_MAINTAIN_DATE" DATE DEFAULT SYSDATE NOT NULL,
"LAST_MAINTAIN_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"MEMO" VARCHAR2(500),
"STATUS" NUMBER DEFAULT 1,
CONSTRAINT PK_ETL_VIEWS PRIMARY KEY ("ID")
);
COMMENT ON TABLE ETL_VIEWS IS
'此表用于維護ETL涉及到所有視圖, 包括:
1, v1---db表中與ods對應到視圖
2, v2---ods表中與db對應到視圖
3, v3---ods表中與dw對應到視圖
4, v4---dw表中與ods中對應到視圖';
/*==============================================================*/
/* Table: ETLS */
/*==============================================================*/
CREATE TABLE ETLS (
"ID" NUMBER NOT NULL,
"ETL_NAME" VARCHAR2(300) NOT NULL,
"ETL_TYPE" VARCHAR2(30) NOT NULL,
"ETL_SRC_VIEW_OR_TABLE" NUMBER NOT NULL,
"ETL_DES_VIEW_OR_TABLE" NUMBER NOT NULL,
"ETL_INIT_ENABLE" NUMBER(1) DEFAULT 1 NOT NULL,
"ETL_ADD_ENABLE" NUMBER(1) DEFAULT 1 NOT NULL,
"ETL_CHARGE_ENABLE" NUMBER(1) DEFAULT 1 NOT NULL,
"CURRENT_VERSION" NUMBER DEFAULT 1 NOT NULL,
"VERSION_HISTORY" VARCHAR2(3000) DEFAULT 'init input' NOT NULL,
"DEVELOP_DATE" DATE DEFAULT SYSDATE NOT NULL,
"DEVELOP_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"LAST_MAINTAIN_DATE" DATE DEFAULT SYSDATE NOT NULL,
"LAST_MAINTAIN_BY" VARCHAR2(100) DEFAULT 'cyyan@isoftstone' NOT NULL,
"MEMO" VARCHAR2(500),
"STATUS" NUMBER DEFAULT 1,
CONSTRAINT PK_ETLS PRIMARY KEY ("ID")
);
COMMENT ON TABLE ETLS IS
'此表用于維護ETL轉換時設計到源表和目的表
源表(或視圖)--->目的表(或視圖)-
(推薦全部使用視圖, 視圖具有更過到靈活性, 而且更統一)
整體架構是在完全相同兩張表(或視圖)之間進行同步處理
規范:
1, 源表(或視圖)-和目的表(或視圖)-完全相同
2, 目的視圖必須是單表';
--存儲過程
/*==============================================================*/
/* Database name: %DATABASE% */
/* DBMS name: ORACLE Version 10g */
/* Created on: 2009-2-1 23:29:27 */
/*==============================================================*/
-- INTEGRITY PACKAGE DECLARATION
CREATE OR REPLACE PACKAGE INTEGRITYPACKAGE AS
PROCEDURE INITNESTLEVEL;
FUNCTION GETNESTLEVEL RETURN NUMBER;
PROCEDURE NEXTNESTLEVEL;
PROCEDURE PREVIOUSNESTLEVEL;
END INTEGRITYPACKAGE;
/
-- INTEGRITY PACKAGE DEFINITION
CREATE OR REPLACE PACKAGE BODY INTEGRITYPACKAGE AS
NESTLEVEL NUMBER;
-- PROCEDURE TO INITIALIZE THE TRIGGER NEST LEVEL
PROCEDURE INITNESTLEVEL IS
BEGIN
NESTLEVEL := 0;
END;
-- FUNCTION TO RETURN THE TRIGGER NEST LEVEL
FUNCTION GETNESTLEVEL RETURN NUMBER IS
BEGIN
IF NESTLEVEL IS NULL THEN
NESTLEVEL := 0;
END IF;
RETURN(NESTLEVEL);
END;
-- PROCEDURE TO INCREASE THE TRIGGER NEST LEVEL
PROCEDURE NEXTNESTLEVEL IS
BEGIN
IF NESTLEVEL IS NULL THEN
NESTLEVEL := 0;
END IF;
NESTLEVEL := NESTLEVEL + 1;
END;
-- PROCEDURE TO DECREASE THE TRIGGER NEST LEVEL
PROCEDURE PREVIOUSNESTLEVEL IS
BEGIN
NESTLEVEL := NESTLEVEL - 1;
END;
END INTEGRITYPACKAGE;
/
CREATE OR REPLACE PROCEDURE PRO_CREATE_VIEW_BY_ETL_VIEWS
AS
--------------PRO_CREATE_VIEW_BY_ETL_VIEWS------------------------
-- CREATED ON 2009-2-1 BY CYYAN@ISOFTSTONE
-- 功能 : 根據ETL_VIEWS中到數據生成視圖
------------------------------------------------------------------------------
VIEW_CREATE_CODE VARCHAR2(10000); --生成視圖到代碼
VIEW_NAME VARCHAR2(100); --視圖名稱
VIEW_SELECT VARCHAR2(4000); --視圖的SELECT部分
VIEW_FROM VARCHAR2(300); --視圖的FROM部分
VIEW_WHERE VARCHAR2(3000); --視圖的WHERE部分
VIEW_ORDER_BY VARCHAR2(600); --視圖的ORDER BY部分
VIEW_GROUP_BY VARCHAR2(600); --視圖的GROUP BY部分
VIEW_HAVING VARCHAR2(600); --視圖的HAVING部分
VIEW_DB_LINK_NAME VARCHAR2(100); --視圖的DB LINK部分
ROW_COUNT NUMBER; --行數
CURSOR ETL_VIEWS_CURSOR IS --提取創建視圖需要到信息
SELECT VIEW_NAME, VIEW_SELECT, VIEW_FROM, VIEW_WHERE, VIEW_ORDER_BY, VIEW_GROUP_BY, VIEW_HAVING, VIEW_DB_LINK_NAME FROM ETL_VIEWS T WHERE T.CURRENT_VERSION = (SELECT MAX(T2.CURRENT_VERSION) FROM ETL_VIEWS T2 WHERE T.VIEW_NAME = T2.VIEW_NAME);
BEGIN
-- 統計行數
SELECT COUNT(*) INTO ROW_COUNT FROM ETL_VIEWS T WHERE T.CURRENT_VERSION = (SELECT MAX(T2.CURRENT_VERSION) FROM ETL_VIEWS T2 WHERE T.VIEW_NAME = T2.VIEW_NAME);
OPEN ETL_VIEWS_CURSOR; --打開游標
FOR I IN 1 .. ROW_COUNT LOOP --遍歷
FETCH ETL_VIEWS_CURSOR
INTO VIEW_NAME, VIEW_SELECT, VIEW_FROM, VIEW_WHERE, VIEW_ORDER_BY, VIEW_GROUP_BY, VIEW_HAVING, VIEW_DB_LINK_NAME;
---拼接創建視圖到語句
VIEW_CREATE_CODE := 'create or replace view ' || VIEW_NAME || ' as select ' || VIEW_SELECT || ' from ' || VIEW_FROM;
IF VIEW_DB_LINK_NAME IS NOT NULL THEN
VIEW_CREATE_CODE := VIEW_CREATE_CODE || '@' || VIEW_DB_LINK_NAME;
END IF;
IF VIEW_WHERE IS NOT NULL THEN
VIEW_CREATE_CODE := VIEW_CREATE_CODE || ' where ' || VIEW_WHERE;
END IF;
IF VIEW_ORDER_BY IS NOT NULL THEN
VIEW_CREATE_CODE := VIEW_CREATE_CODE || ' order by ' || VIEW_ORDER_BY;
END IF;
IF VIEW_GROUP_BY IS NOT NULL THEN
VIEW_CREATE_CODE := VIEW_CREATE_CODE || ' group by ' || VIEW_GROUP_BY;
END IF;
IF VIEW_HAVING IS NOT NULL THEN
VIEW_CREATE_CODE := VIEW_CREATE_CODE || ' having ' || VIEW_HAVING;
END IF;
--輸出創建語句
--DBMS_OUTPUT.PUT_LINE(VIEW_CREATE_CODE);
--DBMS_OUTPUT.PUT_LINE('');
--執行創建視圖
EXECUTE IMMEDIATE VIEW_CREATE_CODE;
END LOOP;
CLOSE ETL_VIEWS_CURSOR; --關閉游標
END;
/
CREATE OR REPLACE PROCEDURE PRO_INSERT_INTO_ETL_VIEWS
AS
--ADD BY CYYAN@ISOFTSTONE
--2009年2月1日21:33:37
---此存儲過程用于 將ETL_TABLE中標識需要創建VIEW 到TABLE, 進行自動提起轉換到ETL_VIEWS中.
--處理過程用到啦系統表COL從此表中獲取列名
TABLE_NAME VARCHAR2(100); --表名
COL_NAME VARCHAR2(100); --列名
TABLE_COUNT NUMBER; --表到行數
--COL_COUNT NUMBER; --列數
ETL_VIEWS_INSERT_CODE VARCHAR2(600); --插入語句到 INSERT部分
ETL_VIEWS_VALUES_CODE VARCHAR2(16000); --插入語句到VALUES部分
--ETL_VIEWS的到列
VIEW_NAME_PREFIX VARCHAR2(30);--實體名到前綴
TABLE_TYPE VARCHAR2(30); --表類型 如 DB, ODS, DW
TABLE_ROOT_IN VARCHAR2(30); --表來源, 來自那個系統, 如資金系統"NHZJ", 財務系統"NHCW"
VIEW_SELECT VARCHAR2(10000); --VIEW 語句到SELECT部分, 這個需要遍歷一個表到所有列
DB_LINK_NAME VARCHAR2(100);
CURRENT_VERSION VARCHAR2(600); --版本部分, 這里沒更新, 只要全部刪除, 或不斷插入, 此字段定義了版本, 沒有變更都形成新到版本, 取值是取最大值
CURSOR_NUMBER NUMBER;
COL_SELECT_SQL VARCHAR2(100);
RETURN_VALUE NUMBER;
--從ETL_TABLES中查詢需要生成視圖到表
CURSOR DB_TABLES_CURSOR IS
SELECT UPPER(TABLE_NAME), T.TABLE_TYPE, T.TABLE_ROOT_IN, T.TABLE_CREATE_VIEW_NAME_PREFIX, DB_LINK_NAME FROM ETL_TABLES T WHERE (UPPER(T.TABLE_TYPE) = 'DB' OR UPPER(T.TABLE_TYPE) = 'DW' ) AND T.TABLE_NEED_CREATE_VIEW = 1;
--CURSOR_NUMBER NUMBER; --游標 OLD WAY 執行需要, NEW WAY 不需要
--RETURN_VALUE NUMBER; --執行后返回值 OLD WAY 執行需要, NEW WAY 不需要
BEGIN
-- TEST STATEMENTS HERE
SELECT COUNT(*) INTO TABLE_COUNT FROM ETL_TABLES T WHERE (UPPER(T.TABLE_TYPE) = 'DB' OR UPPER(T.TABLE_TYPE) = 'DW' ) AND T.TABLE_NEED_CREATE_VIEW = 1;
--構造INSERT部分
ETL_VIEWS_INSERT_CODE := 'insert into etl_views(view_name, view_type, view_root_in, view_select, view_from, current_version, VIEW_DB_LINK_NAME) ';
OPEN DB_TABLES_CURSOR;
FOR I IN 1 .. TABLE_COUNT LOOP --表遍歷
FETCH DB_TABLES_CURSOR
INTO TABLE_NAME, TABLE_TYPE, TABLE_ROOT_IN, VIEW_NAME_PREFIX, DB_LINK_NAME;
--構造VALUES部分
ETL_VIEWS_VALUES_CODE := 'values(''' || VIEW_NAME_PREFIX || TABLE_NAME || ''', ''' || TABLE_TYPE || ''', ''' || TABLE_ROOT_IN || '''';
DBMS_OUTPUT.PUT(TABLE_NAME);
/* 使用CURSOR遍歷列到方法 不適用于DB_LINK
--準備遍歷列
SELECT COUNT(*) INTO COL_COUNT FROM COL@DB_LINK_NHZJ WHERE COL.TNAME = UPPER(TABLE_NAME);
DBMS_OUTPUT.PUT_LINE(' table has ' || COL_COUNT || ' cols');
DECLARE
CURSOR COLS_CURSOR IS
SELECT C.CNAME FROM COL@DB_LINK_NHZJ C WHERE C.TNAME = UPPER(TABLE_NAME);
BEGIN
OPEN COLS_CURSOR;
VIEW_SELECT := '';
--下面用逗號拼接列
FETCH COLS_CURSOR --遍歷第一列
INTO COL_NAME;
VIEW_SELECT := VIEW_SELECT || COL_NAME;
FOR J IN 2 .. COL_COUNT LOOP --遍歷后面到列
FETCH COLS_CURSOR
INTO COL_NAME;
DBMS_OUTPUT.PUT_LINE(' ' || COL_NAME);
VIEW_SELECT := VIEW_SELECT || ', ' || COL_NAME;
END LOOP;
CLOSE COLS_CURSOR;
END;
--DBMS_OUTPUT.PUT_LINE(VIEW_SELECT);
-- DBMS_OUTPUT.PUT_LINE(ETL_VIEWS_VALUES_CODE);
*/
/* 使用 DBMS_SQL */
-- ANOTHER WAY USER DBMS_SQL PACKAGE
COL_SELECT_SQL := 'select t.cname from sys.col@' || DB_LINK_NAME || ' T where T.tname = ''' || TABLE_NAME || '''';
--SQL_CODE := 'select t.cname from sys.col T where T.tname = ''' || TABLE_NAME || '''';
CURSOR_NUMBER := DBMS_SQL.OPEN_CURSOR();
DBMS_SQL.PARSE(CURSOR_NUMBER, COL_SELECT_SQL, DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN(CURSOR_NUMBER,1,COL_NAME, 100);
RETURN_VALUE := DBMS_SQL.EXECUTE(CURSOR_NUMBER);
DBMS_OUTPUT.PUT_LINE(' RETURN_VALUE = ' || RETURN_VALUE);
RETURN_VALUE := DBMS_SQL.FETCH_ROWS(CURSOR_NUMBER); --獲取第一列
DBMS_SQL.COLUMN_VALUE(CURSOR_NUMBER,1,COL_NAME);
VIEW_SELECT := COL_NAME;
WHILE DBMS_SQL.FETCH_ROWS(CURSOR_NUMBER)<>0 LOOP ---遍歷其它到列
DBMS_SQL.COLUMN_VALUE(CURSOR_NUMBER,1,COL_NAME);
DBMS_OUTPUT.PUT_LINE(COL_NAME);
VIEW_SELECT := VIEW_SELECT || ', ' || COL_NAME;
END LOOP;
-- DBMS_OUTPUT.PUT_LINE('VIEW_SELECT : ' || VIEW_SELECT);
DBMS_SQL.CLOSE_CURSOR(CURSOR_NUMBER);
--生成最新到版本號: 視圖名稱是唯一的
SELECT NVL(MAX(CURRENT_VERSION),0) + 1 INTO CURRENT_VERSION FROM ETL_VIEWS V WHERE V.VIEW_NAME = VIEW_NAME_PREFIX || TABLE_NAME;
ETL_VIEWS_VALUES_CODE := ETL_VIEWS_VALUES_CODE || CHR(10) || ', ''' || VIEW_SELECT || '''' || CHR(10) || ', ''' || TABLE_NAME || ''', ''' || CURRENT_VERSION || ''', ''' || DB_LINK_NAME || ''')';
--輸出插入到語句
--DBMS_OUTPUT.PUT_LINE(ETL_VIEWS_INSERT_CODE);
--DBMS_OUTPUT.PUT_LINE(ETL_VIEWS_VALUES_CODE);
--DBMS_OUTPUT.PUT_LINE('');
--DBMS_STANDARD.
--執行插入語句
-- NEW WAY
EXECUTE IMMEDIATE ETL_VIEWS_INSERT_CODE || ETL_VIEWS_VALUES_CODE;
/*
-- OLD WAY
CURSOR_NUMBER := DBMS_SQL.OPEN_CURSOR();
DBMS_SQL.PARSE(CURSOR_NUMBER, ETL_VIEWS_INSERT_CODE, DBMS_SQL.NATIVE);
RETURN_VALUE := DBMS_SQL.EXECUTE(CURSOR_NUMBER);
DBMS_SQL.CLOSE_CURSOR(CURSOR_NUMBER);
*/
END LOOP;
COMMIT; --提交
CLOSE DB_TABLES_CURSOR; --關閉游標
--EXCEPTION
--ROLLBACK;
END;
/
CREATE OR REPLACE TRIGGER TRG_ID_ON_ETLS
BEFORE INSERT ON ETLS
FOR EACH ROW
DECLARE
-- NOTHING
BEGIN
SELECT SEQ_ETL_INCREASE_ID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGGER_ID_INCREASE;
/
CREATE OR REPLACE TRIGGER TRG_ID_ON_ETL_TABLES
BEFORE INSERT ON ETL_TABLES
FOR EACH ROW
DECLARE
-- NOTHING
BEGIN
SELECT SEQ_ETL_INCREASE_ID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGGER_ID_INCREASE;
/
CREATE OR REPLACE TRIGGER TRG_ID_ON_ETL_VIEWS
BEFORE INSERT ON ETL_VIEWS
FOR EACH ROW
DECLARE
-- NOTHING
BEGIN
SELECT SEQ_ETL_INCREASE_ID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGGER_ID_INCREASE;
/
posted @
2010-12-31 10:42 xzc 閱讀(1636) |
評論 (0) |
編輯 收藏