專用服務器模式下:一種方式是監聽進程接收到用戶進程請求后,產生一個新的專用服務器進程,并且將對用戶進程的所有控制信息傳給此服務器進程,也就是說新建的服務器進程繼承了監聽進程的信息,然后服務器進程給用戶進程發一個RESEND包,通知用戶進程可以開始給它發信息了,用戶進程給這個新建的服務器進程發一個CONNECT包,服務器進程再以ACCEPT包回應用戶進程,致此,用戶進程正式與服務器進程確定連接。我們把這種連接叫做HAND-OFF連接,也叫轉換連接。另一種方式是監聽進程接收到用戶進程的請求后產生一個新的專用服務器進程,這個服務器進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監聽進程,監聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給服務器進程發送一個CONNECT包,服務器進程再給用戶進程發送一個ACCEPT包,致此,用戶進程可以正式向服務器進程發送信息了。這種方式我們叫做重定向連接。HAND-OFF連接需要系統平臺具有進程繼承的能力,為了使WINDOWS NT/2000支持HAND-OFF必須在HKEY_LOCAL_MACHINE>SOFTWARE>ORACLE>HOMEX中設置USE_SHARED_SOCKET。
共享服務器模式下:只有重定向連接的方式,工作方式是監聽進程接收到用戶進程的請求后產生一個新的調度進程,這個調度進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監聽進程,監聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給調度進程發送一個CONNECT包,調度進程再給用戶進程發送一個ACCEPT包,致此,用戶進程可以正式向調度進程發送信息了。可以通過設置MAX_DISPIATCHERS這個參數來確定調度進程的最大數目,如果調度進程的個數已經達到了最大,或者已有的調度進程不是滿負荷,監聽進程將不再創建新的調度進程,而是讓其中一個調度進程選用一個TCP/IP端口來與此用戶進程交互。調度進程每接收一個用戶進程請求都會在監聽進程處作一個登記,以便監聽進程能夠均衡每個調度進程的負荷,所有的用戶進程請求將分別在有限的調度進程中排隊,所有調度進程再順序的把各自隊列中的部分用戶進程請求放入同一個請求隊列,等候多個ORACLE的共享服務器進程進行處理(可以通過SHARED_SERVERS參數設置共享服務器進程的個數),也就是說所有的調度進程共享同一個請求隊列,共享服務器模式下一個實例只有一個請求隊列,共享服務器進程處理完用戶進程的請求后將根據用戶進程請求取自不同的調度進程將返回結果放入不同的響應隊列,也就是說有多少調度進程就有多少響應隊列,然后各個調度進程從各自的響應隊列中將結果取出再返回給用戶進程。
以上我們講完了用戶與ORACLE的連接方式,下面我們要講ORACLE服務器進程如可處理用戶進程的請求,當一個用戶進程發出了一條SQL語名:UPDATE TABBLEA SET SALARY=SALARY*2;首先,服務器進程把這條語句的字符轉換成ASCII等效數字碼,接著這個ASCII碼被傳遞給一個HASH函數,并返回一個HASH值,服務器進程將到SHARED POOL 的共享PL/SQL區去查找是否存在同樣的HASH值,如果存在,服務器進程將使用這條語句已高速緩存在SHARED POOL中的已分析過的版本來執行,如果不存在,服務器進程將對該語句進行語法分析,首先檢查該語句的語法的正確性,接著對語句中涉及的表、索引、視圖等對象進行解析,并對照數據字典檢查這些對象的名稱以及相關結構,并根據ORACLE選用的優化模式以及數據字典中是否存在相應對象的統計數據和是否使用了存儲大綱來生成一個執行計劃或從存儲大綱中選用一個執行計劃,然后再用數據字典核對此用戶對相應對象的執行權限,最后生成一個編譯代碼。ORACLE將這條語名的本身實際文本、HASH值、編譯代碼、與此語名相關聯的任何統計數據和該語句的執行計劃緩存在SHARED POOL的共享PL/SQL區。服務器進程通過SHARED POOL 鎖存器來申請可以向哪些共享PL/SQL區中緩存這此內容,也就是說被SHARED POOL鎖存器鎖定的PL/SQL區中的塊不可被覆蓋,因為這些塊可能被其它進程所使用。在SQL分析階段將用到LIBRARY CACHE,從數據字典中核對表、視圖等結構的時候,需要將數據字典從磁盤讀入LIBRARY CACHE,因此,在讀入之前也要使用LIBRARY CACHE鎖存器來申請用于緩存數據字典。
生成編譯代碼之后,接著下一步服務器進程要準備開始更新數據,服務器進程將到DB BUFFER中查找是否有相關對象的緩存數據,下面分兩個可能進行解釋:
如果沒有,服務器進程將在表頭部請求一些行鎖,如果成功加鎖,服務器進程將從數據文件中讀這些行所在的數據塊放入DB BUFFER中空閑的區域或者覆蓋已被擠出LRU列表的非臟數據塊緩沖區,并且排列在LRU列表的頭部,如果這些非臟數據緩沖區寫完也不能滿足新數據的請求時,會立即觸發DBWN進程將臟數據列表中指向的緩沖塊寫入數據文件,并且清洗掉這些緩沖區,來騰出空間緩沖新讀入的數據,也就是在放入DB BUFFER之前也是要先申請DB BUFFER中的鎖存器,成功鎖定后,再寫入DB BUFFER,然后服務器程將該語句影響的被讀入DB BUFFER塊中的這些行的ROWID及將要更新的原值和新值及SCN等信息逐條的寫入REDO LOG BUFFER,在寫入REDO LOG BUFFER之前也是先請求REDO LOG BUFFER塊的鎖存器,成功鎖定之后才開始寫入,當寫入達到REDO LOG BUFFER大小的三分之一或寫入量達到1M或超過三秒后或發生檢查點時或者DBWN之前發生,LGWR將把REDO LOG BUFFER中的數據寫入磁盤上的重做日志文件,已被寫入重做日志文件的REDO LOG BUFFER中的塊上的鎖存器被釋放,并可被后來寫入的信息所覆蓋,REDO LOG BUFFER以循環的方式工作。當一個重做日志文件寫滿后,LGWR將切換到下一個重做日志文件,如果是歸檔模式,歸檔進程還將前一個寫滿的重做日志進程寫入歸檔日志文件,重做日志文件也是循環工作方式。寫完所有的REDO LOG BUFFER之后,服務器進程開始改寫這個DB BUFFER塊頭部的事務列表并寫入SCN,然后COPY包含這個塊的頭部事務列表及SCN信息的數據副本放入回滾段中,我們將回滾段中的副本稱為數據塊的“前映像”。(回滾段可以存儲在專門的回滾表空間中,這個表空間由一個或多個物理文件組成,并專用于回滾表空間,回滾段也可在其它表空間中的數據文件中開辟。)然后改寫這個DB BUFFER塊的數據,并在其頭部寫入對應的回滾段地址,如果對一行數據多次UPDATE而不COMMIT則在回滾段中將會有多個“前映像”,除第一個“前映像”含有SCN信息外,其它的每個“前映像”的頭部還含有SCN信息和“前前映像”的回滾段地址。一次UPDATE操作只對應一個SCN。然后服務器進程在臟數據列表中建立一條指向此緩沖塊的指針。接著服務器進程會從數據文件讀入第二個塊重復以上讀入,記日志,建立回滾段,修改,放入臟列表的動作,當臟數據列表達到一定長度時,DBWN進程將臟數據列表中指向的緩沖塊全部寫入數據文件,也就是釋放加在這些DB BUFER 塊上的鎖存器。其實ORACLE可以一次從數據文件中讀入幾個塊放入DB BUFFER,可以通過參數DB_FILE_MULTIBLOCK_READ_COUNT來設置一次讀入的塊的個數。
如果要查找的數據已緩存,則根據用戶的SQL操作類型決定如何操作,如果是SELECT 則查看DB BUFFER塊的頭部是否有事務,如果有,將從回滾段讀取,如果沒有則比較SELECT 的SCN與DB BUFFER塊頭部的SCN如果比自己大,仍然從回滾段讀取,如果比自己小則認這是一個非臟緩存,可以直接從這個DB BUFFER塊中讀取。如果是UPDATE則即使在DB BUFFER中找到一個沒有事務,而且SCN比自己小的非臟緩存數據塊,服務器進程仍然要到表的頭部對這條記錄申請加鎖,加鎖成功則進行后續動作,如果不成功,則要等待前面的進程解鎖后才能進行動作。
只有當SQL語句影響的所有行所在的最后一個塊被讀入DB BUFFER并且重做信息被寫入REDO LOG BUFFER(僅是指重做日志緩沖,而非重做日志文件)之后,用戶才可以發出COMMIT,COMMIT觸發LGRW,但并不強制立即DBWN來釋放所有相應的DB BUFFER塊上的鎖,也就是說有可能出現已COMMIT,但在隨后的一段時間內DBWN還在寫這條語句涉及的數據塊的情形,表頭部的行鎖,并不是在COMMIT一發出就馬上釋放,實際上要等到相應的DBWN進程結束才會釋放。一個用戶請求鎖定另一個用戶已COMMIT的資源不成功的機會是存在的,從COMMIT到DBWN進程結束之間的時間很短,如果恰巧在這個時間斷電,由于COMMIT已觸發LGWR進程,所以這些未來得及寫入數據文件的改變會在實例重啟后由SMON進程根據重做日志文件來前滾。如果未COMMIT就斷電,由于DBWN之前觸發LGWR,所有DBWN在數據文件上的修改都會被先一步記入重做日志文件,實例重啟后,SMON進程再根據重做日志文件來回滾。
如果用戶ROOLBACK,則服務器進程會根據數據文件塊和DB BUFFER中塊的頭部的事務列表和SCN以及回滾段地址找到回滾段中相應的修改前的副本,并且用這些原值來還原當前數據文件中已修改但未提交的改變。如果有多個“前映像”,服務器進程會在一個“前映像”的頭部找到“前前映像”的回滾段地址,一直找到同一事務下的最早的一個“前映像”為止。一旦發出了COMMIT,用戶就不能ROOLBACK,這使得COMMIT后DBWN進程還沒有全部完成的后續動作得到了保障。
下面我們要提到檢查點的作用,當一個全部檢查點發生的時候,首先讓LGWR進程將REDO LOG BUFFER中的所有緩沖(包含未提交的重做信息)寫入重做日志文件,然后讓DBWN進程將DB BUFFER中所有已提交的緩沖寫入數據文件(不強制寫未提交的)。然后更新控制文件和數據文件頭部的SCN,表明當前數據庫是一致的,如果在發生檢點之前斷電,并且當時有一個未提交的改變正在進行,實例重啟之后,SMON進程將從上一個檢查點開始核對這個檢查點之后記錄在重做日志文件中已提交的和未提交改變,因為DBWN之前會觸發LGWR,所以DBWN對數據文件的修改一定會被先記錄在重做日志文件中。因此,斷電前被DBWN寫進數據文件的改變將通過重做日志文件中的記錄進行還原,叫做回滾,如果斷電時有一個已提交,但DBWN動作還沒有完全完成的改變存在,因為已經提交,提交會觸發LGWR進程,所以不管DBWN動作是否已完成,該語句將要影響的行及其產生的結果一定已經記錄在重做日志文件中了,則實例重啟后,SMON進程根據重做日志文件進行前滾。由此可見,實例失敗后用于恢復的時間由兩個檢查點之間的間隔大小來決定,我們可以通個四個參數設置檢查點執行的頻率,LOG_CHECKPOINT_IMTERVAL決定了兩個檢查點之間寫入重做日志文件的系統物理塊的大小,LOG_CHECKPOINT_TIMEOUT決定了兩個檢查點之間的時間長度,FAST_START_IO_TARGET決定了用于恢復時需要處理的塊的大小,FAST_START_MTTR_TARGET直接決定了用于恢復的時間的長短。SMON進程執行的前滾和回滾與用戶的回滾是不同的,SMON是根據重做日志文件進行前滾或回滾,而用戶的回滾一定是根據回滾段的內容進行回滾的。在這里我們要說一下回滾段存儲的數據,假如是delete操作,則回滾段將會記錄整個行的數據,假如是update,則回滾段只記錄被修改了的字段的變化前的數據(前映像),也就是沒有被修改的字段是不會被記錄的,假如是insert,則回滾段只記錄插入記錄的rowid。這樣假如事務提交,那回滾段中簡單標記該事務已經提交;假如是回退,則如果操作是是delete,回退的時候把回滾段中數據重新寫回數據塊,操作如果是update,則把變化前數據修改回去,操作如果是insert,則根據記錄的rowid 把該記錄刪除。
下面我們要講DBWN如何來寫數據文件,在寫數據文件前首先要找到可寫的空閑數據塊,ORACLE中空閑數據塊可以通過FREELIST或BITMAP來維護,它們位于一個段的頭部用來標識當前段中哪些數據塊可以進行INSERT。在本地管理表空間中ORACLE自動管理分配給段的區的大小,區的分配信息存儲在組成表空間的數據文件的頭部,而數據字典管理的表空間用戶可以在創建時決定區的大小,并且區的分配信息是存儲在數據字典中的,只在本地管理的表空間中才能選用段自動管理,采用自動段空間管理的本地管理表空間中的段中的空閑數據塊的信息就存放在段的頭部并且使用位圖來管理,采用手動管理的本地管理表空間中的段和數據字典管理的表空間中的段中的空閑數據塊的管理都使用位于段頭部的空閑列表來管理,空閑列表的工作方式:首先一個空的數據塊被加入空閑列表,當其中空閑空間小于PCTFREE設置的值之后,這個塊從空閑列表刪除,當這個塊中的內容降至PCTUSED設置的值之下后,這個數據塊被再次加入空閑列表,位于空閑列表中的數據塊都是可以向其中INSERT的塊,當一個塊移出了空閑列表,但只要其中還有保留空間就可以進行UPDATE,當對其中一行UPDATE一個大數據時,如果當前塊不能完全放下整個行,只會把整個行遷移到一個新的數據塊,并在原塊位置留下一個指向新塊的指針,這叫行遷移。如果一個數據塊可以INSERT,當插入一個當前塊裝不下的行時,這個行會溢出到兩個或兩個幾上的塊中,這叫行鏈接。如果用戶的動作是INSERT 則服務器進程會先鎖定FREELIST,然后找到空閑塊的地址,再釋放FREELIST,當多個服務器進程同時想要鎖定FREELIST時即發生FREELIST的爭用,可以在非采用自動段空間管理的表空間中創建表時指定FREELIST的個數,默認為1,如果是在采用自動段空間管理的表空間中創建表,即使指定了FREELIST也會被忽略,因為此時將使用BITMAP而不是FREELIST來管理段中的空閑空間。如果用戶動作是UPDATE服務器進程將不會使用到FREELIST和BITMAP,因為不要去尋找一個空閑塊,而使用鎖的隊列。
下面來講一下ORACLE鎖的機制,ORACLE分鎖存器和鎖兩種。鎖存器是用來保護對內存結構的訪問,比如對DB BUFFER中塊的鎖存器申請,只有在DBWN完成后,這些DB BUFFER塊被解鎖。然后用于其它的申請。鎖存器不可以在進程間共享,鎖存器的申請要么成功要么失敗,沒有鎖存器申請隊列。主要的鎖存器有SHARED POOL鎖存器,LIBRARY CACHE鎖存器,CACHE BUFFERS LRU CHAIN鎖存器,CACHE BUFFERS CHAINS 鎖存器,REDO ALLOCATION 鎖存器,REDO COPY 鎖存器。ORACLE的鎖是用來保護數據訪問的,鎖的限制比鎖存器要更寬松,比如,多個用戶在修改同一表的不同行時,可以共享一個表上的一個鎖,鎖的申請可以按照被申請的順序來排隊等候,然后依次應用,這種排隊機制叫做隊列(ENPUEUE),如果兩個服務器進程試圖對同一表的同一行進行加鎖,則都進入鎖的申請隊列,先進的加鎖成功,后面的進程要等待,直到前一個進程解鎖才可以加鎖,這叫做鎖的爭用,而且一旦加鎖成功,這個鎖將一直保持到用戶發出COMMIT或ROOLBACK命令為止。如果兩個用戶鎖定各自的一行并請求對方鎖定的行的時候將發生無限期等待即死鎖,死鎖的發生都是由于鎖的爭用而不是鎖存器的爭用引起的,ORACLE在遇到死鎖時,自動釋放其中一個用戶的鎖并回滾此用戶的改變。正常情況下發生鎖的爭用時,數據的最終保存結果由SCN來決定哪個進程的更改被最終保存。兩個用戶的服務器進程在申請同一表的多個行的鎖的時候是可以交錯進入鎖的申請隊列的。只有其中發生爭用才會進行等待。創建表時指定的MAXTRANS參數決了,表中的一個數據塊最多可以被幾個事務同時鎖定。
下面是幾個關于回滾段和死鎖的事例:
有表:Test (id number(10)) 有記錄1000000條
一,大SELECT,小UPDATE
A會話----Select * from test;----設scn=101----執行時間09:10:11
B會話-----Update test set id=9999999 where id=1000000----設scn=102-----執行時間09:10:12
我們會發現B會話會在A會話前完成,A會話中顯示的ID=100000是從回滾段中讀取的,因為A會話在讀到ID=1000000所在的BLOCK時發現BLOCK上有事務信息,因此要從回滾段中讀,如果UPDATE在SELECT讀到此BLOCK之前已經COMMIT,則SELECT 讀到此BLOCK時發現其BLOCK上沒有事務信息,但是會發現其BLICK的SCN比SELECT自己的SCN大,因此也會從回滾段中讀取。因此是否從回滾段讀一是看是否有事務信息二是比較SCN大小。如果B會話在A會話結束前連續多次對同一條記錄UPDATE并COMMIT,那么在回滾段中將記錄多個“前映像”,而每個“前映像”中不但包括了原BLOCK的數據和SCN也記錄了“前前映像”的回滾段地址,因此A會話在查詢到被UPDATE過的BLOCK時,會根據BLOCK記錄的回滾段的地址,找到回滾段中的“前映像”,發現這個“前映像”的SCN也比自己的大,因此將根據這個“前映像”中記錄的“前前映像”的回滾段地址,在回滾段中找到“前前映像”,再與這個“前前映像”比較SCN,如果比自己小就讀取,如果還比自己大,則重復以上步驟,直到找到比自己SCN小的“前…前映像”為止,如果找不到,就會報ORA-01555快照太舊這個錯誤。
二、大UPDATE,小SELECT
A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話-----select * from test where id=1000000----設scn=102-----執行時間09:10:12
我們會發現B會話會在A會話前完成,B會話中顯示的ID=1000000是從BLOCK中直接讀取的,因為B會話在讀到ID=1000000所在的BLOCK時,A會話還沒有來得及對其鎖定,因此B會話既不會發現BLOCK上有事務信息,也不會發現BLOCK上的SCN比SELECT的大,因此會從BLOCK中直接讀取,如果SELECT在UPDATE鎖定此BLOCK后才發出,B會話讀到此BLOCK時發現其BLOCK上有事務信息,因此會從回滾段中讀取。
三、大UPDATE,小UPDATE
A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話1-----Update test set id=999999 where id=1000000----設scn=102-----執行時間09:10:12
B會話2----- select * from test where id=2----設scn=103-----執行時間09:10:14
B會話3----- update test set id=3 where id=2----設scn=104-----執行時間09:10:15
我們會發現B會話1會完成,A會話將一直等待,因為B會話1會先于A會話鎖定ID=1000000所在的BLOCK,并改寫頭部的事務信息,A會話在試圖鎖定此BLOCK時,發現其上有事務信息,將會一直等待B會話1事務結束后再行鎖定, B會話2查詢到的ID=2是從回滾段中讀取的而不是從BLOCK中直接讀出來的。因為A會話已將ID=2的BLOCK鎖定,并寫入了回滾段,從B會話3可以證明這一點,B會話3發出后,B會話3會收到死鎖的信息,死鎖的原因是A會話在等待B會話對ID=1000000所在的BLOCK解鎖,現在B會話又在等待A會話對ID=2所在的BLOCK解鎖,因此形成死鎖,因此證明ID=2所在的BLOCK已被A會話鎖定,然后A會話也會收到死鎖的信息
文件內容統計命令:wc | |
http://www.fanqiang.com (2001-05-08 14:24:15) | |
|
一、特殊符號ascii定義
制表符 chr(9)
換行符 chr(10)
回車符 chr(13)
二、嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行
select REPLACE(gg, chr(10), '') from dual
要注意chr(13) | | chr(10) 此類結合使用的情況比較多,回車換行在notepad中是比較好看點的,所以要考慮此種情況
select translate(string,chr(13)||chr(10),',') from dual;
1、例子一
create table TEST_1
(
VA VARCHAR2(10),
VB NUMBER(2),
VC VARCHAR2(10),
VD NUMBER(11,2),
VE NUMBER(11,4),
VCL CLOB
);
SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(10),',') from test_1;
VB VC TT TRANSLATE(VC,CHR(10),',')
--- ---------- ---------- -------------------------
0 Aaaaaaaaa Aaaaaaaaa Aaaaaaaaa
1 Aaaaaaaaa Aaaaaaaaa Aaaaaaaaa
2 大Ba 大Babc帶 大Ba,b,c帶
b
c帶
3 C C C
1 D D D
5 A A A
5 A A A
0 A A A
0 A A A
2、例子二
要注意chr(13) | | chr(10) 此類結合使用的情況比較多,回車換行在notepad中是比較好看點的,所以要考慮此種情況
select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
VB VC TT TRANSLATE(VC,CHR(13)||CHR(10),
--- ---------- ---------- ------------------------------
0 Aaaaaaaaa Aaaaaaaaa Aaaaaaaaa
1 Aaaaaaaaa Aaaaaaaaa Aaaaaaaaa
2 大Ba 大Babc帶 大Babc帶
b
c帶
3 C C C
1 D D D
5 A A A
5 A A A
0 A A A
0 A A A
11 rows selected
三、對于字符大對象的符號處理
對于clob字段中的符號處理,先to_char然后一樣的處理
SQL> select to_char(vcl),replace(to_char(vcl),chr(10),'[]') from test_1;
TO_CHAR(VCL) REPLACE(TO_CHAR(VCL),CHR(10),'
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行 嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行[]select REPLACE(gg, chr(10), '') from dual[]sel
select REPLACE(gg, chr(10), '') from dual
select translate(string,chr(13)||chr(10),',') from dual;
func:
2.2.1 單記錄字符函數
函 數 說 明
ASCII 返回對應字符的十進制值
CHR 給出十進制返回字符
CONCAT 拼接兩個字符串,與 || 相同
INITCAT 將字符串的第一個字母變為大寫
INSTR 找出某個字符串的位置
INSTRB 找出某個字符串的位置和字節數
LENGTH 以字符給出字符串的長度
LENGTHB 以字節給出字符串的長度
LOWER 將字符串轉換成小寫
LPAD 使用指定的字符在字符的左邊填充
LTRIM 在左邊裁剪掉指定的字符
RPAD 使用指定的字符在字符的右邊填充
RTRIM 在右邊裁剪掉指定的字符
REPLACE 執行字符串搜索和替換
SUBSTR 取字符串的子串
SUBSTRB 取字符串的子串(以字節)
SOUNDEX 返回一個同音字符串
TRANSLATE 執行字符串搜索和替換
TRIM 裁剪掉前面或后面的字符串
UPPER 將字符串變為大寫
NVL 以一個值來替換空值
ASCII(<c1>)
<c1>是字符串。返回與指定的字符對應的十進制數。
SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual;
A a ZERO SPACE
---------- ---------- ---------- ----------
65 97 48 32
SQL> select ascii('趙') zhao,length('趙') leng from dual;
ZHAO LENG
---------- ----------
54740 1
CHR(<I>[NCHAR])
給出整數,返回對應字符。如:
SQL> select chr(54740) zhao,chr(65) chr65 from dual;
ZH C
-- -
趙 A
CONCAT(<c1>,<c2>)
SQL> select concat('010-','8801 8159')||'轉23' 趙元杰電話 from dual;
趙元杰電話
-----------------
010-8801 8159 轉23
INITCAP(<c1>)
返回字符串c1 并第一個字母變為大寫。例如:
SQL> select initcap('simth') upp from dual;
UPP
-----
Simth
INSTR(<c1>,<c2>[,<I>[,<j>] ] )
在一個字符串中搜索指定的字符,返回發現指定的字符的位置。
C1: 被搜索的字符串
C2: 希望搜索的字符串
I: 搜索的開始位置,缺省是1
J: 出現的位置,缺省是1。
SQL> SELECT INSTR ('Oracle Training', 'ra', 1, 2) "Instring" FROM DUAL;
Instring
----------
9
INSTRB(<c1>,<c2>[,<I>[,<j>] ] )
除了返回的字節外 ,與INSTR 相同,
LENGTH( <c> )
返回字符串 c 的長度。
SQL> l
1 select name,length(name),addr,length(addr),sal,length(to_char(sal))
2* from nchar_tst
SQL> /
NAME LENGTH(NAME) ADDR LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL))
------ ------------ ---------------- ------------ ---------- ----------------
趙元杰 3 北京市海淀區 6 99999.99 8
LENGTHB( <c> )
以字節返回字符串的字節數。
SQL> select name,lengthb(name),length(name) from nchar_tst;
NAME LENGTHB(NAME) LENGTH(NAME)
------ ------------- ------------
趙元杰 6 3
LOWER ( <c> )
返回字符串并將所有字符變為小寫。
SQL> select lower('AaBbCcDd') AaBbCcDd from dual;
AABBCCDD
--------
aabbccdd
UPPER( <c>)
與 LOWER 相反,將給出字符串變為大寫。如:
SQL> select upper('AaBbCcDd') AaBbCcDd from dual;
AABBCCDD
--------
AABBCCDD
RPAD 和LPAD(粘貼字符)
RPAD(string,Length[,'set'])
LPAD(string,Length[,'set'])
RPAD在列的右邊粘貼字符;
LPAD在列的左邊粘貼字符。
例 1:
SQL>select RPAD(City,35,'.'),temperature from weather;
RPAD(City,35,'.') temperature
-------------------------- ----------------
CLEVELAND...... 85
LOS ANGELES.. 81
.........................
(即不夠 35 個字符用'.'填滿)
LTRIM(左截斷)RTRIM(右截斷) 函數
LTRIM (string [,’set’])
Left TRIM (左截斷)刪去左邊出現的任何set 字符。
RTRIM (string [,’set’])
Right TRIM (右截斷)刪去右邊出現的任何set 字符。
例1:
SELECT RTRIM (‘Mother Theresa, The’, ‘The’) “Example of Right
Trimming” FROM DUAL;
Example of Right
----------------
Mother Theresa,
SUBSTR Substr(string,start[,Count])
取子字符串中函數
對字串 (或字段),從 start字符 開始,連續取 count 個字符并返回結果,如果沒有指 count
則一直取到尾。
select phone,substr(phone,1,3) || ‘0’ || substr(phone,4)
from telecommunication where master ’中國電信’;
SUBSTRB(string,start[,Count])
對字串 (或字段),從 start字節 開始,連續取 count 個字節并返回結果,如果沒有指 count
則一直取到尾。
REPLACE (‘string’ [,’string_in’,’string_out’])
String: 希望被替換的字符串或變量。
String_in: 被替換字符串。
String_out: 要替換字符串。
SQL> select replace('Informaix 中國公司','Informaix','IBM Informix')
2 IBM 數據庫 from dual;
IBM 數據庫
--------------------
IBM Informix 中國公司
SOUNDEX( <c> )
返回一個與給定的字符串讀音相同的字符串(不管拼寫是否一樣)。
SELECT DPL_NAME FROM DENIED_PARTIES_LIST WHERE
SOUNDEX(DPL_NAME) = SOUNDEX(‘Saddam Hussain’) ;
DPL_NAME
----------------------------------------------
Al Husseni
Sadda Al Sada.
REPLACE (‘string’ [,’string_in’,’string_out’])
String:希望被替換的字符串或變量。
String_in: 被替換字符串。
String_out: 要替換字符串。
SELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL;
Example
-------
Miracle
TRIM ( [<leading>] <trailing> FROM <trim_char> )
RIM可以使你對給定的字符串進行裁剪(前面,后面或前后)。
z 如果指定 LEADING, Oracle 從trim_char 中裁剪掉前面的字符;
z 如果指定TRAILING, Oracle 從trim_char 中裁剪掉尾面的字符;
z 如果指定兩個都指定或一個都沒有給出,Oracle從trim_char 中裁剪掉前面及尾面的字
符;
z 如果不指定 trim_character, 缺省為空格符;
z 如果只指定trim_source, Oracle Oracle從trim_char 中裁剪掉前面及尾面的字符。
例子:將下面字符串中的前面和后面的‘0 ‘字符都去掉:
SELECT TRIM (0 FROM 0009872348900) "TRIM Example" FROM DUAL;
TRIM example
--------------------------------
98723489
語法:TRANSLATE(expr,from,to)
om,to) expr: 代表一串字符,
expr: 代表一串字符,from 與 to 是從左到右一一對應的關系,如果不能對應,則視為空值。
舉例:
select translate('abcbbaadef','ba','#@') from dual (b將被#替代,a將被@替代)
select translate(ab
select translate('abcbbaadef','bad','#@') from dual (b將被#替代,a將被@替代,d對應的值是空值,將被移走)
因此:結果依次為:@#c##@@def 和@#c##@@ef
|
在linux下獲取時間字符串
命令 date
# 以yyyymmdd格式輸出23天之前現在這個時刻的時間
$ date +%Y%m%d –date=’23 days ago’
$ date -u
Thu Sep 28 09:32:04 UTC 2006
$ date -R
Thu, 28 Sep 2006 17:32:28 +0800
# 測試十億分之一秒
$ date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’
20060928 17:44:20.906805000
20060928 17:44:20.909188000
20060928 17:44:20.911535000
20060928 17:44:20.913886000
date 參考
$ date –help
Usage: date [OPTION]… [+FORMAT]
or: date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
Display the current time in the given FORMAT, or set the system date.
-d, –date=STRING display time described by STRING, not `now’
# such as ‘n days ago |1 month ago|n years ago’
-f, –file=DATEFILE like –date once for each line of DATEFILE
-ITIMESPEC, –iso-8601[=TIMESPEC] output date/time in ISO 8601 format.
TIMESPEC=`date’ for date only,
`hours’, `minutes’, or `seconds’ for date and
time to the indicated precision.
–iso-8601 without TIMESPEC defaults to `date’.
-r, –reference=FILE display the last modification time of FILE
-R, –rfc-2822 output RFC-2822 compliant date string
-s, –set=STRING set time described by STRING
-u, –utc, –universal print or set Coordinated Universal Time
–help display this help and exit
–version output version information and exit
FORMAT controls the output. The only valid option for the second form
specifies Coordinated Universal Time. Interpreted sequences are:
%% 輸出%符號 a literal %
%a 當前域的星期縮寫 locale’s abbreviated weekday name (Sun..Sat)
%A 當前域的星期全寫 locale’s full weekday name, variable length (Sunday..Saturday)
%b 當前域的月份縮寫 locale’s abbreviated month name (Jan..Dec)
%B 當前域的月份全稱 locale’s full month name, variable length (January..December)
%c 當前域的默認時間格式 locale’s date and time (Sat Nov 04 12:02:33 EST 1989)
%C n百年 century (year divided by 100 and truncated to an integer) [00-99]
%d 兩位的天 day of month (01..31)
%D 短時間格式 date (mm/dd/yy)
%e 短格式天 day of month, blank padded ( 1..31)
%F 文件時間格式 same as %Y-%m-%d
%g the 2-digit year corresponding to the %V week number
%G the 4-digit year corresponding to the %V week number
%h same as %b
%H 24小時制的小時 hour (00..23)
%I 12小時制的小時 hour (01..12)
%j 一年中的第幾天 day of year (001..366)
%k 短格式24小時制的小時 hour ( 0..23)
%l 短格式12小時制的小時 hour ( 1..12)
%m 雙位月份 month (01..12)
%M 雙位分鐘 minute (00..59)
%n 換行 a newline
%N 十億分之一秒 nanoseconds (000000000..999999999)
%p 大寫的當前域的上下午指示 locale’s upper case AM or PM indicator (blank in many locales)
%P 小寫的當前域的上下午指示 locale’s lower case am or pm indicator (blank in many locales)
%r 12小時制的時間表示(時:分:秒,雙位) time, 12-hour (hh:mm:ss [AP]M)
%R 24小時制的時間表示 (時:分,雙位)time, 24-hour (hh:mm)
%s 自基礎時間 1970-01-01 00:00:00 到當前時刻的秒數 seconds since `00:00:00 1970-01-01 UTC’ (a GNU extension)
%S 雙位秒 second (00..60); the 60 is necessary to accommodate a leap second
%t 橫向制表位(tab) a horizontal tab
%T 24小時制時間表示 time, 24-hour (hh:mm:ss)
%u 數字表示的星期(從星期一開始 1-7)day of week (1..7); 1 represents Monday
%U 一年中的第幾周星期天為開始 week number of year with Sunday as first day of week (00..53)
%V 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (01..53)
%w 一周中的第幾天 星期天為開始 0-6 day of week (0..6); 0 represents Sunday
%W 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (00..53)
%x 本地日期格式 locale’s date representation (mm/dd/yy)
%X 本地時間格式 locale’s time representation (%H:%M:%S)
%y 兩位的年 last two digits of year (00..99)
%Y 年 year (1970…)
%z RFC-2822 標準時間格式表示的域 RFC-2822 style numeric timezone (-0500) (a nonstandard extension)
%Z 時間域 time zone (e.g., EDT), or nothing if no time zone is determinable
By default, date pads numeric fields with zeroes. GNU date recognizes
the following modifiers between `%’ and a numeric directive.
`-’ (hyphen) do not pad the field
`_’ (underscore) pad the field with spaces
二元比較操作符,比較變量或者比較數字.注意數字與字符串的區別.
整數比較
-eq 等于,如:if [ "$a" -eq "$b" ]
-ne 不等于,如:if [ "$a" -ne "$b" ]
-gt 大于,如:if [ "$a" -gt "$b" ]
-ge 大于等于,如:if [ "$a" -ge "$b" ]
-lt 小于,如:if [ "$a" -lt "$b" ]
-le 小于等于,如:if [ "$a" -le "$b" ]
< 小于(需要雙括號),如:(("$a" < "$b"))
<= 小于等于(需要雙括號),如:(("$a" <= "$b"))
> 大于(需要雙括號),如:(("$a" > "$b"))
>= 大于等于(需要雙括號),如:(("$a" >= "$b"))
字符串比較
= 等于,如:if [ "$a" = "$b" ]
== 等于,如:if [ "$a" == "$b" ],與=等價
注意:==的功能在[[]]和[]中的行為是不同的,如下:
1 [[ $a == z* ]] # 如果$a以"z"開頭(模式匹配)那么將為true
2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么結果為true
3
4 [ $a == z* ] # File globbing 和word splitting將會發生
5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么結果為true
一點解釋,關于File globbing是一種關于文件的速記法,比如"*.c"就是,再如~也是.
但是file globbing并不是嚴格的正則表達式,雖然絕大多數情況下結構比較像.
!= 不等于,如:if [ "$a" != "$b" ]
這個操作符將在[[]]結構中使用模式匹配.
< 小于,在ASCII字母順序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意:在[]結構中"<"需要被轉義.
> 大于,在ASCII字母順序下.如:
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意:在[]結構中">"需要被轉義.
具體參考Example 26-11來查看這個操作符應用的例子.
-z 字符串為"null".就是長度為0.
-n 字符串不為"null"
注意:
使用-n在[]結構中測試必須要用""把變量引起來.使用一個未被""的字符串來使用! -z
或者就是未用""引用的字符串本身,放到[]結構中。雖然一般情況下可
以工作,但這是不安全的.習慣于使用""來測試字符串是一種好習慣.
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhrmghl/archive/2006/10/22/1345115.aspx
測試平臺:RHEL4.5shell中數組的下標默認是從0開始的 1. 將字符串存放在數組中,獲取其長度 #!/bin/bash str="a b --n d" array=($str) length=${#array[@]} echo $length for ((i=0; i<$length; i++)) do echo ${array[$i]} done along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh 4 a b --n d 打印字符串: [root@mc2 tmp]# cat test.sh #!/bin/bash str="a b c" for i in $str do echo $i done [root@mc2 tmp]# cat array.sh #!/bin/bash str="a b c" array=($str) for ((i=0;i<${#array[@]};i++)) do echo ${array[$i]} done 結果: a b c 2. 字符串用其他字符分隔時 #!/bin/bash str2="a#b#c" a=($(echo $str2 | tr '#' ' ' | tr -s ' ')) length=${#a[@]} for ((i=0; i<$length; i++)) do echo ${a[$i]} done #echo ${a[2]} along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh a b c 3. 數組的其他操作 #!/bin/bash str="a b --n dd" array=($str) length=${#array[@]} #直接輸出的是數組的第一個元素 echo $array #用下標的方式訪問數組元素 echo ${array[1]} #輸出這個數組 echo ${array[@]} #輸出數組中下標為3的元素的長度 echo ${#array[3]} #輸出數組中下標為1到3的元素 echo ${array[@]:1:3} #輸出數組中下標大于2的元素 echo ${array[@]:2} #輸出數組中下標小于2的元素 echo ${array[@]::2} along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh a b a b --n dd 2 b --n dd --n dd a b 4. 遍歷訪問一個字符串(默認是以空格分開的,當字符串是由其他字符分隔時可以參考 2) #!/bin/bash str="a --m" for i in $str do echo $i done along@along-laptop:~/code/shell/shell/mycat/testfile$ ./para_test.sh a --m 5. 如何用echo輸出一個 字符串str="-n". 由于-n是echo的一個參數,所以一般的方法echo "$str"是無法輸出的. 解決方法可以有: echo x$str | sed 's/^x//' echo -ne "$str\n" echo -e "$str\n\c" printf "%s\n" $str (這樣也可以) |
來源地址: http://hi.bccn.net/space-21499-do-blog-id-13524.html
shell for 循環指令使用
2008-11-02 22:34
for可以使一些不支持通配符的命令對一系列文件進行操作。在WIN9X中,TYPE命令(顯示文件內容)是不支持*.txt這種格式的(WIN2K開始TYPE已支持通配)。遇到類似情況就可以用FOR:
for %a in (*.txt) do type %a
現分別舉例說明如下:
1. 用 /r 遍歷目錄樹
當用 *.* 或 *.txt 等文件名通配符作為 for /r 的循環范圍時,可以對當前目錄下所有文件(包括子目錄里面的文件)進行操作。舉個例子,你想在當前目錄的所有txt文件(包括子目錄)內容中查找"bluebear"字樣,但由于find本身不能遍歷子目錄,所以我們用for:
for /r . %a in (*.txt) do @find "bluebear" %a
for /r . %a in (.) do @if exist %aCVS rd /s /q %aCVS
for /r . %a in (.) do @if exist %aCVS @echo %aCVS
c: empa1.txt
c: empa2.txt
c: empsubdir3.txt
c: empsubdir4.txt
for /f %a in (todel.txt) do del %a
Volume in drive D is DATA
Volume Serial Number is C47C-9908
Directory of D: mp
09/26/2001 12:50 PM 18,426 alg0925.txt
12/02/2001 04:29 AM 795 bsample.txt
04/11/2002 04:18 AM 2,043 invitation.txt
4 File(s) 25,651 bytes
0 Dir(s) 4,060,700,672 bytes free
for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a DEL %a
for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a echo %a
alg0925.txt
bsample.txt
invitation.txt
FOR /F "delims==" %i IN ('set') DO @echo %i
ALLUSERSPROFILE
APPDATA
CLASSPATH
CommonProgramFiles
COMPUTERNAME
ComSpec
dircmd
HOMEDRIVE
......
FOR /F "delims== tokens=2" %i IN ('set') DO @echo %i
Sat 07/13/2002
for /f "tokens=3 delims=/ " %a in ('date /t') do @echo %a
for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b
g:mp3Archived-18-01-A游鴻明-下沙游鴻明-01 下沙.mp3
g:mp3Archived-18-01-A游鴻明-下沙游鴻明-02 21個人.mp3
......
g:mp3Archived-18-01-A王菲-寓言王菲-阿修羅.mp3
g:mp3Archived-18-01-A王菲-寓言王菲-彼岸花.mp3
g:mp3Archived-18-01-A王菲-寓言王菲-不愛我的我不愛.mp3
......
游鴻明-01 下沙
游鴻明-02 21個人
......
王菲-阿修羅
王菲-彼岸花
王菲-不愛我的我不愛
......
for /r g:mp3 %a in (*.mp3) do @echo %~na