《Oracle经典教程》
轉(zhuǎn)自?https://blog.csdn.net/self_realian/article/details/72724307
走進(jìn)Oracle.?2
1.????Oracle簡介...?3
2.????Oracle安裝...?4
3.????Oracle客戶端工具...?9
4.????Oracle服務(wù)...?16
5.????Oracle啟動和關(guān)閉...?17
6.????Oracle用戶和權(quán)限...?18
7.????本章總結(jié)...?21
8.????本章練習(xí)...?22
SQL數(shù)據(jù)操作和查詢...?25
1.????SQL簡介...?26
2.????Oracle數(shù)據(jù)類型...?26
3.????創(chuàng)建表和約束...?27
4.????數(shù)據(jù)操縱語言(DML)...?30
5.????操作符...?35
6.????高級查詢...?36
7.????本章總結(jié)...?44
8.????本章練習(xí)...?45
子查詢和常用函數(shù)...?48
1.????子查詢...?49
2.????Oracle中的偽列...?51
3.????Oracle函數(shù)...?54
4.????本章總結(jié)...?62
5.????本章練習(xí)...?63
表空間、數(shù)據(jù)庫對象...?66
1.????Oracle數(shù)據(jù)庫對象...?67
2.????同義詞...?67
3.????序列...?70
4.????視圖...?72
5.????索引...?74
6.????表空間...?75
7.????本章總結(jié)...?79
8.????本章練習(xí)...?80
PL/SQL程序設(shè)計...?83
1.????PL/SQL簡介...?84
2.????PL/SQL塊...?85
3.????PL/SQL數(shù)據(jù)類型...?89
4.????PL/SQL條件控制和循環(huán)控制...?91
5.????PL/SQL中動態(tài)執(zhí)行SQL語句...?101
6.????PL/SQL的異常處理...?102
7.????本章總結(jié)...?108
8.????本章練習(xí)...?109
Oracle應(yīng)用于.Net平臺...?111
1.????回顧ADO.NET.?112
2.????使用ADO.Net連接Oracle.?113
3.????抽象工廠中加入Oracle.?117
4.????本章總結(jié)...?121
5.????本章練習(xí)...?122
數(shù)據(jù)庫導(dǎo)入導(dǎo)出...?124
1.????Oracle導(dǎo)入導(dǎo)出...?125
2.????EXP導(dǎo)出數(shù)據(jù)...?125
3.????IMP導(dǎo)入...?128
4.????常見問題...?128
?
?
?
?
?
?
?
?
?
第1章
?
?
走進(jìn)Oracle
?
?
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? Oracle安裝 ü? Oracle創(chuàng)建用戶和角色 ü? 客戶端鏈接Oracle服務(wù)器 ? |
?
?
?
?
1.???Oracle簡介
在第一學(xué)期我們已經(jīng)接觸過關(guān)系型數(shù)據(jù)庫SQL Server,對數(shù)據(jù)庫、表、記錄、表的增刪改查操作等這些基本的概念已經(jīng)了解。Oracle是基于對象的關(guān)系型數(shù)據(jù)庫,Oracle也是用表的形式對數(shù)據(jù)存儲和管理,并且在Oracle的操作中添加了一些面向?qū)ο蟮乃枷搿?/p>
?
Oracle數(shù)據(jù)庫是Oracle(中文名稱叫甲骨文)公司的核心產(chǎn)品,Oracle數(shù)據(jù)庫是一個適合于大中型企業(yè)的數(shù)據(jù)庫管理系統(tǒng)。在所有的數(shù)據(jù)庫管理系統(tǒng)中(比如:微軟的SQL Server,IBM的DB2等),Oracle的主要用戶涉及面非常廣,包括:銀行、電信、移動通信、航空、保險、金融、電子商務(wù)和跨國公司等。Oracle產(chǎn)品是免費的,可以在Oracle官方網(wǎng)站上下載到安裝包,另一方面Oracle服務(wù)是收費的。
?
Oracle公司成立以來,從最初的數(shù)據(jù)庫版本到Oracle7、Oracle8i、Oracle9i,Oracle10g到Oracle11g,雖然每一個版本之間的操作都存在一定的差別,但是Oracle對數(shù)據(jù)的操作基本上都遵循SQL標(biāo)準(zhǔn)。因此對Oracle開發(fā)來說版本之間的差別不大。
?
很多人沒有學(xué)習(xí)Oracle就開始發(fā)怵,因為人們在誤解Oracle,認(rèn)為Oracle太難學(xué)了,認(rèn)為Oracle不是一般人用的數(shù)據(jù)庫,其實任何數(shù)據(jù)庫對應(yīng)用程序研發(fā)人員來說,都是大同小異,因為目前多數(shù)數(shù)據(jù)庫都支持標(biāo)準(zhǔn)的SQL。在Oracle這本書中,我們能學(xué)習(xí)到:
???Oracle的安裝
???Oracle數(shù)據(jù)管理
???常用子查詢及常用函數(shù)
???PL/SQL編程
???Oracle基本管理
?
由于在第一學(xué)期已經(jīng)接觸了SQL Server,Oracle數(shù)據(jù)庫的概念不是很難,主要是實踐,因此在本書的學(xué)習(xí)中,認(rèn)真的完成上機(jī)練習(xí)是學(xué)習(xí)好本書的關(guān)鍵。
?
接下來我們先從Oracle安裝開始,接觸一些Oracle中基本的概念。
?
2.???Oracle安裝
Oracle數(shù)據(jù)庫產(chǎn)品是免費的,我們可以從Oracle的官方網(wǎng)站(http://www.oracle.com)下載到程序安裝包,Oracle在Windows下的安裝非常方便,安裝開始后,一直點擊安裝程序的“下一步”即可。
?
1.???????下載Oracle10g后,解壓到一個文件夾下,單擊“setup.exe”文件即可啟動安裝界面。如下圖:
?
?
圖1??Oracle安裝啟動界面
?
Oracle主目錄位置就是Oracle準(zhǔn)備安裝的位置,稱為“Oracle_Home”,一般Oracle根據(jù)當(dāng)前計算機(jī)的硬盤大小默認(rèn)給出一個合適的位置。Oracle安裝時可以只安裝Oracle軟件,然后單獨創(chuàng)建數(shù)據(jù)庫,也可以在上圖中選中“創(chuàng)建啟動數(shù)據(jù)庫”復(fù)選框,在安裝Oracle產(chǎn)品時,同時創(chuàng)建一個數(shù)據(jù)庫,對初學(xué)者來說,推薦這樣安裝。填寫全局?jǐn)?shù)據(jù)庫名,以及管理員的密碼。全局?jǐn)?shù)據(jù)庫名是數(shù)據(jù)庫在服務(wù)器網(wǎng)絡(luò)中的唯一標(biāo)識。
?
2.???????點擊“下一步”,就會出現(xiàn)如下圖內(nèi)容,開始對Oracle服務(wù)器進(jìn)行環(huán)境檢查,主要查看服務(wù)器是否符合Oracle安裝的條件,比如操作系統(tǒng)是否支持、系統(tǒng)內(nèi)存是否符合Oracle安裝的最低要求等。
?
?
圖2??Oracle安裝前環(huán)境檢查
?
3.???????Oracle檢查通過后,單擊“下一步”,就會列出所有安裝Oracle過程中的默認(rèn)選項。
?
?
圖3??Oracle默認(rèn)安裝設(shè)置
?
4.???????單擊“安裝”按鈕,進(jìn)入安裝界面,這一過程經(jīng)歷時間比較長,根據(jù)計算機(jī)的性能不同有很大差別。
?
?
圖4??Oracle安裝
?
5.???????上圖完成后,進(jìn)入了各種Oracle工具的安裝階段,包括網(wǎng)絡(luò)配置向?qū)?#xff0c;iSQL*plus等(后面課程中講解)。如下圖所示:
?
?
圖5??Oracle各種工具的安裝
?
6.???????接下來自動啟動DBCA(Database Configuration Assistant)進(jìn)入創(chuàng)建默認(rèn)數(shù)據(jù)庫階段。
?
?
圖6? DBCA下安裝數(shù)據(jù)庫
?
???????? Oracle中的數(shù)據(jù)庫主要是指存放數(shù)據(jù)的文件,這些文件在Oracle安裝完成后,在計算機(jī)硬盤上都能找到,包括數(shù)據(jù)文件、控制文件和數(shù)據(jù)庫日志文件。
?
數(shù)據(jù)庫創(chuàng)建后會有一系列為該數(shù)據(jù)庫提供服務(wù)的內(nèi)存空間和后臺進(jìn)程,稱為該數(shù)據(jù)庫的實例。每一個數(shù)據(jù)庫至少會有一個實例為其服務(wù)。實例中的內(nèi)存結(jié)構(gòu)稱為系統(tǒng)全局區(qū)(SGA),系統(tǒng)會根據(jù)當(dāng)前計算機(jī)系統(tǒng)的性能給SGA分配非??捎^的內(nèi)存空間。
?
Oracle創(chuàng)建數(shù)據(jù)庫不能像SQL Server那樣用一個簡單的CREATE DATABASE命令就能完成,在創(chuàng)建數(shù)據(jù)庫的過程中還需要配置各種參數(shù)。雖然有DBCA工具向?qū)?#xff0c;但是仍然需要進(jìn)行比較麻煩的配置。
????????
| ? | 雖然一個Oracle數(shù)據(jù)庫服務(wù)器中可以安裝多個數(shù)據(jù)庫,但是一個數(shù)據(jù)庫需要占用非常大的內(nèi)存空間,因此一般一個服務(wù)器只安裝一個數(shù)據(jù)庫。每一個數(shù)據(jù)庫可以有很多用戶,不同的用戶擁有自己的數(shù)據(jù)庫對象(比如:數(shù)據(jù)庫表),一個用戶如果訪問其他用戶的數(shù)據(jù)庫對象,必須由對方用戶授予一定的權(quán)限。不同的用戶創(chuàng)建的表,只能被當(dāng)前用戶訪問。因此在Oracle開發(fā)中,不同的應(yīng)用程序只需使用不同的用戶訪問即可。 |
?
7.???????數(shù)據(jù)庫創(chuàng)建完畢后,需要設(shè)置數(shù)據(jù)庫的默認(rèn)用戶。Oracle中為管理員預(yù)置了兩個用戶分別是SYS和SYSTEM。同時Oracle為程序測試提供了一個普通用戶scott,口令管理中,可以對數(shù)據(jù)庫用戶設(shè)置密碼,設(shè)置是否鎖定。?Oracle客戶端使用用戶名和密碼登錄Oracle系統(tǒng)后才能對數(shù)據(jù)庫操作。
?
?
圖7??DBCA下的口令管理
?
圖8? 為system,sys,scott用戶設(shè)置密碼
?
?????????默認(rèn)的用戶中,SYS和SYSTEM用戶是沒有鎖定的,安裝成功后可以直接使用,SCOTT用戶默認(rèn)為鎖定狀態(tài),因此不能直接使用,需要把SCOTT用戶設(shè)定為非鎖定狀態(tài)才能正常使用。
?
?????????這一步完成后,Oracle系統(tǒng)安裝成功。
?
| ? | Oracle數(shù)據(jù)庫中,默認(rèn)情況下,所有系統(tǒng)的數(shù)據(jù),SQL關(guān)鍵字等都是大寫的,在操作過程中,Oracle會自動把這些內(nèi)容轉(zhuǎn)換為大寫,因此用戶操作時不需考慮大小寫問題,一般情況下,為了良好的程序風(fēng)格,程序中建議關(guān)鍵字用大寫,非關(guān)鍵字可以使用小寫。 |
?
3.???Oracle客戶端工具
Oracle服務(wù)器安裝成功后,就可以通過客戶端工具連接Oracle服務(wù)器了,可以到Oracle官方下載Oracle專用的客戶端軟件,大多客戶端工具都是基于Oracle客戶端軟件的。接下來介紹幾種常用的Oracle客戶端工具。
?
2??SQL*Plus工具
?
該工具是Oracle系統(tǒng)默認(rèn)安裝下,自帶的一個客戶端工具。在Windows命令行中輸入“sqlplusw”命令,就能夠啟動該工具了。
?
?
圖9? SQL*Plus工具
?
輸入用戶名和密碼后,如果SQL*Plus與數(shù)據(jù)庫服務(wù)器在同一臺計算機(jī)上,并且當(dāng)前服務(wù)器下只有一個數(shù)據(jù)庫實例,那么“主機(jī)字符串”可以不用填寫。
?
| ? | SQL*Plus工具雖然是Oracle自帶的工具,但是在現(xiàn)實開發(fā)中,基于該環(huán)境對開發(fā)不方便,因此很少使用。 |
?
SQL*Plus連接成功后就如圖所示:
?
?
圖10??SQL*Plus工具登錄后
?
2??SQL*Plus命令行工具
?
該命令行工具,提供了與數(shù)據(jù)庫交互的能力和維護(hù)數(shù)據(jù)庫的能力,包括了Oracle自帶的SQL*Plus工具的全部功能,在Oracle管理中經(jīng)常使用。在命令行中輸入:“sqlplus /nolog”即可啟動該工具。如下圖:
?
?
圖11? 啟動SQL*Plus命令行工具
?
?????????輸入“sqlplus /nolog”命令后,只是啟動了一個客戶端進(jìn)程,并沒有與服務(wù)器連接,連接到Oracle服務(wù)器的命令是:
?
conn?用戶名/密碼?as?連接身份@服務(wù)器連接字符串
?
說明:
1.???????連接身份:表示該用戶連接后擁有的權(quán)限。
???sysdba:即數(shù)據(jù)庫管理員,權(quán)限包括:打開數(shù)據(jù)庫服務(wù)器、關(guān)閉數(shù)據(jù)庫服務(wù)器、備份數(shù)據(jù)庫、恢復(fù)數(shù)據(jù)庫、日志歸檔、會話限制、管理功能、創(chuàng)建數(shù)據(jù)庫。sys用戶必須用sysdba身份才能登錄,system用戶可以用普通身份登錄。
???sysyoper:即數(shù)據(jù)庫操作員,權(quán)限包括:打開數(shù)據(jù)庫服務(wù)器、關(guān)閉數(shù)據(jù)庫服務(wù)器、備份數(shù)據(jù)庫、恢復(fù)數(shù)據(jù)庫、日志歸檔、會話限制。
???normal:即普通用戶,權(quán)限只有查詢某些數(shù)據(jù)表的數(shù)據(jù)。默認(rèn)的身份是normal用戶。
?
2.???????客戶端工具可以根據(jù)“服務(wù)器連接字符串”對服務(wù)器進(jìn)行連接,有了連接字符串后客戶端就可以像操作本機(jī)一樣操作遠(yuǎn)程數(shù)據(jù)庫,因此“服務(wù)器連接字符串”的配置也叫本地網(wǎng)絡(luò)服務(wù)配置,如果SQL*Plus工具啟動在服務(wù)器上,并且服務(wù)器上只有一個數(shù)據(jù)庫實例的情況下,連接字符串可以缺省,在連接字符串中包括連接服務(wù)器的協(xié)議,服務(wù)器的地址,服務(wù)器的端口等設(shè)置,Oracle服務(wù)名等,該配置文件在Oracle安裝目錄下的:?network/ADMIN/ tnsnames.ora。該文件是一個文本文件,用記事本打開后如下所示:
?
?
圖12? 服務(wù)器連接字符串配置
?
2??配置本地網(wǎng)絡(luò)服務(wù)名
?
?????????本地網(wǎng)絡(luò)服務(wù)名,即客戶端與服務(wù)器的連接字符串,本地網(wǎng)絡(luò)服務(wù)名是客戶端的配置,Oracle客戶端安裝后,可以使用客戶端自帶的網(wǎng)絡(luò)配置向?qū)?#xff08;Net Configuration Assistant)進(jìn)行配置:
?
1.???????啟動Net Configuration Assistant。選擇“本地Net服務(wù)名配置”選項。如下圖所示:
?
?
圖13? 啟動Net Configuration Assistant
?
2.???????選擇“下一步”,本步驟可以對本地網(wǎng)絡(luò)服務(wù)名進(jìn)行添加,刪除,測試是否正常連接等操作,選擇“添加”選項。
?
?
圖14??Net Configuration Assistant
?
3.???????點擊“下一步”,填寫服務(wù)名,該服務(wù)名就是Oracle安裝時(圖1),為數(shù)據(jù)庫取的全局?jǐn)?shù)據(jù)庫名。
?
?
圖15? 服務(wù)名配置
?
4.???????點擊“下一步”,選擇服務(wù)需要的協(xié)議,默認(rèn)是TCP協(xié)議。推薦使用默認(rèn)的TCP協(xié)議。
?
?
圖16? 選擇協(xié)議
?
5.???????點擊“下一步”,輸入主機(jī)名,主機(jī)名可以是計算機(jī)名稱,也可以是一個IP地址,主機(jī)如果是本機(jī),可以使用本機(jī)計算機(jī)名稱、“l(fā)ocalhost”、“127.0.0.1”、或者本機(jī)的IP地址。
?
?
圖17? 輸入主機(jī)名和端口
?
6.???????單擊“下一步”,選擇“是,進(jìn)行測試”選項。進(jìn)入下圖界面。
?
?
圖18? 測試成功
?
在測試時,默認(rèn)采用的用戶名和密碼是system/manager進(jìn)行測試,如果用戶system的密碼不是“manager”,有可能測試通不過,更改登錄后,輸入正確的用戶名和密碼后再進(jìn)行測試即可。
7.???????測試成功后,單擊“下一步”,出現(xiàn)如下界面,這一步是為本地網(wǎng)絡(luò)服務(wù)命名,即圖12中的服務(wù)器連接字符串名。
?
?
圖19? 為網(wǎng)絡(luò)服務(wù)名命名
?
?????????點擊“下一步”,配置就完成了,進(jìn)入tnsnames.ora文件中查看,就出現(xiàn)了如圖12中的內(nèi)容。
?
2??PL/SQL Developer工具
?
在實際Oracle開發(fā)中,經(jīng)常使用一個功能強(qiáng)大的第三方工具:“PL/SQL Developer”工具。PL/SQL Developer基本上可以實現(xiàn)Oracle開發(fā)中的任何操作。它運行在客戶端時必須先安裝Oracle客戶端,并且通過網(wǎng)絡(luò)配置向?qū)渲镁W(wǎng)絡(luò)服務(wù)名后才能正常與服務(wù)器連接。
?
?
圖20 PL/SQL Developer
?
4.???Oracle服務(wù)
Oracle在windows中安裝完成后,會安裝很多服務(wù),下面介紹幾個主要的服務(wù)。
?
?
圖21?Oracle服務(wù)
?
???OracleService+服務(wù)名,該服務(wù)是數(shù)據(jù)庫啟動的基礎(chǔ),只有該服務(wù)啟動了,Oracle數(shù)據(jù)庫才能正常啟動。這是必須啟動的服務(wù)。
???OracleOraDb10g_home1TNSListener,該服務(wù)是服務(wù)器端為客戶端提供的監(jiān)聽服務(wù),只有該服務(wù)在服務(wù)器上正常啟動,客戶端才能連接到服務(wù)器。該監(jiān)聽服務(wù)接收客戶端發(fā)出的請求,然后將請求傳遞給數(shù)據(jù)庫服務(wù)器。一旦建立了連接,客戶端和數(shù)據(jù)庫服務(wù)器就能直接通信了。
???OracleOraDb10g_home1iSQL*Plus,該服務(wù)提供了用瀏覽器對數(shù)據(jù)庫中數(shù)據(jù)操作的方式。該服務(wù)啟動后,就可以使用瀏覽器進(jìn)行遠(yuǎn)程登錄并進(jìn)行數(shù)據(jù)庫操作了。如下圖所示:
?
?
圖22 iSQL*Plus
?
???OracleDBConsole+服務(wù)名,Oracle10g中的一個新服務(wù)。在Oracle9i之前,Oracle官方提供了一個基于圖形界面的企業(yè)管理器(EM),從Oracle10g開始,Oracle提供了一個基于B/S的企業(yè)管理器,在操作系統(tǒng)的命令行中輸入命令:emctl start dbconsole,就可以啟動OracleDbConsole服務(wù),如下圖所示:
?
?
圖23?EM服務(wù)的啟動
?
?????????服務(wù)啟動之后,就可以在瀏覽器中輸入上圖中進(jìn)入EM的地址,使用B/S方式管理Oracle服務(wù)器。
?
5.???Oracle啟動和關(guān)閉
OracleService啟動動后,就可以對數(shù)據(jù)庫進(jìn)行管理了,Oracle的啟動和關(guān)閉是最基本的命令,在SQL*Plus中,啟動Oracle必須是sys用戶,命令格式是:
?
startup open
?
?
圖24?Oracle服務(wù)啟動
?
???????? Oracle服務(wù)關(guān)閉用命令:shutdown immediate
?
?
圖25?Oracle服務(wù)關(guān)閉
?
6.???Oracle用戶和權(quán)限
Oracle中,一般不會輕易在一個服務(wù)器上創(chuàng)建多個數(shù)據(jù)庫,在一個數(shù)據(jù)庫中,不同的項目由不同的用戶訪問,每一個用戶擁有自身創(chuàng)建的數(shù)據(jù)庫對象,因此用戶的概念在Oracle中非常重要。Oracle的用戶可以用CREATE USER命令來創(chuàng)建。其語法是:
?
語法結(jié)構(gòu):創(chuàng)建用戶
| CREATE USER 用戶名 IDENTIFIED BY 口令 [ACCOUNT LOCK|UNLOCK] |
語法解析:
???????? LOCK|UNLOCK創(chuàng)建用戶時是否鎖定,默認(rèn)為鎖定狀態(tài)。鎖定的用戶無法正常的登錄進(jìn)行數(shù)據(jù)庫操作。
?
代碼演示:創(chuàng)建用戶
| SQL> CREATE USER jerry 2? IDENTIFIED BY tom 3? ACCOUNT UNLOCK; |
????????
| ? | Oracle在SQL*Plus中的命令以分號(;)結(jié)尾,代表命令完畢并執(zhí)行,系統(tǒng)同時會把該命令保存在緩存中,緩存中只保存最近執(zhí)行過的命令,如果重新執(zhí)行緩存中的命令,直接使用左斜杠符號(/)。如果命令不以分號結(jié)尾,該命令只是寫入緩存保存起來,但并不執(zhí)行。 |
?
?????????盡管用戶成功創(chuàng)建,但是還不能正常的登錄Oracle數(shù)據(jù)庫系統(tǒng),因為該用戶還沒有任何權(quán)限。如果用戶能夠正常登錄,至少需要CREATE SESSION系統(tǒng)權(quán)限。
?
???????? Oracle用戶對數(shù)據(jù)庫管理或?qū)ο蟛僮鞯臋?quán)利,分為系統(tǒng)權(quán)限和數(shù)據(jù)庫對象權(quán)限。系統(tǒng)權(quán)限比如:CREATE SESSION,CREATE TABLE等,擁有系統(tǒng)權(quán)限的用戶,允許擁有相應(yīng)的系統(tǒng)操作。數(shù)據(jù)庫對象權(quán)限,比如對表中的數(shù)據(jù)進(jìn)行增刪改操作等,擁有數(shù)據(jù)庫對象權(quán)限的用戶可以對所擁有的對象進(jìn)行對應(yīng)的操作。
?
?????????還有一個概念就是數(shù)據(jù)庫角色(role),數(shù)據(jù)庫角色就是若干個系統(tǒng)權(quán)限的集合。下面介紹幾個常用角色:
???CONNECT角色,主要應(yīng)用在臨時用戶,特別是那些不需要建表的用戶,通常只賦予他們CONNECT role。CONNECT是使用Oracle的簡單權(quán)限,擁有CONNECT角色的用戶,可以與服務(wù)器建立連接會話(session,客戶端對服務(wù)器連接,稱為會話)。
???RESOURCE角色,更可靠和正式的數(shù)據(jù)庫用戶可以授予RESOURCE role。RESOURCE提供給用戶另外的權(quán)限以創(chuàng)建他們自己的表、序列、過程(procedure)、觸發(fā)器(trigger)、索引(index)等。
???DBA角色,DBA role擁有所有的系統(tǒng)權(quán)限----包括無限制的空間限額和給其他用戶授予各種權(quán)限的能力。用戶SYSTEM擁有DBA角色。
?
一般情況下,一個普通的用戶(如SCOTT),擁有CONNECT和RESOURCE兩個角色即可進(jìn)行常規(guī)的數(shù)據(jù)庫開發(fā)工作。
?
?????????可以把某個權(quán)限授予某個角色,可以把權(quán)限、角色授予某個用戶。系統(tǒng)權(quán)限只能由DBA用戶授權(quán),對象權(quán)限由擁有該對象的用戶授權(quán),授權(quán)語法是:
?
語法結(jié)構(gòu):授權(quán)
| GRANT角色|權(quán)限 TO 用戶(角色) |
?
代碼演示:授權(quán)
| SQL> GRANT CONNECT TO jerry; 授權(quán)成功。 SQL> GRANT RESOURCE TO jerry; 授權(quán)成功。 SQL> |
????????
語法結(jié)構(gòu):其他操作
| //回收權(quán)限 REVOKE 角色|權(quán)限 FROM 用戶(角色) //修改用戶的密碼 ALTER USER?用戶名?IDENTIFIED BY?新密碼 //修改用戶處于鎖定(非鎖定)狀態(tài) ALTER USER 用戶名 ACCOUNT LOCK|UNLOCK |
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
7.???本章總結(jié)
???Oracle是基于對象的關(guān)系型數(shù)據(jù)庫,Oracle產(chǎn)品免費,服務(wù)收費。
???Oracle安裝后默認(rèn)會有兩個管理員用戶(system,sys)和一個普通用戶Scott。
???Sql*plus是Oracle管理和數(shù)據(jù)操作的客戶端工具。
???客戶端鏈接服務(wù)器前,服務(wù)器要啟動監(jiān)聽服務(wù),并且客戶端工具要安裝Oracle客戶端,并且在客戶端要建立本地網(wǎng)絡(luò)服務(wù)名。
???Oracle服務(wù)和監(jiān)聽啟動后才能對數(shù)據(jù)庫進(jìn)行操作。
???用startup命令啟動數(shù)據(jù)庫,用shutdown命令關(guān)閉數(shù)據(jù)庫。
???Oracle的角色包括了一系列系統(tǒng)權(quán)限和普通對象權(quán)限,可以把權(quán)限授權(quán)給角色,把權(quán)限或者角色授權(quán)給用戶。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
8.???本章練習(xí)
1.???????描述Oracle安裝過程中的關(guān)鍵點。
2.???????描述創(chuàng)建本地網(wǎng)絡(luò)服務(wù)名的步驟。
3.???????描述Oracle主要服務(wù)的作用。
4.???????Oracle使用什么命令才能啟動和關(guān)閉。
5.???????什么是Oracle權(quán)限和角色?他們的關(guān)系是什么?
6.???????創(chuàng)建一個用戶,并授權(quán)CONNECT和RESOURCE。
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
第2章
?
?
SQL數(shù)據(jù)操作和查詢
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? Oracle數(shù)據(jù)類型 ü? SQL建表和約束 ü? SQL對數(shù)據(jù)增刪改 ü? SQL查詢 ü? Oracle偽列 ? |
?
?
1.???SQL簡介
在第一學(xué)期的SQL Server學(xué)習(xí)中,已經(jīng)知道,SQL是結(jié)構(gòu)化查詢語言(Structured Query Language[D1]?),專門用于數(shù)據(jù)存取、數(shù)據(jù)更新及數(shù)據(jù)庫管理等操作。并且已經(jīng)學(xué)習(xí)了用SQL語句對數(shù)據(jù)庫的表進(jìn)行增刪改查的操作。
?
在Oracle開發(fā)中,客戶端把SQL語句發(fā)送給服務(wù)器,服務(wù)器對SQL語句進(jìn)行編譯、執(zhí)行,把執(zhí)行的結(jié)果返回給客戶端。Oracle SQL語句由如下命令組成:
???數(shù)據(jù)定義語言Data?Definition?Language(DDL)[D2]?,包括CREATE(創(chuàng)建)命令、ALTER(修改)命令、DROP(刪除)命令等。
???數(shù)據(jù)操縱語言Data?Manipulation?Language(DML)[D3]?,包括INSERT(插入)命令、UPDATE(更新)命令、DELETE(刪除)命令、SELECT … FOR UPDATE(查詢)等。
???數(shù)據(jù)查詢語言Data Query Language(DQL),包括基本查詢語句、Order By子句、Group By子句等。
???事務(wù)控制語言(TCL),包括COMMIT(提交)命令、SAVEPOINT(保存點)命令、ROLLBACK(回滾)命令。
???數(shù)據(jù)控制語言(DCL),GRANT(授權(quán))命令、REVOKE(撤銷)命令。
?
目前主流的數(shù)據(jù)庫產(chǎn)品(比如:SQL Server、Oracle)都支持標(biāo)準(zhǔn)的SQL語句。數(shù)據(jù)定義語言,表的增刪改操作,數(shù)據(jù)的簡單查詢,事務(wù)的提交和回滾,權(quán)限的授權(quán)和撤銷等,Oracle與SQL Server在操作上基本一致。
?
2.???Oracle數(shù)據(jù)類型
Oracle數(shù)據(jù)庫的核心是表,表中的列使用到的常見數(shù)據(jù)類型如下:
?
| 類型 | 含義 |
| CHAR(length) | 存儲固定長度的字符串。參數(shù)length指定了長度,如果存儲的字符串長度小于length,用空格填充。默認(rèn)長度是1,最長不超過2000字節(jié)。 |
| VARCHAR2(length) | 存儲可變長度的字符串。length指定了該字符串的最大長度。默認(rèn)長度是1,最長不超過4000字符。 |
| NUMBER(p,s) | 既可以存儲浮點數(shù),也可以存儲整數(shù),p表示數(shù)字的最大位數(shù)(如果是小數(shù)包括整數(shù)部分和小數(shù)部分和小數(shù)點,p默認(rèn)是38為),s是指小數(shù)位數(shù)。 |
| DATE | 存儲日期和時間,存儲紀(jì)元、4位年、月、日、時、分、秒,存儲時間從公元前4712年1月1日到公元后4712年12月31日。 |
| TIMESTAMP | 不但存儲日期的年月日,時分秒,以及秒后6位,同時包含時區(qū)。 |
| CLOB | 存儲大的文本,比如存儲非結(jié)構(gòu)化的XML文檔 |
| BLOB | 存儲二進(jìn)制對象,如圖形、視頻、聲音等。 |
表1??Oracle的部分?jǐn)?shù)據(jù)類型
?
?????????對應(yīng)NUMBER類型的示例:
?
| 格式 | 輸入的數(shù)字 | 實際的存儲 |
| NUMBER | 1234.567 | 1234.567 |
| NUMBER(6,2) | 123.4567 | 123.46 |
| NUMBER(4,2) | 12345.67 | 輸入的數(shù)字超過了所指定的精度,數(shù)據(jù)庫不能存儲 |
表2??Number示例
?
?????????對于日期類型,可以使用sysdate內(nèi)置函數(shù)可以獲取當(dāng)前的系統(tǒng)日期和時間,返回DATE類型,用systimestamp函數(shù)可以返回當(dāng)前日期、時間和時區(qū)。
?
?
圖1??sysdate和sysTimestamp
?
???????? Oracle的查詢中,必須使用“select?列… from?表”的完整語法,當(dāng)查詢單行函數(shù)的時候,from后面使用DUAL表,dual表在系統(tǒng)中只有一行一列,該表在輸出單行函數(shù)時為了select…from的語法完整性而使用。
?
3.???創(chuàng)建表和約束
Oracle創(chuàng)建表同SQL Server一樣,使用CREATE TABLE命令來完成。創(chuàng)建約束則使用如下命令:
語法格式:ALTERTABLE命令
| ???ALTER TABLE?表名?ADDCONSTRAINT[D4]?約束名約束內(nèi)容。 |
?
不論創(chuàng)建表還是約束,與SQL Server基本相同,注意:在Oracle中default是一個值,而SQL Server中default是一個約束[D5]?,因此Oracle的default設(shè)置可以在建表的時候創(chuàng)建。
?
案例1:創(chuàng)建一個學(xué)生信息(INFOS)表和約束
?
代碼演示:Oracle創(chuàng)建表和約束
| CREATE TABLE INFOS ( ??STUID VARCHAR2(7) NOT NULL,????--學(xué)號 學(xué)號=‘S’+班號+2位序號 ??STUNAME VARCHAR2(10) NOT NULL,? --姓名 ??GENDER VARCHAR2(2) NOT NULL,??? --性別? ??AGE NUMBER(2) NOT NULL,??????? --年齡 ??SEAT NUMBER(2) NOT NULL,??????? --座號 ??ENROLLDATE DATE,????? --入學(xué)時間 ??STUADDRESS VARCHAR2(50)?DEFAULT?'地址不詳',??????--住址 ??CLASSNO VARCHAR2(4) NOT NULL??? --班號班號=學(xué)期序號+班級序號? ) /? ① ALTER TABLE INFOS ADD?CONSTRAINT PK_INFOS PRIMARY KEY(STUID)?②[D6]? / ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_GENDER? CHECK(GENDER = '男' OR GENDER = '女')??③[D7]? / ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_SEAT CHECK(SEAT >=0 AND SEAT <=50)??④ / ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_AGE? CHECK(AGE >=0 AND AGE<=100)??⑤ / ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_CLASSNO? CHECK((CLASSNO >='1001' AND CLASSNO<='1999') OR (CLASSNO >='2001' AND CLASSNO<='2999'))??⑥ / ALTER TABLE INFOS ADD CONSTRAINTS UN_STUNAME UNIQUE(STUNAME)??⑦[D8]? / |
代碼解析:
①??在Oracle代碼中,“/”執(zhí)行緩存區(qū)中的語句,由于緩沖區(qū)中只存儲一條剛剛保存過語句,由于每條語句沒有用分號結(jié)尾,只是保存在緩沖區(qū),因此每條語句后面都有單獨一行“/”。
②??創(chuàng)建一個主鍵約束[D9]?。
③??與 ④ ⑤ ⑥ ⑦一起創(chuàng)建各種check約束。其中⑦是唯一約束,表示該列值是唯一的,列中的值不能重復(fù)。
?
Oracle中創(chuàng)建外鍵約束與SQL Server相同。比如:現(xiàn)有成績表定義如下:
?
案例2:創(chuàng)建一個成績表(SCORES)表和約束
?
代碼演示:Oracle創(chuàng)建表和約束
| CREATE TABLE SCORES ( ????ID NUMBER ,??????? ????????????????????????--ID??① ????TERM VARCHAR2(2),????????????????????????????? ???? --學(xué)期 S1或S2 ??? ? STUID VARCHAR2(7) NOT NULL,?????????????????? --學(xué)號 ??? ? EXAMNO VARCHAR2(7) NOT NULL,?????????????? --考號 E+班號+序號????? ??? ? WRITTENSCORE NUMBER(4,1) NOT NULL,??? --筆試成績 ??? ? LABSCORE NUMBER(4,1) NOT NULL???????????? --機(jī)試成績 ) ALTER TABLE SCORES ??? ADD CONSTRAINT CK_SCORES_TERM CHECK(TERM = 'S1' OR TERM ='S2') / ALTER TABLE SCORES ??? ADD CONSTRAINT FK_SCORES_INFOS_STUID FOREIGN KEY(STUID) REFERENCES INFOS(STUID)??② / |
代碼解析:
①??SQL Server中可以使用identify創(chuàng)建自動增長列,但是Oracle中的自動增長需要借助序列(Sequence)完成,在后面章節(jié)中講解。
②??Oracle中的外鍵約束定義。
?
4.???數(shù)據(jù)操縱語言(DML)
數(shù)據(jù)操縱語言(DML)用于對數(shù)據(jù)庫的表中數(shù)據(jù)進(jìn)行添加、修改、刪除和SELECT…For UPDATE(后面專門學(xué)習(xí)該查詢)操作。對比一期學(xué)習(xí)過的SQL Server操作,接下來一一介紹在Oracle中的操作。
?
2??簡單查詢
?
數(shù)據(jù)查詢是用SELECT命令從數(shù)據(jù)庫的表中提取信息。SELECT語句的語法是:
?
語法結(jié)構(gòu):簡單查詢
| SELECT *|列名|表達(dá)式?FROM?表名?WHERE?條件?ORDER BY?列名 |
語法解析:
1.???????*表示表中的所有列。
2.???????列名可以選擇若干個表中的列名,各個列表中間用逗號分隔。
3.???????表達(dá)式可以是列名、函數(shù)、常數(shù)等組成的表達(dá)式。
4.???????WHERE子句是查詢的條件。
5.???????ORDER BY?要求在查詢的結(jié)果中排序,默認(rèn)是升序[D10]?。
?
?
圖2? 數(shù)據(jù)查詢
????????
???????? Oracle中可以把查詢的結(jié)果根據(jù)結(jié)果集中的表結(jié)構(gòu)和數(shù)據(jù)形成一張新表。
?
語法結(jié)構(gòu):根據(jù)結(jié)果集創(chuàng)建表
| CREATE TABLE?表名?AS SELECT語句 |
?
代碼演示:根據(jù)結(jié)果集創(chuàng)建表
| SQL> CREATE TABLE INFOS1 AS SELECT * FROM INFOS; TABLE CREATED |
?
?????????使用上面命令創(chuàng)建的新表中,不存在任何約束,并且把查詢的數(shù)據(jù)一起插入到新表中。如果只復(fù)制表結(jié)構(gòu),只需使查詢的條件不成立(比如where 1=2),就不會查詢從出任何數(shù)據(jù),從而復(fù)制一個表結(jié)構(gòu)。
????????
代碼演示:復(fù)制表結(jié)構(gòu)
| SQL> CREATE TABLE INFOS2 AS SELECT * FROM INFOS WHERE 1=2; TABLE CREATED |
?
2??數(shù)據(jù)插入
?
用INSERT命令完成對數(shù)據(jù)的插入。
?
語法結(jié)構(gòu):根據(jù)結(jié)果集創(chuàng)建表
| INSERT INTO?表名(列名1,列名2……) VALUES (值1,值2……) |
語法解析:
1.???????列名可以省略。當(dāng)省略列名時,默認(rèn)是表中的所有列名,列名順序為表定義中列的先后順序。
2.???????值的數(shù)量和順序要與列名的數(shù)量和順序一致。值的類型與列名的類型一致。
?
代碼演示:向INFOS表和SCORES表中插入數(shù)據(jù)
| SQL> INSERT INTO INFOS VALUES (? ① ? 2? 's100102', '林沖', '男', 22, 2, ? 3? TO_DATE('2009-8-9 06:30:10','YYYY-MM-DD HH24:MI:SS '),? ② ? 4? '西安', '1001' ??5? ) ??6? / 1 row inserted SQL> INSERT INTO INFOS VALUES ( 's100104','阮小二','男',26,3,SYSDATE,default,'1001');? ③ ?1 row inserted SQL>COMMIT;? ④ |
代碼解析:
①??表名后面缺省了列名,默認(rèn)是表Infos中的所有列名,values中的值要與表中列一一對應(yīng),包括順序和數(shù)據(jù)類型的對應(yīng)。在SQL*Plus中一條語句可以寫在多行,那么從第二行開始,sqlplus會為每一行前面給出行號。
②??在Oracle中,日期是國際化的,不同的區(qū)域安裝的數(shù)據(jù)庫,默認(rèn)的日期格式不同,因此為了程序便于移植,日期的輸入要使用TO_DATE函數(shù)對日期格式化后輸入,采用格式化字符串對日期進(jìn)行格式化時,格式化字符串中字符不區(qū)分大小寫,常見的格式化字符如下:
1.?????????yyyy表示四位年份
2.?????????mm表示兩位月份,比如3月表示為03
3.?????????dd表示兩位日期
4.?????????hh24表示小時從0-23,hh12也表示小時從0-11。
5.?????????mi?表示分鐘
6.?????????ss表示秒
③??在遇到存在默認(rèn)值的列時,可以使用default值代替。
④??commit是把用戶操作(添加、刪除、修改操作)提交,只有提交操作后,數(shù)據(jù)才能真正更新到表中,否則其他用戶無法查詢到當(dāng)前用戶操作的結(jié)果。
?
在Oracle中,一個INSERT命令可以把一個結(jié)果集一次性插入到一張表中。使用的語句是:INSERT INTO?表?SELECT子句,如下示例:
?
代碼演示:INSERT向表中插入一個結(jié)果集
| SQL> INSERT INTO INFOS2 SELECT * FROM INFOS; 5 rows inserted |
?
在這種語法下,要求結(jié)果集中每一列的數(shù)據(jù)類型必須與表中的每一列的數(shù)據(jù)類型一致,結(jié)果集中的列的數(shù)量與表中的列的數(shù)量一致。比如表INFOS2,該表的結(jié)構(gòu)與INFO表一樣,那么可以把INFO表中的所有記錄一次性插入到INFOS2表中。
?
Oracle的簡單查詢和SQL Server一樣都可以在查詢列中使用常量,如圖:
?
?
圖3? Select中的常量
?
可以使用剛才的做法,把該結(jié)果集中的數(shù)據(jù)插入到表INFOS中。
?
代碼演示:INSERT向表中插入一個常量結(jié)果集
| SQL> INSERT INTO INFOS SELECT 's100106','盧俊義','男',23,5, ?????? ????????TO_DATE('2009-8-9 08:00:10','YYYY-MM-DD HH24:MI:SS'), ?????????????? '青龍寺','1001' FROM DUAL; 1 rows inserted SQL>COMMIT; |
?
2??更新數(shù)據(jù)
?
Oracle在表中更新數(shù)據(jù)的語法是:
?
語法結(jié)構(gòu):UPDATE操作
| UPDATE?表名?SET?列名1=值,列名2=值…… WHERE?條件 |
?
代碼演示:UPDATE操作
| SQL> UPDATE INFOS SET CLASSNO='1002',STUADDRESS='山東萊蕪' WHERE STUNAME='阮小二'; 1 rows updated SQL> commit; |
?
2??刪除數(shù)據(jù)
?
Oracle在表中刪除數(shù)據(jù)的語法是:
?
語法結(jié)構(gòu):DELETE操作
| DELETE FROM表名?WHERE?條件 |
?
代碼演示:DELETE操作
| SQL> DELETE FROM INFOS WHERE STUID='s100103'; 1 ROW DELETED SQL> COMMIT; |
?
2??TRUNCATE
?
在數(shù)據(jù)庫操作中,TRUNCATE[D11]?命令(是一個DDL命令)可以把表中的所有數(shù)據(jù)一次性全部刪除,語法是:
?
語法結(jié)構(gòu):TRUNCATE
| TRUNCATE TABLE?表名 |
?
TRUNCATE和DELETE都能把表中的數(shù)據(jù)全部刪除,他們的區(qū)別是:
1.???????TRUNCATE是DDL命令,刪除的數(shù)據(jù)不能恢復(fù);DELETE命令是DML命令,刪除后的數(shù)據(jù)可以通過日志文件恢復(fù)。
2.???????如果一個表中數(shù)據(jù)記錄很多,TRUNCATE相對DELETE速度快。
?
由于TRUNCATE命令比較危險,因此在實際開發(fā)中,TRUNCATE命令慎用。
?
| ? | Oracle默認(rèn)安裝中,已經(jīng)創(chuàng)建了一個SCOTT用戶,默認(rèn)密碼是:tiger,該用戶下有四張表分別是:雇員表(EMP),部門表(DEPT),工資登記表和獎金表,請參考本章后面的附表。接下來很多操作都是在該用戶下完成的。 |
?
5.???操作符
Oracle開發(fā)中,依然存在算術(shù)運算,關(guān)系運算,和邏輯運算。
?
2??算術(shù)運算
?
Oracle中的算術(shù)運算符,沒有C#中的算術(shù)運算符豐富,只有+、-、*、/四個,其中除號(/)的結(jié)果是浮點數(shù)。求余運算只能借助函數(shù):MOD(x,y):返回x除以y的余數(shù)。
?
案例3:每名員工年終獎是2000元,請顯示基本工資在2000元以上的員工的月工資,年總工資。
該案例的表請參見本章練習(xí)的附表1、附表2、附表3,這三張表是ORACLE 10g自帶的。
?
代碼演示:查詢中的算術(shù)運算
| SQL> SELECT ENAME,SAL,(SAL*12+2000) FROM EMP WHERE SAL>2000;
6 rows selected |
?
2??關(guān)系運算和邏輯運算
?
Oracle中Where子句經(jīng)中經(jīng)常見到關(guān)系運算和邏輯運算,常見的關(guān)系運算有:
?
| 運算符 | 說明 | 運算符 | 說明 |
| = | 等于 | >? | 大于 |
| <>或者!= | 不等于 | <= | 小于或者等于 |
| <? | 小于 | >= | 大于或者等于 |
表3??Oracle的關(guān)系運算符
?
邏輯運算符有三個:AND、OR、NOT
?
關(guān)系運算和邏輯運算與前面SQL Server學(xué)習(xí)過的一致。
?
2??字符串連接操作符(||)
?
在Oracle中,字符串的連接用雙豎線(||)表示。比如,在EMP表中,查詢工資在2000元以上的姓名以及工作。
?
代碼演示:字符串連接
| SQL> SELECT (ENAME || 'is a ' || JOB) AS "Employee Details"? ① ? 2? FROM EMP ? 3? WHERE SAL>2000; Employee Details ------------------------ JONESis a MANAGER BLAKEis a MANAGER CLARKis a MANAGER SCOTTis a ANALYST KINGis a PRESIDENT FORDis a ANALYST 6 rows selected |
代碼解析:
①??Oracle中字符串可以用單引號,也可以用雙引號,在別名中存在空格時,必須用雙引號。在表名、列名時用雙引號。
?
6.???高級查詢
在第一期學(xué)習(xí)過SQL的簡單查詢和連接查詢。現(xiàn)在學(xué)習(xí)一些新的SQL操作符。
?
2??消除重復(fù)行
?
在Oracle查詢中結(jié)果中,可能出現(xiàn)若干行相同的情況,那么可以使用DISTINCT消除重復(fù)行。具體的用法如示例:
?
代碼演示:DISTINCT消除重復(fù)行
| SQL> SELECT DISTINCT DEPTNO FROM EMP; DEPTNO ------ ??? 30 ??? 20 ??? 10 |
?
2??NULL操作
?
如果某條記錄中有缺少的數(shù)據(jù)值,就是空值(NULL值)??罩挡坏扔?或者空格,空值是指未賦值、未知或不可用的值。任何數(shù)據(jù)類型的列都可以包括NULL值,除非該列被定義為非空或者主鍵。
????????
代碼演示:EMP中的NULL值
| SQL> SELECT ENAME,JOB,SAL,COMM FROM EMP WHERE SAL<2000;
7 rows selected |
?
?????????在查詢條件中NULL值用IS NULL作條件,非NULL值用NOT IS NULL做條件。???
?
案例4:查詢EMP表中沒有發(fā)獎金的員工。
?
代碼演示:NULL值查詢
| SQL> SELECT ENAME,JOB,SAL,COMM FROM EMP 2?? WHERE SAL<2000 AND COMM IS NULL;
? |
?
2??IN 操作
?
在Where子句中可以使用IN操作符來查詢其列值在指定的列表中的行。比如:查詢出工作職責(zé)是SALESMAN、PRESIDENT或者ANALYST的員工。條件有兩種表示方法:
1.???????WHERE job = 'SALESMAN ' OR job = 'PRESIDENT ' OR job = 'ANALYST '
2.???????WHERE job IN ('SALESMAN', 'PRESIDENT', 'ANALYST')
?
代碼演示:IN操作
| SQL> SELECT ENAME,JOB,SAL FROM EMP 2? WHERE job IN ('SALESMAN', 'PRESIDENT', 'ANALYST');
7 rows selected |
?
?????????對應(yīng)IN操作的還有NOT IN,用法一樣,結(jié)果相反。
?
2??BETWEEN…AND…
?
在WHERE子句中,可以使用BETWEEN操作符來查詢列值包含在指定區(qū)間內(nèi)的行。比如,查詢工資從1000到2000之間的員工??梢允褂脗鹘y(tǒng)方法:
????????
???????? WHERE SAL>=1000 AND SAL<=2000
????????
?????????也可以使用:
???????? ??? WHERE SAL BETWEEN 1000 AND 2000
?????????BWTWEEN操作所指定的范圍也包括邊界。
?
代碼演示:BETWEEN操作
| SQL> SELECT ename,job,sal FROM EMP WHERE sal BETWEEN 1000 AND 2000;
6 rows selected |
?
2??LIKE模糊查詢
?
在一些查詢時,可能把握不準(zhǔn)需要查詢的確切值,比如百度搜索時輸入關(guān)鍵字即可查詢出相關(guān)的結(jié)果,這種查詢稱為模糊查詢。模糊查詢使用LIKE關(guān)鍵字通過字符匹配檢索出所需要的數(shù)據(jù)行。字符匹配操作可以使用通配符“%”和“_”:
???%:表示零個或者多個任意字符。
???_:代表一個任意字符。
?
語法是:LIKE?'字符串'[ESCAPE?'字符']。匹配的字符串中,ESCAPE[D12]?后面的“字符”作為轉(zhuǎn)義字符。與一期SQLServer中ESCAPE用法相同。
?
| 通配符表達(dá)式 | 說明 |
| 'S%' | 以S開頭的字符串。 |
| '_S%' | 第二個字符時S的字符串。 |
| '%30\%%' escape '\' | 包含“30%”的字符串,“\”指轉(zhuǎn)義字符,“\%”在字符串中表示一個字符“%”。 |
表4? 通配符示例
?
案例5:顯示員工名稱以J開頭以S結(jié)尾的員工的姓名、工資和工資。
?
代碼演示:LIKE操作
| SQL> SELECT ENAME,JOB,SAL FROM EMP WHERE ENAME LIKE 'J%S'; ? ENAME??????JOB???????????? SAL ----------???--------- ???????--------- JONES??????MANAGER???? 2975.00 JAMES??????CLERK??????? ?950.00 |
?
2??集合運算
?
集合運算就是將兩個或者多個結(jié)果集組合成為一個結(jié)果集。集合運算包括:
???INTERSECT[D13]?(交集),返回兩個查詢共有的記錄。
???UNION ALL(并集),返回各個查詢的所有記錄,包括重復(fù)記錄。
???UNION(并集),返回各個查詢的所有記錄,不包括重復(fù)記錄。
???MINUS[D14]?(補(bǔ)集),返回第一個查詢檢索出的記錄減去第二個查詢檢索出的記錄之后剩余的記錄。
?
當(dāng)使用集合操作的時候,要注意:查詢所返回的列數(shù)以及列的類型必須匹配,列名可以不同。
????????
?????????案例6:查詢出dept表中哪個部門下沒有員工。只需求出dept表中的部門號和emp表中的部門號的補(bǔ)集即可。
?
代碼演示:求補(bǔ)運算
| SQL> SELECT DEPTNO FROM DEPT ??2? MINUS ??3? SELECT DEPTNO FROM EMP; DEPTNO ------ ????40 |
?
?????????前面學(xué)習(xí)過可以通過insert into …select把一個結(jié)果集插入到另一張結(jié)構(gòu)相同的表中,因此可以使用union把若干條記錄一次性插入到一張表中。
?
代碼演示:用union插入多條數(shù)據(jù)
| SQL> INSERT INTO DEPT ??2? SELECT 50,'公關(guān)部','臺灣' FROM DUAL ??3? UNION ??4? SELECT 60,'研發(fā)部','西安' FROM DUAL ??5? UNION ??6? SELECT 70,'培訓(xùn)部','西安' FROM DUAL ??7? / 3 rows inserted |
?
2??連接查詢
?
在SQL Server中已經(jīng)學(xué)習(xí)過內(nèi)聯(lián)接(inner join)、外聯(lián)接(outer join),外聯(lián)接又分為左外聯(lián)接(left outer join)和右外聯(lián)接(right outer join)。Oracle中對兩個表或者若干表之間的外聯(lián)接用(+)表示。
?
案例7:請查詢出工資大于2000元的,員工姓名,部門,工作,工資。
?
由于部門名稱在dept中,其他的信息在emp表中,需要內(nèi)聯(lián)接才能完成。
?
代碼演示:內(nèi)聯(lián)接
| SQL> SELECT e.ENAME,e.JOB,e.SAL,d.DNAME ??2? FROM emp e,dept d ??3? WHERE e.deptno=d.deptno ??4? AND e.SAL>2000;
6 rows selected |
?
?????????也可以使用SQL/92標(biāo)準(zhǔn)中的內(nèi)聯(lián)接:
?
代碼演示:內(nèi)聯(lián)接
| SELECT e.ENAME,e.JOB,e.SAL,d.DNAME ?FROM EMP e?INNER JOIN?DEPT d?ON?e.DEPTNO=d.DEPTNO WHERE e.SAL>2000????????????? |
?
這里INNER JOIN中,關(guān)鍵字INNER可以省略。
????????
案例8:請查詢出每個部門下的員工姓名,工資。
案例分析:
Emp表用外鍵deptno引用Dept表中的deptno,在Dept表中如果有某些部門沒有員工,那么用內(nèi)聯(lián)接,沒有員工的部門將無法顯示,因此必須以Dept表為基準(zhǔn)的外聯(lián)接。
?
代碼演示:外聯(lián)接
| SQL> SELECT e.ENAME,e.JOB,e.SAL,d.DNAME ??2? FROM EMP e ,DEPT d ??3? WHERE? e.DEPTNO(+)=d.DEPTNO??① ??4? /
? ?18 rows selected |
代碼解析:
①???(+):Oracle專用的聯(lián)接符,在條件中出現(xiàn)在左邊指右外聯(lián)接,出現(xiàn)在右邊指左外聯(lián)接。
?
?????????也可以使用SQL/92標(biāo)準(zhǔn)的寫法:
?
代碼演示:外聯(lián)接
| SELECT e.ENAME,e.JOB,e.SAL,d.DNAME FROM EMP e?RIGHT OUTER JOIN?DEPT d?ON?e.DEPTNO=d.DEPTNO |
?
?????????這里RIGHT OUTER JOIN中,關(guān)鍵字OUTER可以省略。
?
| ? | 雖然Oracle自身的聯(lián)接查詢語法比較好寫,同時容易理解,但是為了程序便于移植,推薦使用SQL/92表中的聯(lián)接查詢。同時也可以與SQL Server獲得一致。 |
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
7.???本章總結(jié)
???Oracle SQL語句中有數(shù)據(jù)操縱語言(DML)、數(shù)據(jù)定義語言(DDL)、數(shù)據(jù)控制語言(DCL)、事務(wù)控制語言(TCL)等等。
???DML語句包括增刪改查語句,DDL語句包括數(shù)據(jù)庫對象創(chuàng)建、修改和刪除語句,數(shù)據(jù)控制命令包括GRANT、REVOKE等,事務(wù)控制命令有COMMIT、ROLLBACK等。
???數(shù)據(jù)庫中建表常用的類型有:數(shù)字類型number(p,s),可變字符串varchar2(length),日期date。
???Oracle中default是一個值,在Oracle中不存在default約束。
???Oracle的增刪改語句與SQL Server基本一致,都是使用INSERT、UPDATE、DELETE完成。
???Oracle高級查詢中要注意:DISTINCT、NULL、IN、BETWEEN…AND…。
???集合操作有:UNION、UNION ALL、INTESECT、MINUS。
???聯(lián)接查詢有內(nèi)聯(lián)接和外聯(lián)接。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
8.???本章練習(xí)
1.???????創(chuàng)建一查詢,顯示與Blake在同一部門工作的雇員的項目和受雇日期,但是Blake不包含在內(nèi)。
2.???????顯示位置在Dallas的部門內(nèi)的雇員姓名、變化以及工作。
3.???????顯示被King直接管理的雇員的姓名以及工資。
4.???????創(chuàng)建一查詢,顯示能獲得與Scott一樣工資和獎金的其他雇員的姓名、受雇日期以及工資。
?
附表1:Scott表中的EMP表:員工表
| 序號 | 列名 | 類型 | 說明 |
| 1 | EMPNO | NUMBER(4) | 員工編號,EMP表主鍵 |
| 2 | ENAME | VARCHAR2(10) | 員工姓名 |
| 3 | JOB | VARCHAR2(9) | 員工工作 |
| 4 | MGR | NUMBER(4) | 員工的領(lǐng)導(dǎo)編號,引用EMPNO |
| 5 | HIREDATE | DATE | 入職日期 |
| 6 | SAL | NUMBER(7,2) | 員工工資 |
| 7 | COMM | NUMBER(7,2) | 員工獎金 |
| 8 | DEPTNO | NUMBER(2) | 員工部門編號,是表DEPT的外鍵。 |
?
附表2:Scott表中的DEPT表:部門表
| 序號 | 列名 | 類型 | 說明 |
| 1 | DEPTNO | NUMBER(2) | 部門編號,主鍵 |
| 2 | DNAME | VARCHAR2(14) | 部門名稱 |
| 3 | LOC | VARCHAR2(13) | 部門位置 |
?
附表3:Scott表中的SALGRADE表:工資等級表
| 序號 | 列名 | 類型 | 說明 |
| 1 | GRADE | NUMBER | 等級 |
| 2 | LOSAL | NUMBER | 此等級下最低工資 |
| 3 | HISAL | NUMBER | 此等級下最高工資 |
?
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
?
?
?
?
?
?
第3章
?
?
子查詢和常用函數(shù)
?
?
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? 子查詢 ü? 偽列 ü? 鎖的概念 |
?
?
?
?
?
?
1.???子查詢
子查詢在SELECT、UPDATE、DELETE語句內(nèi)部可以出現(xiàn)SELECT語句。內(nèi)部的SELECT語句結(jié)果可以作為外部語句中條件子句的一部分,也可以作為外部查詢的臨時表。子查詢的類型有:
1.???????單行子查詢:不向外部返回結(jié)果,或者只返回一行結(jié)果。
2.???????多行子查詢:向外部返回零行、一行或者多行結(jié)果。
?
案例1:查詢出銷售部(SALES)下面的員工姓名,工作,工資。
案例分析
該問題可以用聯(lián)接查詢實現(xiàn),由于所需的結(jié)果信息都在Emp表中,可以先從Dept表中查詢出銷售部對應(yīng)的部門號,然后根據(jù)當(dāng)前部門號再到Emp表中查詢出符合該部門的員工記錄即可。從銷售表中查詢出的結(jié)果可以作為Emp表中查詢的條件,SQL語句實現(xiàn)如下:
?
代碼演示:單行子查詢
| SQL> SELECT ENAME,JOB,SAL FROM EMP ? 2? WHERE DEPTNO=(SELECT DEPTNO FROM DEPT WHERE DNAME='SALES')?① ? 3? /
?6 rows selected |
代碼解析:
①??內(nèi)部查詢的結(jié)果作為外部查詢的條件。
?
需要注意:
???如果內(nèi)部查詢不返回任何記錄,則外部條件中字段DEPTNO與NULL比較永遠(yuǎn)為假,也就是說外部查詢不返還任何結(jié)果。
???在單行子查詢中外部查詢可以使用=、>、<、>=、<=、<>等比較運算符。
???內(nèi)部查詢返回的結(jié)果必須與外部查詢條件中的字段(DEPTNO)匹配。
???如果內(nèi)部查詢返回多行結(jié)果則出現(xiàn)錯誤。
?
案例2:查詢出Emp表中比任意一個銷售員(“SALESMAN”)工資低的員工姓名、工作、工資。
案例分析
銷售員在Emp表中有很多條記錄,每個人工資不相等,如果返回“比任意員工的工資還低”的條件,返回比“最高工資還低”即可。如果用子查詢做,子查詢中就會返回多條記錄。用普通的關(guān)系符(>、<等)運行就會出錯。這時候需要用關(guān)鍵字ANY。ANY放在比較運算符后面,表示“任意”的意思。
?
代碼演示:ANY子查詢
| SQL> SELECT ENAME,JOB,SAL FROM EMP ? 2? WHERE SAL<ANY (SELECT SAL FROM EMP WHERE JOB='SALESMAN')??① ? 3? /
?7 rows selected |
代碼解析:
①??<any:比子查詢結(jié)果中任意的值都小,也就是說,比子查詢結(jié)果中最大值還小,那么同理>any表示比子查詢結(jié)果中最小的還大。
?
案例3:查詢出比所有銷售員的工資都高的員工姓名,工作,工資。
?
案例分析
ANY可以表示任意的,但本案例中要求比所有銷售員工資都高,那么就要使用另外一個關(guān)鍵字ALL。ALL與關(guān)系操作符一起使用,表示與子查詢中所有元素比較。
?
代碼演示:ALL子查詢
| SQL> SELECT ENAME,JOB,SAL FROM EMP ? 2? WHERE SAL>ALL (SELECT SAL FROM EMP WHERE JOB='SALESMAN')??① ? 3? /
6 rows selected |
代碼解析:
①??>ALL:比子查詢結(jié)果中所有值還要大,也就是說,比子查詢結(jié)果中最大值還要大。<ALL表示比最小值還要小。
?
對于子查詢還可以使用IN和NOT IN操作符進(jìn)行操作。
?
2.???Oracle中的偽列
在Oracle的表的使用過程中,實際表中還有一些附加的列,稱為偽列。偽列就像表中的列一樣,但是在表中并不存儲。偽列只能查詢,不能進(jìn)行增刪改操作。接下來學(xué)習(xí)兩個偽列:ROWID和ROWNUM。
?
2??ROWID
?
表中的每一行在數(shù)據(jù)文件中都有一個物理地址,ROWID偽列返回的就是該行的物理地址。使用ROWID可以快速的定位表中的某一行。ROWID值可以唯一的標(biāo)識表中的一行。由于ROWID返回的是該行的物理地址,因此使用ROWID可以顯示行是如何存儲的。
?
代碼演示:ROWID
| SQL> SELECT ROWID,ENAME FROM EMP WHERE SAL>2000;
6 rows selected |
?
2??ROWNUM
?
在查詢的結(jié)果集中,ROWNUM為結(jié)果集中每一行標(biāo)識一個行號,第一行返回1,第二行返回2,以此類推。通過ROWNUM偽列可以限制查詢結(jié)果集中返回的行數(shù)。
?
| ? | ROWNUM與ROWID不同,ROWID是插入記錄時生成,ROWNUM是查詢數(shù)據(jù)時生成。ROWID標(biāo)識的是行的物理地址。ROWNUM標(biāo)識的是查詢結(jié)果中的行的次序。 |
?
案例4:查詢出員工表中前5名員工的姓名,工作,工資。
?
代碼演示:ROWNUM
| SQL> SELECT ROWNUM,ENAME,JOB,SAL FROM EMP WHERE ROWNUM<=5;
|
?
案例5:查詢出工資最高的前5名員工的姓名、工資和工資。
案例分析
“工資最高的前5名”需要先降序排序,再取前5名,但是生成ROWNUM操作比排序要早,排序時已經(jīng)連同ROWNUM一起排序了,因此不能直接在案例1的語句中直接加上Order by就行,而是需要對排序的結(jié)果重新做二次查詢,產(chǎn)生新的ROWNUM才能作為查詢的條件依據(jù)。
?
代碼演示:ROWNUM應(yīng)用
| SQL> SELECT ROWNUM,T.* FROM??① ??2????? (SELECT ENAME,JOB,SAL ??3?????? FROM EMP ORDER BY SAL DESC) T??② ??4? WHERE ROWNUM<=5 ??5? / ?
|
代碼解析:
①??T是子查詢②的別名,這里的ROWNUM是第二次查詢后的ROWNUM。
?
案例6:查詢出表EMP中第5條到第10條之間的記錄。
案例分析
這是分頁的應(yīng)用。在查詢條件中,如果查詢條件中ROWNUM大于某一正整數(shù),則不返還任何結(jié)果。
?
代碼演示:ROWNUM分頁
| SQL> SELECT * FROM ??2???? (SELECT ROWNUM R,ENAME,JOB,SAL??① ??3????? FROM EMP WHERE ROWNUM<=10)??② ??4? WHERE R>5??③ ??5? /
|
代碼解析:
①??內(nèi)部查詢中得到ROWNUM?并且用別名R記錄,供外層條件③使用。
②??內(nèi)部查詢的ROWNUM,與外出的ROWNUM列是平等的兩列。
③??使用的R是內(nèi)層產(chǎn)生的ROWNUM,在外層看來,內(nèi)層查詢的ROWNUM是正常的一列。
?
3.???Oracle函數(shù)
Oracle SQL提供了用于執(zhí)行特定操作的專用函數(shù)。這些函數(shù)大大增強(qiáng)了SQL語言的功能。函數(shù)可以接受零個或者多個輸入?yún)?shù),并返回一個輸出結(jié)果。Oracle數(shù)據(jù)庫中主要使用兩種類型的函數(shù):
1.?????????單行函數(shù):對每一個函數(shù)應(yīng)用在表的記錄中時,只能輸入一行結(jié)果,返回一個結(jié)果,比如:MOD(x,y)返回x除以y的余數(shù)(x和y可以是兩個整數(shù),也可以是表中的整數(shù)列)。常用的單行函數(shù)有:
???字符函數(shù):對字符串操作。
???數(shù)字函數(shù):對數(shù)字進(jìn)行計算,返回一個數(shù)字。
???轉(zhuǎn)換函數(shù):可以將一種數(shù)據(jù)類型轉(zhuǎn)換為另外一種數(shù)據(jù)類型。
???日期函數(shù):對日期和時間進(jìn)行處理。
2.?????????聚合函數(shù):聚合函數(shù)同時可以對多行數(shù)據(jù)進(jìn)行操作,并返回一個結(jié)果。比如SUM(x)返回結(jié)果集中x列的總合。
????????
2??字符函數(shù)
?
字符函數(shù)接受字符參數(shù),這些參數(shù)可以是表中的列,也可以是一個字符串表達(dá)式。下表列出了常用的字符函數(shù)。
?
| 函數(shù) | 說明 |
| ASCII(x) | 返回字符x的ASCII碼。 |
| CONCAT(x,y) | 連接字符串x和y。 |
| INSTR(x, str [,start] [,n) | 在x中查找str,可以指定從start開始,也可以指定從第n次開始。 |
| LENGTH(x) | 返回x的長度。 |
| LOWER(x) | x轉(zhuǎn)換為小寫。 |
| UPPER(x) | x轉(zhuǎn)換為大寫。 |
| LTRIM(x[,trim_str]) | 把x的左邊截去trim_str字符串,缺省截去空格。 |
| RTRIM(x[,trim_str]) | 把x的右邊截去trim_str字符串,缺省截去空格。 |
| TRIM([trim_str FROM] x) | 把x的兩邊截去trim_str字符串,缺省截去空格。 |
| REPLACE(x,old,new) | 在x中查找old,并替換為new。 |
| SUBSTR(x,start[,length]) | 返回x的字串,從staart處開始,截取length個字符,缺省length,默認(rèn)到結(jié)尾。 |
表1? 字符函數(shù)
?
| 示例 | 示例結(jié)果 |
| SELECT ASCII('a') FROM DUAL | 97 |
| SELECT CONCAT('Hello', ' world') FROM DUAL | Hello world |
| SELECT INSTR('Hello world','or') FROM DUAL | 8 |
| SELECT LENGTH('Hello') FROM DUAL | 5 |
| SELECT LOWER('hElLO') FROM DUAL; | hello |
| SELECT UPPER('hello') FROM DUAL | HELLO |
| SELECT LTRIM('===HELLO===', '=') FROM DUAL | HELLO=== |
| SELECT '=='||LTRIM('?? HELLO===') FROM DUAL | ==HELLO=== |
| SELECT RTRIM('===HELLO===', '=') FROM DUAL | ===HELLO |
| SELECT '='||TRIM('?? HELLO?? ')||'=' FROM DUAL | =HELLO= |
| SELECT TRIM('=' FROM '===HELLO===') FROM DUAL | HELLO |
| SELECT REPLACE('ABCDE','CD','AAA') FROM DUAL | ABAAAE |
| SELECT SUBSTR('ABCDE',2) FROM DUAL | BCDE |
| SELECT SUBSTR('ABCDE',2,3) FROM DUAL | BCD |
表2? 字符函數(shù)示例
?
2??數(shù)字函數(shù)
?
數(shù)字函數(shù)接受數(shù)字參數(shù),參數(shù)可以來自表中的一列,也可以是一個數(shù)字表達(dá)式。
?
| 函數(shù) | 說明 | 示例 |
| ABS(x) | x絕對值 | ABS(-3)=3 |
| ACOS(x) | x的反余弦 | ACOS(1)=0 |
| COS(x) | 余弦 | COS(1)=1.57079633 |
| CEIL(x) | 大于或等于x的最小值 | CEIL(5.4)=6 |
| FLOOR(x) | 小于或等于x的最大值 | FLOOR(5.8)=5 |
| LOG(x,y) | x為底y的對數(shù) | LOG(2,4)=2 |
| MOD(x,y) | x除以y的余數(shù) | MOD(8,3)=2 |
| POWER(x,y) | x的y次冪 | POWER(2,3)=8 |
| ROUND(x[,y]) | x在第y位四舍五入 | ROUND(3.456,2)=3.46 |
| SQRT(x) | x的平方根 | SQRT(4)=2 |
| TRUNC(x[,y]) | x在第y位截斷 | TRUNC(3.456,2)=3.45 |
表3? 數(shù)字函數(shù)
?
說明:
1.???????ROUND(X[,Y]),四舍五入。
在缺省y時,默認(rèn)y=0;比如:ROUND(3.56)=4。
y是正整數(shù),就是四舍五入到小數(shù)點后y位。ROUND(5.654,2)=5.65。
y是負(fù)整數(shù),四舍五入到小數(shù)點左邊|y|位。ROUND(351.654,-2)=400。
?
2.????????TRUNC(x[,y]),直接截取,不四舍五入。
在缺省y時,默認(rèn)y=0;比如:TRUNC (3.56)=3。
y是正整數(shù),就是四舍五入到小數(shù)點后y位。TRUNC (5.654,2)=5.65。
y是負(fù)整數(shù),四舍五入到小數(shù)點左邊|y|位。TRUNC (351.654,-2)=300。
?
2??日期函數(shù)
?
日期函數(shù)對日期進(jìn)行運算。常用的日期函數(shù)有:
1.?????????ADD_MONTHS(d,n),在某一個日期d上,加上指定的月數(shù)n,返回計算后的新日期。d表示日期,n表示要加的月數(shù)。
?
?
圖1??ADD_MONTHS函數(shù)示例
?
2.?????????LAST_DAY(d),返回指定日期當(dāng)月的最后一天。
?
?
圖2??LAST_DAY函數(shù)示例
?
3.?????????ROUND(d[,fmt]),返回一個以fmt為格式的四舍五入日期值,d是日期,fmt是格式模型。默認(rèn)fmt為DDD,即月中的某一天。
???如果fmt為“YEAR”則舍入到某年的1月1日,即前半年舍去,后半年作為下一年。
???如果fmt為“MONTH”則舍入到某月的1日,即前月舍去,后半月作為下一月。
???默認(rèn)為“DDD”,即月中的某一天,最靠近的天,前半天舍去,后半天作為第二天。
???如果fmt為“DAY”則舍入到最近的周的周日,即上半周舍去,下半周作為下一周周日。
?
?
圖3? ROUND函數(shù)示例
????????
與ROUND對應(yīng)的函數(shù)時TRUNC(d[,fmt])對日期的操作,TRUNC與ROUND非常相似,只是不對日期進(jìn)行舍入,直接截取到對應(yīng)格式的第一天。
?
4.?????????EXTRACT(fmt FROM d),提取日期中的特定部分。
?
fmt為:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND。其中YEAR、MONTH、DAY可以為DATE類型匹配,也可以與TIMESTAMP類型匹配;但是HOUR、MINUTE、SECOND必須與TIMESTAMP類型匹配。
?
HOUR匹配的結(jié)果中沒有加上時區(qū),因此在中國運行的結(jié)果小8小時。
?
圖4??EXTRACT函數(shù)示例
?
2??轉(zhuǎn)換函數(shù)
?
轉(zhuǎn)換函數(shù)將值從一種數(shù)據(jù)類型轉(zhuǎn)換為另外一種數(shù)據(jù)類型。常用的轉(zhuǎn)換函數(shù)有:
?
1.?????????TO_CHAR(d|n[,fmt])
?
把日期和數(shù)字轉(zhuǎn)換為制定格式的字符串。fmt是格式化字符串,日期的格式化字符串前面已經(jīng)學(xué)習(xí)過。
?
代碼演示:TO_CHAR對日期的處理
| SQL> SELECT TO_CHAR(SYSDATE,'YYYY"年"MM"月"DD"日" HH24:MI:SS') "date"? ① ? 2? FROM DUAL; ? date ----------------------- 2009年08月11日 12:06:00 |
代碼解析:
①??在格式化字符串中,使用雙引號對非格式化字符進(jìn)行引用。
?
針對數(shù)字的格式化,格式化字符有:
?
| 參數(shù) | 示例 | 說明 |
| 9 | 999 | 指定位置處顯示數(shù)字。 |
| . | 9.9 | 指定位置返回小數(shù)點 |
| , | 99,99 | 指定位置返回一個逗號 |
| $ | $999 | 數(shù)字開頭返回一個美元符號 |
| EEEE | 9.99EEEE | 科學(xué)計數(shù)法表示 |
| L | L999 | 數(shù)字前加一個本地貨幣符號 |
| PR | 999PR | 如果數(shù)字式負(fù)數(shù)則用尖括號進(jìn)行表示 |
表4? 數(shù)字格式化字符
?
代碼演示:TO_CHAR對數(shù)字的處理
| SQL> SELECT TO_CHAR(-123123.45,'L9.9EEEEPR') "date" ? 2? FROM DUAL ? 3? / date -------------------- ?<¥1.2E+05> |
?
2.?????????TO_DATE(x [,fmt])
把一個字符串以fmt格式轉(zhuǎn)換為一個日期類型,前面已經(jīng)學(xué)習(xí)過。
????????
3.?????????TO_NUMBER(x[,fmt])
把一個字符串以fmt格式轉(zhuǎn)換為一個數(shù)字。fmt格式字符參考表3。
?
代碼演示:TO_NUM函數(shù)
| SQL> SELECT TO_NUMBER('-$12,345.67','$99,999.99') "NUM" ? 2? FROM DUAL ? 3? / ? ???NUM --------------- ?-12345.67 |
?
2??其他單行函數(shù)
?
1.?????????NVL(x,value)
如果x為空,返回value,否則返回x。
????????
?????????案例7:對工資是2000元以下的員工,如果沒有發(fā)獎金,每人獎金100元。
?
代碼演示:NVL函數(shù)
| SQL> SELECT ENAME,JOB,SAL,NVL(COMM,100) FROM EMP WHERE SAL<2000;
? 7 rows selected |
?
2.?????????NVL2(x,value1,value2)
如果x非空,返回value1,否則返回value2。
?
案例8:對EMP表中工資為2000元以下的員工,如果沒有獎金,則獎金為200元,如果有獎金,則在原來的獎金基礎(chǔ)上加100元。
?
代碼演示:NVL2函數(shù)
| SQL> SELECT ENAME,JOB,SAL,NVL2(COMM,comm+100,200) "comm" ? 2? FROM EMP WHERE SAL<2000;
8 rows selected |
?
2??聚合函數(shù)
?
聚合函數(shù)同時對一組數(shù)據(jù)進(jìn)行操作,返回一行結(jié)果,比如計算一組數(shù)據(jù)的總和,平均值等。
?
| 名稱 | 作用 | 語法 |
| AVG | 平均值 | AVG(表達(dá)式) |
| SUM | 求和 | SUM(表達(dá)式) |
| MIN、MAX | 最小值、最大值 | MIN(表達(dá)式)、MAX(表達(dá)式) |
| COUNT | 數(shù)據(jù)統(tǒng)計 | COUNT(表達(dá)式) |
表 5? 聚合函數(shù)
?
案例9:求本月所有員工的基本工資總和。
?
代碼演示:SUM函數(shù)
| SQL> select sum(sal) from emp; ? SUM(SAL) ---------------- ? ???29025 |
?
案例10:求不同部門的平均工資。
?
代碼演示:AVG函數(shù)下的分組查詢
| SQL> SELECT DEPTNO,AVG(SAL) FROM EMP GROUP BY DEPTNO; ? DEPTNO?? AVG(SAL) --------- ?????---------- ??? 30 ???1566.66666 ??? 20??? 2175 ??? 10 ???2916.66666 |
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
4.???本章總結(jié)
???Oracle常用函數(shù)有字符相關(guān)的函數(shù)、數(shù)字相關(guān)的函數(shù)、日期相關(guān)的函數(shù)、轉(zhuǎn)換函數(shù)等。
???EXTRACT函數(shù)能夠獲取日期中的某個字段的值。
???TO_CHAR函數(shù)能夠把數(shù)字和日期轉(zhuǎn)換成固定的字符串格式。TO_DATE?????????函數(shù)能夠把固定格式的字符串轉(zhuǎn)換為日期類型。
???子查詢中有返回單行的子查詢和返回多行的子查詢。
???Oracle中存在ROWID、ROWNUM等偽列。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
5.???本章練習(xí)
1.???????描述TO_CHAR和TO_DATE函數(shù)的用法。
2.???????描述EXTRACT函數(shù)的用法。
3.???????你知道有哪些關(guān)于日期函數(shù)的用法?
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
第4章
?
?
表空間、數(shù)據(jù)庫對象
?
?
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? 同義詞概念 ü? 序列的應(yīng)用 ü? 視圖的概念 ü? 索引的概念 ü? 表空間的概念 |
?
?
?
?
1.???Oracle數(shù)據(jù)庫對象
數(shù)據(jù)庫對象是數(shù)據(jù)庫的組成部分,常常用CREATE命令進(jìn)行創(chuàng)建,可以使用ALTER命令修改,用DROP執(zhí)行刪除操作。前面已經(jīng)接觸過的數(shù)據(jù)庫對象有表、用戶等。
?
今天將學(xué)習(xí)更多的Oracle數(shù)據(jù)庫對象:
???同義詞:就是給數(shù)據(jù)庫對象一個別名。
???序列:Oracle中實現(xiàn)增長的對象。
???視圖:預(yù)定義的查詢,作為表一樣的查詢使用,是一張?zhí)摂M表。
???索引:對數(shù)據(jù)庫表中的某些列進(jìn)行排序,便于提高查詢效率。
?
2.???同義詞
同義詞(Synonym)是數(shù)據(jù)庫對象的一個別名,Oracle可以為表、視圖、序列、過程、函數(shù)、程序包等指定一個別名。同義詞有兩種類型:
???私有同義詞:擁有CREATE SYNONYM權(quán)限的用戶(包括非管理員用戶)即可創(chuàng)建私有同義詞,創(chuàng)建的私有同義詞只能由當(dāng)前用戶使用。
???公有同義詞:系統(tǒng)管理員可以創(chuàng)建公有同義詞,公有同義詞可以被所有用戶訪問。
?
?????????創(chuàng)建同義詞的語法是:
?
語法結(jié)構(gòu):同義詞
| CREATE [OR REPLACE] [PUBLIC] SYSNONYM [schema.]synonym_name FOR [schema.]object_name |
語法解析:
①??CREATE [OR REPLACE:]表示在創(chuàng)建同義詞時,如果該同義詞已經(jīng)存在,那么就用新創(chuàng)建的同義詞代替舊同義詞。
②??PULBIC:創(chuàng)建公有同義詞時使用的關(guān)鍵字,一般情況下不需要創(chuàng)建公有同義詞。
③??Oracle中一個用戶可以創(chuàng)建表、視圖等多種數(shù)據(jù)庫對象,一個用戶和該用戶下的所有數(shù)據(jù)庫對象的集合稱為Schema(中文稱為模式或者方案),用戶名就是Schema名。一個數(shù)據(jù)庫對象的全稱是:用戶名.對象名,即schema.object_name。
?
如果一個用戶有權(quán)限訪問其他用戶對象時,就可以使用全稱來訪問。比如:
?
代碼演示:System用戶訪問Scott用戶的Emp表
| SQL> conn system/manager@orcl; Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 Connected as system ? SQL>? SELECT ENAME,JOB,SAL FROM SCOTT.EMP WHERE SAL>2000;? ①
?6 rows selected |
代碼解析:
①??管理員用戶可以訪問任何用戶的數(shù)據(jù)庫對象,SYSTEM用戶訪問SCOTT用戶的EMP表時,必須使用SCOTT.EMP。
?
案例1:創(chuàng)建一個用戶XiaoMei,該用戶擁有CONNECT角色和RESOURCE角色。為SCOTT用戶的EMP表創(chuàng)建同義詞,并通過同義詞訪問該EMP表。
?
代碼演示:創(chuàng)建同義詞并訪問
| SQL> CONN system/manager@orcl; Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 Connected as system SQL> CREATE USER XiaoMei IDENTIFIED BY XiaoMei; ?① User created SQL> GRANT CONNECT TO XiaoMei; Grant succeeded SQL> GRANT RESOURCE TO XiaoMei; Grant succeeded SQL> GRANT CREATE SYNONYM TO XiaoMei; Grant succeeded ? SQL> CONN XiaoMei/XiaoMei@ORCL; Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 Connected as XiaoMei ? SQL> CREATE SYNONYM MyEmp FOR SCOTT.EMP; ?② Synonym created SQL> SELECT * FROM MYEMP; ?③ SELECT * FROM MYEMP ORA-00942: 表或視圖不存在 ? SQL> CONNECT SCOTT/tiger@ORCL Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 Connected as SCOTT ? SQL> GRANT ALL ON EMP TO XiaoMei; ?④ Grant succeeded ? SQL> CONNECT XiaoMei/XiaoMei@ORCL; Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 Connected as XiaoMei ? SQL>? SELECT ENAME,JOB,SAL FROM MyEmp WHERE SAL>2000;? ⑤
?6 rows selected |
代碼解析:
①??在管理員用戶下創(chuàng)建用戶XiaoMei,對用戶XiaoMei授予CONNECT和RESOURCE角色。為了XiaoMei能夠創(chuàng)建序列,必須授予系統(tǒng)權(quán)限:CREATE SYNONYM。
②??在XiaoMei用戶下,為SCOTT.EMP創(chuàng)建私有同義詞MyEmp,同義詞MyEmp只能在XiaoMei用戶下使用。訪問MyEmp就是訪問SCOTT.EMP對象。
③??訪問MyEmp對象出錯:對象不存在。因為XiaoMei如果訪問MyEmp,就相當(dāng)于訪問SCOTT.EMP對象,那么SCOTT用戶必須對XiaoMei授予相應(yīng)的權(quán)限。
④??SCOTT用戶下,把EMP表的所有權(quán)限(增刪改查)授予XiaoMei。
⑤??對MyEmp執(zhí)行查詢操作。MyEmp就可以像在本地的表一樣使用。
?
刪除同義詞使用的語法是:
?
語法結(jié)構(gòu):刪除同義詞
| DROP [PUBLIC] SYNONYM [schema.]sysnonym_name |
語法解析:
①??PUBLIC:刪除公共同義詞。
②??同義詞的刪除只能被擁有同義詞對象的用戶或者管理員刪除。
③??此命令只能刪除同義詞,不能刪除同義詞下的源對象。
?
3.???序列
序列(Sequence)是用來生成連續(xù)的整數(shù)數(shù)據(jù)的對象。序列常常用來作為主鍵中增長列,序列中的可以升序生成,也可以降序生成。創(chuàng)建序列的語法是:
?
語法結(jié)構(gòu):創(chuàng)建序列
| CREATE SEQUENCE sequence_name [START WITH num] [INCREMENT BY increment] [MAXVALUE num|NOMAXVALUE] [MINVALUE num|NOMINVALUE] [CYCLE|NOCYCLE] [CACHE num|NOCACHE] |
語法解析:
①??START WITH:從某一個整數(shù)開始,升序默認(rèn)值是1,降序默認(rèn)值是-1。
②??INCREMENT BY:增長數(shù)。如果是正數(shù)則升序生成,如果是負(fù)數(shù)則降序生成。升序默認(rèn)值是1,降序默認(rèn)值是-1。
③??MAXVALUE:指最大值。
④??NOMAXVALUE:這是最大值的默認(rèn)選項,升序的最大值是:1027,降序默認(rèn)值是-1。
⑤??MINVALUE:指最小值。
⑥??NOMINVALUE:這是默認(rèn)值選項,升序默認(rèn)值是1,降序默認(rèn)值是-1026。
⑦??CYCLE:表示如果升序達(dá)到最大值后,從最小值重新開始;如果是降序序列,達(dá)到最小值后,從最大值重新開始。
⑧??NOCYCLE:表示不重新開始,序列升序達(dá)到最大值、降序達(dá)到最小值后就報錯。默認(rèn)NOCYCLE。
⑨??CACHE:使用CACHE選項時,該序列會根據(jù)序列規(guī)則預(yù)生成一組序列號。保留在內(nèi)存中,當(dāng)使用下一個序列號時,可以更快的響應(yīng)。當(dāng)內(nèi)存中的序列號用完時,系統(tǒng)再生成一組新的序列號,并保存在緩存中,這樣可以提高生成序列號的效率。Oracle默認(rèn)會生產(chǎn)20個序列號。
⑩??NOCACHE:不預(yù)先在內(nèi)存中生成序列號。
?
案例2:創(chuàng)建一個從1開始,默認(rèn)最大值,每次增長1的序列,要求NOCYCLE,緩存中有30個預(yù)先分配好的序列號。
?
代碼演示:生成序列號
| SQL> CREATE SEQUENCE MYSEQ ? 2? MINVALUE 1 ? 3? START WITH 1 ? 4? NOMAXVALUE ? 5? INCREMENT BY 1 ? 6? NOCYCLE ? 7? CACHE 30 ? 8? / ? Sequence created |
?
序列創(chuàng)建之后,可以通過序列對象的CURRVAL和NEXTVAL兩個“偽列”分別訪問該序列的當(dāng)前值和下一個值。
?
代碼演示:序列使用
| SQL> SELECT MYSEQ.NEXTVAL FROM DUAL; NEXTVAL ---------- ?? 1 SQL> SELECT MYSEQ.NEXTVAL FROM DUAL; NEXTVAL ---------- 2 SQL> SELECT MYSEQ.CURRVAL FROM DUAL; CURRVAL ---------- ?? 2 |
?
?????????使用ALTER SEQUENCE可以修改序列,在修改序列時有如下限制:
1.???????不能修改序列的初始值。
2.???????最小值不能大于當(dāng)前值。
3.???????最大值不能小于當(dāng)前值。
?
使用DROP SEQUENCE命令可以刪除一個序列對象。
?
代碼演示:序列修改和刪除
| SQL> ALTER SEQUENCE MYSEQ ? 2? MAXVALUE 10000 ? 3? MINVALUE -300 ? 4? / SEQUENCE ALTERED SQL> DROP SEQUENCE MYSEQ; SEQUENCE DROPPED |
?
4.???視圖
視圖(View)實際上是一張或者多張表上的預(yù)定義查詢,這些表稱為基表。從視圖中查詢信息與從表中查詢信息的方法完全相同。只需要簡單的SELECT…FROM即可。
?
視圖具有以下優(yōu)點:
1.???????可以限制用戶只能通過視圖檢索數(shù)據(jù)。這樣就可以對最終用戶屏蔽建表時底層的基表。
2.???????可以將復(fù)雜的查詢保存為視圖。可以對最終用戶屏蔽一定的復(fù)雜性。
3.???????限制某個視圖只能訪問基表中的部分列或者部分行的特定數(shù)據(jù)。這樣可以實現(xiàn)一定的安全性。
4.???????從多張基表中按一定的業(yè)務(wù)邏輯抽出用戶關(guān)心的部分,形成一張?zhí)摂M表。
?
語法結(jié)構(gòu):創(chuàng)建視圖
| CREATE [OR REPLACE] [{FORCE|NOFORCE}] VIEW view_name AS SELECT查詢 [WITH READ ONLY CONSTRAINT] |
語法解析:
1.???????OR REPLACE:如果視圖已經(jīng)存在,則替換舊視圖。
2.???????FORCE:即使基表不存在,也可以創(chuàng)建該視圖,但是該視圖不能正常使用,當(dāng)基表創(chuàng)建成功后,視圖才能正常使用。
3.???????NOFORCE:如果基表不存在,無法創(chuàng)建視圖,該項是默認(rèn)選項。
4.???????WITH READ ONLY:默認(rèn)可以通過視圖對基表執(zhí)行增刪改操作,但是有很多在基表上的限制(比如:基表中某列不能為空,但是該列沒有出現(xiàn)在視圖中,則不能通過視圖執(zhí)行insert操作),WITH READ ONLY說明視圖是只讀視圖,不能通過該視圖進(jìn)行增刪改操作?,F(xiàn)實開發(fā)中,基本上不通過視圖對表中的數(shù)據(jù)進(jìn)行增刪改操作。
?
案例3:基于EMP表和DEPT表創(chuàng)建視圖
?
代碼演示:視圖
| SQL> CREATE OR REPLACE VIEW EMPDETAIL ? 2? AS ? 3? SELECT EMPNO,ENAME,JOB,HIREDATE,EMP.DEPTNO,DNAME ? 4? FROM EMP JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO ? 5? WITH READ ONLY ? 6? / ? VIEW CREATED ? SQL> SELECT * FROM EMPDETAIL;? ①
14 ROWS SELECTED |
代碼解析:
①???對視圖可以像表一樣進(jìn)行查詢。該視圖中隱藏了員工的工資。
?
刪除視圖可以使用“DROP VIEW?視圖名稱”,刪除視圖不會影響基表的數(shù)據(jù)。
?
5.???索引
當(dāng)我們在某本書中查找特定的章節(jié)內(nèi)容時,可以先從書的目錄著手,找到該章節(jié)所在的頁碼,然后快速的定位到該頁。這種做法的前提是頁面編號是有序的。如果頁碼無序,就只能從第一頁開始,一頁頁的查找了。
?
數(shù)據(jù)庫中索引(Index)的概念與目錄的概念非常類似。如果某列出現(xiàn)在查詢的條件中,而該列的數(shù)據(jù)是無序的,查詢時只能從第一行開始一行一行的匹配。創(chuàng)建索引就是對某些特定列中的數(shù)據(jù)排序,生成獨立的索引表。在某列上創(chuàng)建索引后,如果該列出現(xiàn)在查詢條件中,Oracle會自動的引用該索引,先從索引表中查詢出符合條件記錄的ROWID,由于ROWID是記錄的物理地址,因此可以根據(jù)ROWID快速的定位到具體的記錄,表中的數(shù)據(jù)非常多時,引用索引帶來的查詢效率非常可觀。
?
| ? | 2??如果表中的某些字段經(jīng)常被查詢并作為查詢的條件出現(xiàn)時,就應(yīng)該考慮為該列創(chuàng)建索引。 2??當(dāng)從很多行的表中查詢少數(shù)行時,也要考慮創(chuàng)建索引。有一條基本的準(zhǔn)則是:當(dāng)任何單個查詢要檢索的行少于或者等于整個表行數(shù)的10%時,索引就非常有用。 |
?
Oracle數(shù)據(jù)庫會為表的主鍵和包含唯一約束的列自動創(chuàng)建索引。索引可以提高查詢的效率,但是在數(shù)據(jù)增刪改時需要更新索引,因此索引對增刪改時會有負(fù)面影響。
?
語法結(jié)構(gòu):創(chuàng)建索引
| CREATE [UNIQUE] INDEX index_name ON table_name(column_name[,column_name…]) |
語法解析:
1.???????UNIQUE:指定索引列上的值必須是唯一的。稱為唯一索引。
2.???????index_name:指定索引名。
3.???????tabl_name:指定要為哪個表創(chuàng)建索引。
4.???????column_name:指定要對哪個列創(chuàng)建索引。我們也可以對多列創(chuàng)建索引;這種索引稱為組合索引。
?
案例4:為EMP表的ENAME列創(chuàng)建創(chuàng)建唯一索引,為EMP表的工資列創(chuàng)建普通索引,把JOB列先變?yōu)樾懺賱?chuàng)建索引。
?
代碼演示:創(chuàng)建索引
| SQL> CREATE UNIQUE INDEX UQ_ENAME_IDX ON EMP(ENAME); ?① Index created SQL> CREATE INDEX IDX_SAL ON EMP(SAL); ?② Index created SQL> CREATE INDEX IDX_JOB_LOWER ON EMP(LOWER(JOB));? ③ Index created |
代碼解析:
①??為SCOTT.EMP表的ENAME列創(chuàng)建唯一索引。
②??為SCOTT.EMP表的SAL列創(chuàng)建索引。
③??在查詢中可能經(jīng)常使用job的小寫作為條件的表達(dá)式,因此創(chuàng)建索引時,可以先對JOB列中的所有值轉(zhuǎn)換為小寫后創(chuàng)建索引,而這時需要使用lower函數(shù),這種索引稱為基于函數(shù)的索引。
?
在select語句查詢時,Oracle系統(tǒng)會自動為查詢條件上的列應(yīng)用索引。索引就是對某一列進(jìn)行排序,因此在索引列上,重復(fù)值越少,索引的效果越明顯。
Oracle可以為一些列值重復(fù)非常多且值有限的列(比如性別列)上創(chuàng)建位圖索引。關(guān)于Oracle更多的索引類型(比如反向鍵索引等),請參考Oracle官方文檔。
?
6.???表空間
在數(shù)據(jù)庫系統(tǒng)中,存儲空間是較為重要的資源,合理利用空間,不但能節(jié)省空間,還可以提高系統(tǒng)的效率和工作性能。Oracle可以存放海量數(shù)據(jù),所有數(shù)據(jù)都在數(shù)據(jù)文件中存儲。而數(shù)據(jù)文件大小受操作系統(tǒng)限制,并且過大的數(shù)據(jù)文件對數(shù)據(jù)的存取性能影響非常大。同時Oracle是跨平臺的數(shù)據(jù)庫,Oracle數(shù)據(jù)可以輕松的在不同平臺上移植,那么如何才能提供統(tǒng)一存取格式的大容量呢?Oracle采用表空間來解決。
?
表空間只是一個邏輯概念,若干操作系統(tǒng)文件(文件可以不是很大)可以組成一個表空間。表空間統(tǒng)一管理空間中的數(shù)據(jù)文件,一個數(shù)據(jù)文件只能屬于一個表空間。一個數(shù)據(jù)庫空間由若干個表空間組成。如圖所示:
?
?
圖1? 數(shù)據(jù)空間、表空間和數(shù)據(jù)文件
?
???????? Oracle中所有的數(shù)據(jù)(包括系統(tǒng)數(shù)據(jù)),全部保存在表空間中,常見的表空間有:
???系統(tǒng)表空間:存放系統(tǒng)數(shù)據(jù),系統(tǒng)表空間在數(shù)據(jù)庫創(chuàng)建時創(chuàng)建。表空間名稱為SYSTEM。存放數(shù)據(jù)字典和視圖以及數(shù)據(jù)庫結(jié)構(gòu)等重要系統(tǒng)數(shù)據(jù)信息,在運行時如果SYSTEM空間不足,對數(shù)據(jù)庫影響會比較大,雖然在系統(tǒng)運行過程中可以通過命令擴(kuò)充空間,但還是會影響數(shù)據(jù)庫的性能,因此有必要在創(chuàng)建數(shù)據(jù)庫時適當(dāng)?shù)陌褦?shù)據(jù)文件設(shè)置大一些。
???TMEP表空間:臨時表空間,安裝數(shù)據(jù)庫時創(chuàng)建,可以在運行時通過命令增大臨時表空間。臨時表空間的重要作用是數(shù)據(jù)排序。比如當(dāng)用戶執(zhí)行了諸如Order by等命令后,服務(wù)器需要對所選取數(shù)據(jù)進(jìn)行排序,如果數(shù)據(jù)很大,內(nèi)存的排序區(qū)可能裝不下太大數(shù)據(jù),就需要把一些中間的排序結(jié)果寫在硬盤的臨時表空間中。
???用戶表自定義空間:用戶可以通過CREATE TABLESPACE命令創(chuàng)建表空間。
?
創(chuàng)建表空間需要考慮數(shù)據(jù)庫對分區(qū)(Extent,一個Oracle分區(qū)是數(shù)據(jù)庫文件中一段連續(xù)的空間,Oracle分區(qū)是Oracle管理中最小的單位)的管理,比如當(dāng)一個表創(chuàng)建后先申請一個分區(qū),在Insert執(zhí)行過程中,如果分區(qū)數(shù)據(jù)已滿,需要重新申請另外的分區(qū)。如果一個數(shù)據(jù)庫中的分區(qū)大小不一,創(chuàng)建表空間時需要考慮一系列問題。因此在Oracle8i之后,創(chuàng)建表空間都推薦使用“本地管理表空間”,這種表空間中的分區(qū)是一個固定大小的值,創(chuàng)建表空間的語法是:
?
語法結(jié)構(gòu):創(chuàng)建表空間
| CREATE TABLESPACE 空間名稱 DATAFILE '文件名1' SIZE 數(shù)字M [,'文件名2' SIZE 數(shù)字….] EXTENT MANAGEMENT LOCAL UNIFORM SIZE 數(shù)字M |
語法解析:
1.???????文件名包括完整路徑和文件名,每個數(shù)據(jù)文件定義了文件的初始大小,初始大小一般以“M”為單位。一個表空間中可以有多個數(shù)據(jù)文件。
2.???????EXTENT MANAGEMENT LOCAL指明表空間類型是:本地管理表空間。本地管理表空間要求Oracle中的數(shù)據(jù)分區(qū)(Extent)大小統(tǒng)一。
3.???????UNIFORM SIZE:指定每個分區(qū)的統(tǒng)一大小。
?
案例5:創(chuàng)建一個表空間,包含兩個數(shù)據(jù)文件大小分別是10MB,5MB,要求extent的大小統(tǒng)一為1M。
?
代碼演示:創(chuàng)建表空間
| SQL> CREATE TABLESPACE MYSPACE ? 2? DATAFILE 'D:/A.ORA' SIZE 10M, ? 3???????????? 'D:/B.ORA' SIZE 5M ? 4? EXTENT MANAGEMENT LOCAL ? 5? UNIFORM SIZE 1M ? 6? / ? Tablespace created |
?
必須是管理員用戶才能創(chuàng)建表空間,當(dāng)表空間的空間不足時可以使用ALTER TABLESPACE命令向表空間中追加數(shù)據(jù)文件擴(kuò)充表空間。
?
代碼演示:擴(kuò)充表空間
| SQL> ALTER TABLESPACE MYSPACE ? 2? ADD DATAFILE 'D:/C.ORA' SIZE 10M ? 3? / ? Tablespace altered |
?
?????????表空間可以在不使用時刪除,使用DROP TABLESPACE命令。
?
?????????數(shù)據(jù)庫的所有數(shù)據(jù)全部在某一表空間中存放,在創(chuàng)建用戶時,可以為用戶指定某一表空間,那么該用戶下的所有數(shù)據(jù)庫對象(比如表)默認(rèn)都存儲在該空間中。
?
代碼演示:為某一用戶指定默認(rèn)表空間
| SQL> CREATE USER ACONG IDENTIFIED BY ACONG ? 2?? DEFAULT TABLESPACE MYSPACE ? 3? / ? User created |
?
?????????在創(chuàng)建表時,表中數(shù)據(jù)存放在用戶的默認(rèn)表空間中,也可以通過tablespace子句為表指定表中數(shù)據(jù)存放在其他表空間中。
?
代碼演示:為表指定表空間
| SQL> CREATE TABLE SCORES ? 2? ( ? 3????????? ID NUMBER , ? 4????????? TERM VARCHAR2(2), ? 5? ?? ????STUID VARCHAR2(7) NOT NULL, ? 6? ?? ????EXAMNO VARCHAR2(7) NOT NULL, ? 7? ?? ????WRITTENSCORE NUMBER(4,1) NOT NULL, ? 8? ?? ????LABSCORE NUMBER(4,1) NOT NULL ? 9? ) ?10? TABLESPACE MYSPACE ?11? / ? Table created |
?
?????????創(chuàng)建索引時也可以為索引指定表空間。
?
代碼演示:為索引指定表空間
| SQL> CREATE INDEX UQ_ID ON SCORES(ID) ? 2? TABLESPACE MYSPACE; ? Index created |
?
?????????表和索引一旦創(chuàng)建,表空間無法修改。
?
?
?
?
?
7.???本章總結(jié)
???Oracle數(shù)據(jù)庫對象都是使用CREATE命令創(chuàng)建的。
???同義詞就是數(shù)據(jù)庫對象的一個別名。同義詞的類型有公有同義詞和私有同義詞。只有管理員可以創(chuàng)建共有同義詞。創(chuàng)建同義詞的命令是:CREATE SYNONYM。
???序列能夠產(chǎn)生一個連續(xù)不重復(fù)的整數(shù)。經(jīng)常作為數(shù)據(jù)庫的主鍵生成器。創(chuàng)建序列的命令是CREATE SEQUENCE。
???序列的訪問使用兩個“偽列”,CURRVAL表示序列的當(dāng)前值,NEXTVAL表示序列的下一個值。
???視圖就是一個預(yù)處理的查詢語句,可以從若干表中過濾數(shù)據(jù)。
???索引就是在查詢中經(jīng)常使用的列進(jìn)行排序。常見的索引有:普通索引、唯一序列、組合索引以及基于函數(shù)的索引。此外還有位圖索引、反向鍵索引等。
???表空間是數(shù)據(jù)庫的一個邏輯概念,表空間由若干個數(shù)據(jù)文件組成。為數(shù)據(jù)庫對象和數(shù)據(jù)提供統(tǒng)一的空間管理。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
8.???本章練習(xí)
1.???????產(chǎn)生一個用于DEPT表的主鍵值的序列,序列起始值是100,最大值是500,增長步長是10。
2.???????用序列產(chǎn)生DEPT表的主鍵,向DEPT表中插入3條記錄。
3.???????為DEPT表創(chuàng)建一個同義詞。
4.???????創(chuàng)建一個視圖包括EMP表的EMPNO,ENAME,JOB,部門表的DNAME列,只能包含銷售部的記錄。
5.???????為EMP表的ENAME列創(chuàng)建唯一索引。
6.???????為EMP表的SAL列創(chuàng)建一個普通索引。
7.???????以學(xué)期和學(xué)生姓名為名稱比如(S2XiaoMei)創(chuàng)建一個表空間,該表空間是以學(xué)生姓名為用戶的默認(rèn)表空間。
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
第5章
?
?
PL/SQL程序設(shè)計
?
?
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? PL/SQL數(shù)據(jù)類型 ü? PL/SQL條件和循環(huán)控制 ü? 動態(tài)執(zhí)行SQL ü? PL/SQL中的異常處理 |
?
?
?
?
?
1.???PL/SQL簡介
從第一學(xué)期到現(xiàn)在,在數(shù)據(jù)庫上一直使用單一的SQL語句進(jìn)行數(shù)據(jù)操作,沒有流程控制,無法開發(fā)復(fù)雜的應(yīng)用。Oracle PL/SQL語言(Procedural Language/SQL)是結(jié)合了結(jié)構(gòu)化查詢與Oracle自身過程控制為一體的強(qiáng)大語言,PL/SQL不但支持更多的數(shù)據(jù)類型,擁有自身的變量聲明、賦值語句,而且還有條件、循環(huán)等流程控制語句。過程控制結(jié)構(gòu)與SQL數(shù)據(jù)處理能力無縫的結(jié)合形成了強(qiáng)大的編程語言,可以創(chuàng)建過程和函數(shù)以及程序包。
?
???????? PL/SQL是一種塊結(jié)構(gòu)的語言,它將一組語句放在一個塊中,一次性發(fā)送給服務(wù)器,PL/SQL引擎分析收到PL/SQL語句塊中的內(nèi)容,把其中的過程控制語句由PL/SQL引擎自身去執(zhí)行,把PL/SQL塊中的SQL語句交給服務(wù)器的SQL語句執(zhí)行器執(zhí)行。如圖所示:
?
?
圖1? PL/SQL體系結(jié)構(gòu)
?
???????? PL/SQL塊發(fā)送給服務(wù)器后,先被編譯然后執(zhí)行,對于有名稱的PL/SQL塊(如子程序)可以單獨編譯,永久的存儲在數(shù)據(jù)庫中,隨時準(zhǔn)備執(zhí)行。PL/SQL的優(yōu)點還有:
?
???支持SQL
?
SQL是訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)語言,通過SQL命令,用戶可以操縱數(shù)據(jù)庫中的數(shù)據(jù)。PL/SQL支持所有的SQL數(shù)據(jù)操縱命令、游標(biāo)控制命令、事務(wù)控制命令、SQL函數(shù)、運算符和偽列。同時PL/SQL和SQL語言緊密集成,PL/SQL支持所有的SQL數(shù)據(jù)類型和NULL值。
?
???支持面向?qū)ο缶幊?/strong>
?
PL/SQL支持面向?qū)ο蟮木幊?#xff0c;在PL/SQL中可以創(chuàng)建類型,可以對類型進(jìn)行繼承,可以在子程序中重載方法等。
?
???更好的性能
?
SQL是非過程語言,只能一條一條執(zhí)行,而PL/SQL把一個PL/SQL塊統(tǒng)一進(jìn)行編譯后執(zhí)行,同時還可以把編譯好的PL/SQL塊存儲起來,以備重用,減少了應(yīng)用程序和服務(wù)器之間的通信時間,PL/SQL是快速而高效的。
?
???可移植性
?
使用PL/SQL編寫的應(yīng)用程序,可以移植到任何操作系統(tǒng)平臺上的Oracle服務(wù)器,同時還可以編寫可移植程序庫,在不同環(huán)境中重用。
?
???安全性
??????????????????
可以通過存儲過程對客戶機(jī)和服務(wù)器之間的應(yīng)用程序邏輯進(jìn)行分隔,這樣可以限制對Oracle數(shù)據(jù)庫的訪問,數(shù)據(jù)庫還可以授權(quán)和撤銷其他用戶訪問的能力。
?
2.???PL/SQL塊
PL/SQL是一種塊結(jié)構(gòu)的語言,一個PL/SQL程序包含了一個或者多個邏輯塊,邏輯塊中可以聲明變量,變量在使用之前必須先聲明。除了正常的執(zhí)行程序外,PL/SQL還提供了專門的異常處理部分進(jìn)行異常處理。每個邏輯塊分為三個部分,語法是:
?
語法結(jié)構(gòu):PL/SQL塊的語法
| [DECLARE ???? --declaration statements]? ① BEGIN ???? --executable statements? ② [EXCEPTION ???? --exception statements]? ③ END; |
語法解析:
①??聲明部分:聲明部分包含了變量和常量的定義。這個部分由關(guān)鍵字DECLARE開始,如果不聲明變量或者常量,可以省略這部分。
②??執(zhí)行部分:執(zhí)行部分是?PL/SQL塊的指令部分,由關(guān)鍵字BEGIN開始,關(guān)鍵字END結(jié)尾。所有的可執(zhí)行PL/SQL語句都放在這一部分,該部分執(zhí)行命令并操作變量。其他的PL/SQL塊可以作為子塊嵌套在該部分。PL/SQL塊的執(zhí)行部分是必選的。注意END關(guān)鍵字后面用分號結(jié)尾。
③??異常處理部分:該部分是可選的,該部分用EXCEPTION關(guān)鍵字把可執(zhí)行部分分成兩個小部分,之前的程序是正常運行的程序,一旦出現(xiàn)異常就跳轉(zhuǎn)到異常部分執(zhí)行。
?
PL/SQL是一種編程語言,與Java和C#一樣,除了有自身獨有的數(shù)據(jù)類型、變量聲明和賦值以及流程控制語句外,PL/SQL還有自身的語言特性:
?
PL/SQL對大小寫不敏感,為了良好的程序風(fēng)格,開發(fā)團(tuán)隊都會選擇一個合適的編碼標(biāo)準(zhǔn)。比如有的團(tuán)隊規(guī)定:關(guān)鍵字全部大些,其余的部分小寫。
?
PL/SQL塊中的每一條語句都必須以分號結(jié)束,SQL語句可以是多行的,但分號表示該語句結(jié)束。一行中可以有多條SQL語句,他們之間以分號分隔,但是不推薦一行中寫多條語句。
?
PL/SQL中的特殊符號說明:
?
| 類型 | 符號 | 說明 |
| 賦值運算符 | := | Java和C#中都是等號,PL/SQL的賦值是:= |
| 特殊字符 | || | 字符串連接操作符。 |
| -- | PL/SQL中的單行注釋。 | |
| /*,*/ | PL/SQL中的多行注釋,多行注釋不能嵌套。 | |
| <<,>> | 標(biāo)簽分隔符。只為了標(biāo)識程序特殊位置。 | |
| .. | 范圍操作符,比如:1..5?標(biāo)識從1到5 | |
| 算術(shù)運算符 | +,-,*,/ | 基本算術(shù)運算符。 |
| ** | 求冪操作,比如:3**2=9 | |
| 關(guān)系運算符 | >,<,>=,<=,= | 基本關(guān)系運算符,=表示相等關(guān)系,不是賦值。 |
| <>,!= | 不等關(guān)系。 | |
| 邏輯運算符 | AND,OR,NOT | 邏輯運算符。 |
表1??PL/SQL中的特殊符號和運算符
?
2??變量聲明
?
PL/SQL支持SQL中的數(shù)據(jù)類型,PL/SQL中正常支持NUMBER,VARCHAR2,DATE等Oracle SQL數(shù)據(jù)類型。聲明變量必須指明變量的數(shù)據(jù)類型,也可以聲明變量時對變量初始化,變量聲明必須在聲明部分。聲明變量的語法是:
?
語法格式:聲明變量
| 變量名數(shù)據(jù)類型[ :=初始值] |
語法解析:
數(shù)據(jù)類型如果需要長度,可以用括號指明長度,比如:varchar2(20)。
?
代碼演示:聲明變量
| SQL> DECLARE ? 2?????? sname VARCHAR2(20) :='jerry';? ① ? 3? BEGIN ? 4?????? sname:=sname||' and tom';? ② ? 5?????? dbms_output.put_line(sname);? ③ ? 6? END; ? 7? /jerry PL/SQL procedure successfully completed |
代碼解析:
①??聲明一個變量sname,初始化值是“jerry”。字符串用單引號,如果字符串中出現(xiàn)單引號可以使用兩個單引號(’’)來表示,即單引號同時也具有轉(zhuǎn)義的作用。
②??對變量sname重新賦值,賦值運算符是“:=”。
③??dbms_output.put_line是輸出語句,可以把一個變量的值輸出,在SQL*Plus中輸出數(shù)據(jù)時,可能沒有結(jié)果顯示,可以使用命令:set serveroutput on設(shè)置輸出到SQL*Plus控制臺上。
?
對變量賦值還可以使用SELECT…INTO?語句從數(shù)據(jù)庫中查詢數(shù)據(jù)對變量進(jìn)行賦值。但是查詢的結(jié)果只能是一行記錄,不能是零行或者多行記錄。
?
代碼演示:變量賦值
| SQL> DECLARE ? 2?????? sname VARCHAR2(20) DEFAULT 'jerry';? ① ? 3? BEGIN ? 4?????? SELECT ename INTO sname FROM emp WHERE empno=7934;? ② ? 5?????? dbms_output.put_line(sname); ? 6? END; ? 7? / MILLER PL/SQL procedure successfully completed |
代碼解析:
①??變量初始化時,可以使用DEFAULT關(guān)鍵字對變量進(jìn)行初始化。
②??使用select…into語句對變量sname賦值,要求查詢的結(jié)果必須是一行,不能是多行或者沒有記錄。
?
2??聲明常量
?
常量在聲明時賦予初值,并且在運行時不允許重新賦值。使用CONSTANT關(guān)鍵字聲明常量。
?
代碼演示:聲明常量
| SQL> DECLARE ? 2?????? pi CONSTANT number :=3.14;?? --圓周率長值? ① ? 3?????? r number DEFAULT 3;?? --圓的半徑默認(rèn)值3? ② ? 4?????? area number;?? --面積。 ? 5? BEGIN ? 6?????? area:=pi*r*r;?? --計算面積 ? 7?????? dbms_output.put_line(area);? --輸出圓的面積 ? 8? END; ? 9? / ? 28.26 ? PL/SQL procedure successfully completed |
代碼解析:
①??聲明常量時使用關(guān)鍵字CONSTANT,常量初值可以使用賦值運算符(:=)賦值,也可以使用DEFAULT關(guān)鍵字賦值。
?
在SQL*Plus中還可以聲明Session(會話,也就是一個客戶端從連接到退出的過程稱為當(dāng)前用戶的會話。)全局級變量,該變量在整個會話過程中均起作用,類似的這種變量稱為宿主變量。宿主變量在PL/SQL引用時要用“:變量名”引用。
?
代碼演示:宿主常量
| SQL> var emp_name varchar(30);? ① SQL> BEGIN ? 2? SELECT ename INTO :emp_name FROM emp WHERE empno=7499;? ② ? 3 ?END; ? 4? / PL/SQL procedure successfully completed emp_name --------- ALLEN ? SQL> print emp_name;? ③ emp_name --------- ALLEN |
代碼解析:
①??可以使用var聲明宿主變量。
②??PL/SQL中訪問宿主變量時要在變量前加“:”。
③??在SQL*Plus中,使用print可以輸出變量中的結(jié)果。
?
3.???PL/SQL數(shù)據(jù)類型
前面在建表時,學(xué)習(xí)過Oracle SQL的數(shù)據(jù)類型,PL/SQL不但支持這些數(shù)據(jù)類型,還具備自身的數(shù)據(jù)類型。PL/SQL的數(shù)據(jù)類型包括標(biāo)量數(shù)據(jù)類型,引用數(shù)據(jù)類型和存儲文本、圖像、視頻、聲音等非結(jié)構(gòu)化的大數(shù)據(jù)類型(LOB數(shù)據(jù)類型)等。下面列舉一些常用的類型。
?
2??標(biāo)量數(shù)據(jù)類型
?
標(biāo)量數(shù)據(jù)類型的變量只有一個值,且內(nèi)部沒有分量。標(biāo)量數(shù)據(jù)類型包括數(shù)字型,字符型,日期型和布爾型。這些類型有的是Oracle SQL中定義的數(shù)據(jù)類型,有的是PL/SQL自身附加的數(shù)據(jù)類型。字符型和數(shù)字型又有子類型,子類型只與限定的范圍有關(guān),比如NUMBER類型可以表示整數(shù),也可以表示小數(shù),而其子類型POSITIVE只表示正整數(shù)。
?
| 類型 | 說明 |
| VARCHAR2(長度) | 可變長度字符串,Oracle SQL定義的數(shù)據(jù)類型,在PL/SQL中使用時最常32767字節(jié)。在PL/SQL中使用沒有默認(rèn)長度,因此必須指定。 |
| NUMBER(精度,小數(shù)) | Oracle SQL定義的數(shù)據(jù)類型,見第二章。 |
| DATE | Oracle SQL定義的日期類型,見第二章。 |
| TIMESTAMP | Oracle SQL定義的日期類型,見第二章。 |
| CHAR(長度) | Oracle SQL定義的日期類型,固定長度字符,最長32767字節(jié),默認(rèn)長度是1,如果內(nèi)容不夠用空格代替。 |
| LONG | Oracle SQL定義的數(shù)據(jù)類型,變長字符串基本類型,最長32760字節(jié)。在Oracle SQL中最長2147483647字節(jié)。 |
| BOOLEAN | PL/SQL附加的數(shù)據(jù)類型,邏輯值為TRUE、FALSE、NULL |
| BINARY_INTEGER | PL/SQL附加的數(shù)據(jù)類型,介于-231和231之間的整數(shù)。 |
| PLS_INTEGER | PL/SQL附加的數(shù)據(jù)類型,介于-231和231之間的整數(shù)。類似于BINARY_INTEGER,只是PLS_INTEGER值上的運行速度更快。 |
| NATURAL | PL/SQL附加的數(shù)據(jù)類型,BINARY_INTEGER子類型,表示從0開始的自然數(shù)。 |
| NATURALN | 與NATURAL一樣,只是要求NATURALN類型變量值不能為NULL。 |
| POSITIVE | PL/SQL附加的數(shù)據(jù)類型,BINARY_INTEGER子類型,正整數(shù)。 |
| POSITIVEN | 與POSITIVE一樣,只是要求POSITIVE的變量值不能為NULL。 |
| REAL | Oracle SQL定義的數(shù)據(jù)類型,18位精度的浮點數(shù) |
| INT,INTEGER,SMALLINT | Oracle SQL定義的數(shù)據(jù)類型,NUMBERDE的子類型,38位精度整數(shù)。 |
| SIGNTYPE | PL/SQL附加的數(shù)據(jù)類型,BINARY_INTEGER子類型。值有:1、-1、0。 |
| STRING | 與VARCHAR2相同。 |
表2??PL/SQL中標(biāo)量數(shù)據(jù)類型。
?
2??屬性數(shù)據(jù)類型
?
當(dāng)聲明一個變量的值是數(shù)據(jù)庫中的一行或者是數(shù)據(jù)庫中某列時,可以直接使用屬性類型來聲明。Oracle中存在兩種屬性類型:%TYPE和%ROWTYPE。
?
???% ROWTYPE
引用數(shù)據(jù)庫表中的一行作為數(shù)據(jù)類型,即RECORD類型(記錄類型),是PL/SQL附加的數(shù)據(jù)類型。表示一條記錄,就相當(dāng)于C#中的一個對象??梢允褂谩?”來訪問記錄中的屬性。
?
代碼演示:
| SQL> DECLARE ? 2?????? myemp EMP%ROWTYPE;? ① ? 3? BEGIN ? 4?????? SELECT * INTO myemp FROM emp WHERE empno=7934;? ② ? 5?????? dbms_output.put_line(myemp.ename);? ③ ? 6? END; ? 7? / MILLER PL/SQL procedure successfully completed |
代碼解析:
①??聲明一個myemp對象,該對象表示EMP表中的一行。
②??從EMP表中查詢一條記錄放入myemp對象中。
③??訪問該對象的屬性可以使用“.”。
?
???%TYPE
引用某個變量或者數(shù)據(jù)庫的列的類型作為某變量的數(shù)據(jù)類型。
?
代碼演示:%TYPE應(yīng)用
| SQL> DECLARE ? 2?????? sal emp.sal%TYPE;? ① ? 3?????? mysal number(4):=3000; ? 4?????? totalsal mysal%TYPE;? ② ? 5? BEGIN ? 6?????? SELECT SAL INTO sal FROM emp WHERE empno=7934; ? 7?????? totalsal:=sal+mysal; ? 8?????? dbms_output.put_line(totalsal); ?9? END; ?10? / 4300 PL/SQL procedure successfully completed |
代碼解析:
①??定義變量sal為emp表中sal列的類型。
②??定義totalsal是變量mysal的類型。
?
%TYPE可以引用表中的某列作的類型為變量的數(shù)據(jù)類型,也可以引用某變量的類型作為新變量的數(shù)據(jù)類型。
?
4.???PL/SQL條件控制和循環(huán)控制
PL/SQL程序可通過條件或循環(huán)結(jié)構(gòu)來控制命令執(zhí)行的流程。PL/SQL提供了豐富的流程控制語句,與C#一樣也有三種控制結(jié)構(gòu):
???順序結(jié)構(gòu)
???條件結(jié)構(gòu)
???循環(huán)結(jié)構(gòu)
?
2??條件控制
?
C#中的條件控制使用關(guān)鍵字if和switch。PL/SQL中關(guān)于條件控制的關(guān)鍵字有IF-THEN、IF-THEN-ELSE、IF-THEN-ELSIF和多分枝條件CASE。
?
???IF-THEN
該結(jié)構(gòu)先判斷一個條件是否為TRUE,條件成立則執(zhí)行對應(yīng)的語句塊,與C#中的if語句很相似,具體語法是:
?
| C#中if語法 | PL/SQL中IF語法 |
| if (條件){ ???? //條件結(jié)構(gòu)體 } | IF?條件?THEN ???? --條件結(jié)構(gòu)體 END IF; |
表3 ?PL/SQL中條件語法
?
說明:
①??用IF關(guān)鍵字開始,END IF關(guān)鍵字結(jié)束,注意END IF后面有一個分號。
②??條件部分可以不使用括號,但是必須以關(guān)鍵字THEN來標(biāo)識條件結(jié)束,如果條件成立,則執(zhí)行THEN后到對應(yīng)END IF之間的語句塊內(nèi)容。如果條件不成立,則不執(zhí)行條件語句塊的內(nèi)容。
③??C#結(jié)構(gòu)用一對大括號來包含條件結(jié)構(gòu)體的內(nèi)容。PL/SQL中關(guān)鍵字THEN到END IF之間的內(nèi)容是條件結(jié)構(gòu)體內(nèi)容。
④??條件可以使用關(guān)系運算符合邏輯運算符。
?
案例1:查詢JAMES的工資,如果大于900元,則發(fā)獎金800元。
?
代碼演示:IF-THEN應(yīng)用
| DECLARE ????? newSal emp.sal % TYPE; ?BEGIN ????? SELECT sal INTO newSal FROM emp ????? WHERE ename='JAMES'; ????? IF newSal>900 THEN? ① ?????????? UPDATE emp ?????????? SET comm=800 ?????????? WHERE ename='JAMES'; ????? END IF; ????? COMMIT ;? ② END; |
代碼解析:
①??先判斷條件,如果條件為TRUE,則執(zhí)行條件結(jié)構(gòu)體內(nèi)部的內(nèi)容。
②??在PL/SQL塊中可以使用事務(wù)控制語句,該COMMIT同時也能把PL/SQL塊外沒有提交的數(shù)據(jù)一并提交,使用時需要注意。
?
???IF-THEN-ELSE
?
語法格式:IF-THEN-ELSE
| C#中if語法 | PL/SQL中IF語法 |
| if (條件){ ???? //條件成立結(jié)構(gòu)體 } else{ ??? //條件不成立結(jié)構(gòu)體 } | IF?條件?THEN ???? --條件成立結(jié)構(gòu)體 ELSE ???? --條件不成立結(jié)構(gòu)體 END IF; |
表4 ?PL/SQL中條件語法
?
語法解析:
把ELSE與IF-THEN連在一起使用,如果IF條件不成立則執(zhí)行就會執(zhí)行ELSE部分的語句。
?
案例2:查詢JAMES的工資,如果大于900元,則發(fā)獎金800元,否則發(fā)獎金400元。
?
代碼演示:IF-THEN-ELSE應(yīng)用
| DECLARE ????? newSal emp.sal % TYPE; BEGIN ????? SELECT sal INTO newSal FROM emp ????? WHERE ename='JAMES'; ????? IF newSal>900 THEN ?????????? UPDATE emp ?????????? SET comm=800 ?????????? WHERE ename='JAMES'; ??? ??ELSE ?????????? UPDATE emp ?????????? SET comm=400 ?????????? WHERE ename='JAMES'; ????? END IF; END; |
?
???IF-THEN-ELSIF
?
語法格式:IF-THEN-ELSIF
| C#中if語法 | PL/SQL中IF語法 |
| if (條件2){ ???? //條件成立結(jié)構(gòu)體 } else if(條件2){ ??? //條件不成立結(jié)構(gòu)體 } else{ ??? //以上條件都不成立結(jié)構(gòu)體 } | IF?條件1 THEN ???? --條件1成立結(jié)構(gòu)體 ELSIF?條件2 THEN ???? --條件2成立結(jié)構(gòu)體 ELSE ???? --以上條件都不成立結(jié)構(gòu)體 END IF; |
表5 ?PL/SQL中多分枝條件語法
語法解析:
PL/SQL中的再次條件判斷中使用關(guān)鍵字ELSIF,而C#使用else if。
?
案例3:查詢JAMES的工資,如果大于1500元,則發(fā)放獎金100元,如果工作大于900元,則發(fā)獎金800元,否則發(fā)獎金400元。
?
代碼演示:IF-THEN-ELSIF應(yīng)用
| DECLARE ????? newSal emp.sal % TYPE; BEGIN ????? SELECT sal INTO newSal FROM emp ????? WHERE ename='JAMES'; ????? IF newSal>1500 THEN ?????????? UPDATE emp ?????????? SET comm=1000 ?????????? WHERE ename='JAMES'; ????? ELSIF newSal>1500 THEN ?????????? UPDATE emp ?????????? SET comm=800 ?????????? WHERE ename='JAMES'; ????? ELSE ?????????? UPDATE emp ?????????? SET comm=400 ?????????? WHERE ename='JAMES'; ????? END IF; END; |
?
???CASE
?
CASE是一種選擇結(jié)構(gòu)的控制語句,可以根據(jù)條件從多個執(zhí)行分支中選擇相應(yīng)的執(zhí)行動作。也可以作為表達(dá)式使用,返回一個值。類似于C#中的switch語句。語法是:
?
語法格式:CASE
| CASE [selector] WHEN?表達(dá)式1 THEN?語句序列1; WHEN?表達(dá)式2 THEN?語句序列2; WHEN?表達(dá)式3 THEN?語句序列3; …… [ELSE?語句序列N]; END CASE; |
語法解析:
?????????如果存在選擇器selector,選擇器selector與WHEN后面的表達(dá)式匹配,匹配成功就執(zhí)行THEN后面的語句。如果所有表達(dá)式都與selector不匹配,則執(zhí)行ELSE后面的語句。
?
案例4:輸入一個字母A、B、C分別輸出對應(yīng)的級別信息。
?
代碼演示:CASE中存在selector,不返回值
| DECLARE ????? v_grade CHAR(1):=UPPER('&p_grade');? ① BEGIN ????? CASE v_grade? ② ?????????? WHEN 'A' THEN ?????????????? dbms_output.put_line('Excellent'); ?????????? WHEN 'B' THEN ?????????????? dbms_output.put_line('Very Good'); ?????????? WHEN 'C' THEN ?????????????? dbms_output.put_line('Good'); ?????????? ELSE ?????????????? dbms_output.put_line('No such grade'); ????? END CASE; END; |
代碼解析:
①??& grade表示在運行時由鍵盤輸入字符串到grade變量中。
②??v_grade分別于WHEN后面的值匹配,如果成功就執(zhí)行WHEN后的程序序列。
?
CASE語句還可以作為表達(dá)式使用,返回一個值。
?
代碼演示:CASE中存在selector,作為表達(dá)式使用
| DECLARE ????? v_grade CHAR(1):=UPPER('&grade'); ????? p_grade VARCHAR(20) ; BEGIN ????? p_grade :=? ① ????? CASE v_grade ?????????? WHEN 'A' THEN ?????????????? 'Excellent' ?????????? WHEN 'B' THEN ?????????????? 'Very Good' ?????????? WHEN 'C' THEN ?????????????? 'Good' ?????????? ELSE ?????????????? 'No such grade' ????? END; ????? dbms_output.put_line('Grade:' ||v_grade||',the result is '||p_grade); END; |
代碼解析:
①??CASE語句可以返回一個結(jié)果給變量p_grade
?
PL/SQL還提供了搜索CASE語句。也就是說,不使用CASE中的選擇器,直接在WHEN后面判斷條件,第一個條件為真時,執(zhí)行對應(yīng)THEN后面的語句序列。
?
代碼演示:搜索CASE
| DECLARE ????? v_grade CHAR(1):=UPPER('&grade'); ????? p_grade VARCHAR(20) ; BEGIN ????? p_grade := ????? CASE ?????????? WHEN v_grade='A' THEN ?????????????? 'Excellent' ?????????? WHEN v_grade='B' THEN ???????????? ??'Very Good' ?????????? WHEN v_grade='C' THEN ?????????????? 'Good' ?????????? ELSE ?????????????? 'No such grade' ????? END; ????? dbms_output.put_line('Grade:' ||v_grade||',the result is '||p_grade); END; |
?
2??循環(huán)結(jié)構(gòu)
?
PL/SQL提供了豐富的循環(huán)結(jié)構(gòu)來重復(fù)執(zhí)行一些列語句。Oracle提供的循環(huán)類型有:
1.?????????無條件循環(huán)LOOP-END LOOP語句
2.?????????WHILE循環(huán)語句
3.?????????FOR循環(huán)語句
?
在上面的三類循環(huán)中EXIT用來強(qiáng)制結(jié)束循環(huán),相當(dāng)于C#循環(huán)中的break。
?
???LOOP循環(huán)
?
LOOP循環(huán)是最簡單的循環(huán),也稱為無限循環(huán),LOOP和END LOOP是關(guān)鍵字。
?
語法格式:LOOP循環(huán)
| LOOP ??? --循環(huán)體 END LOOP; |
語法格式:
1.???????循環(huán)體在LOOP和END LOOP之間,在每個LOOP循環(huán)體中,首先執(zhí)行循環(huán)體中的語句序列,執(zhí)行完后再重新開始執(zhí)行。
2.???????在LOOP循環(huán)中可以使用EXIT或者[EXIT WHEN?條件]的形式終止循環(huán)。否則該循環(huán)就是死循環(huán)。
?
案例5:執(zhí)行1+2+3+…+100的值
?
代碼演示:LOOP循環(huán)
| DECLARE ????? counter number(3):=0; ????? sumResult number:=0; BEGIN ????? LOOP ????????? counter := counter+1; ????????? sumResult := sumResult+counter; ????????? IF counter>=100 THEN? ① ? ????????????EXIT; ????????? END IF; ??????????--EXIT WHEN counter>=100;? ② ????? END LOOP; ?????? dbms_output.put_line('result is :'||to_char(sumResult)); END; |
代碼解析:
①??LOOP循環(huán)中可以使用IF結(jié)構(gòu)嵌套EXIT關(guān)鍵字退出循環(huán)
②??注釋行,該行可以代替①中的循環(huán)結(jié)構(gòu),WHEN后面的條件成立時跳出循環(huán)。
?
???WHILE循環(huán)
?
與C#中的while循環(huán)很類似。先判斷條件,條件成立再執(zhí)行循環(huán)體。
?
語法格式:WHILE
| C#中while語法 | PL/SQL中WHILE語法 |
| while (條件){ ???? //循環(huán)體體 } | WHILE?條件?LOOP ??? --循環(huán)體 END LOOP; |
表5 ?PL/SQL中LOOP語法
?
案例6:WHILE循環(huán)
?
代碼演示:WHILE循環(huán)
| DECLARE ????? counter number(3):=0; ????? sumResult number:=0; BEGIN ????? WHILE counter<100 LOOP ????????? counter := counter+1; ????????? sumResult := sumResult+counter; ????? END LOOP; ?????? dbms_output.put_line('result is :'||sumResult); END; |
?
???FOR循環(huán)
?
FOR循環(huán)需要預(yù)先確定的循環(huán)次數(shù),可通過給循環(huán)變量指定下限和上限來確定循環(huán)運行的次數(shù),然后循環(huán)變量在每次循環(huán)中遞增(或者遞減)。FOR循環(huán)的語法是:
?
語法格式:FOR循環(huán)
| FOR?循環(huán)變量?IN [REVERSE]?循環(huán)下限..循環(huán)上限?LOOP LOOP --循環(huán)體 END LOOP; |
語法解析:
循環(huán)變量:該變量的值每次循環(huán)根據(jù)上下限的REVERSE關(guān)鍵字進(jìn)行加1或者減1。
REVERSE:指明循環(huán)從上限向下限依次循環(huán)。
?
案例7:FOR循環(huán)
?
代碼演示:FOR循環(huán)
| DECLARE ????? counter number(3):=0; ????? sumResult number:=0; BEGIN ????? FOR counter IN 1..100 LOOP ????????? sumResult := sumResult+counter; ????? END LOOP; ?????? dbms_output.put_line('result is :'||sumResult); END; |
?
2??順序結(jié)構(gòu)
?
在程序順序結(jié)構(gòu)中有兩個特殊的語句。GOTO和NULL
?
???GOTO語句
?
GOTO語句將無條件的跳轉(zhuǎn)到標(biāo)簽指定的語句去執(zhí)行。標(biāo)簽是用雙尖括號括起來的標(biāo)示符,在PL/SQL塊中必須具有唯一的名稱,標(biāo)簽后必須緊跟可執(zhí)行語句或者PL/SQL塊。GOTO不能跳轉(zhuǎn)到IF語句、CASE語句、LOOP語句、或者子塊中。
?
???NULL語句
?
NULL語句什么都不做,只是將控制權(quán)轉(zhuǎn)到下一行語句。NULL語句是可執(zhí)行語句。NULL語句在IF或者其他語句語法要求至少需要一條可執(zhí)行語句,但又不需要具體操作的地方。比如GOTO的目標(biāo)地方不需要執(zhí)行任何語句時。
?
案例8:GOGO?和?NULL
?
代碼演示:GOTO和NULL
| DECLARE ??? sumsal emp.sal%TYPE; BEGIN ??? SELECT SUM(sal) INTO sumsal FROM EMP; ??? IF sumsal>20000 THEN ??????? GOTO first_label;? ① ??? ELSE ??????? GOTO second_label;? ② ??? END IF; ??? <<first_label>>? ③ ??? dbms_output.put_line('ABOVE 20000:' || sumsal); ??? <<second_label>>? ④ ??? NULL; END; |
代碼解析:
①??跳轉(zhuǎn)到程序first_label位置,就是②的位置,first_label是一個標(biāo)簽,用兩個尖括號包含。
②??無條件跳轉(zhuǎn)到sedond_label位置,就是④的位置。④處不執(zhí)行任何內(nèi)容,因此是一個NULL語句。
?
與C#一樣,在PL/SQL中,各種循環(huán)之間可以相互嵌套。
?
5.???PL/SQL中動態(tài)執(zhí)行SQL語句
在PL/SQL程序開發(fā)中,可以使用DML語句和事務(wù)控制語句,但是還有很多語句(比如DDL語句)不能直接在PL/SQL中執(zhí)行。這些語句可以使用動態(tài)SQL來實現(xiàn)。
?
PL/SQL塊先編譯然后再執(zhí)行,動態(tài)SQL語句在編譯時不能確定,只有在程序執(zhí)行時把SQL語句作為字符串的形式由動態(tài)SQL命令來執(zhí)行。在編譯階段SQL語句作為字符串存在,程序不會對字符串中的內(nèi)容進(jìn)行編譯,在運行階段再對字符串中的SQL語句進(jìn)行編譯和執(zhí)行,動態(tài)SQL的語法是:
?
語法格式:動態(tài)SQL
| EXECUTE IMMEDIATE?動態(tài)語句字符串 [INTO?變量列表] [USING?參數(shù)列表] |
語法解析:
?????????如果動態(tài)語句是SELECT語句,可以把查詢的結(jié)果保存到INTO后面的變量中。如果動態(tài)語句中存在參數(shù),USING為語句中的參數(shù)傳值。
?????????動態(tài)SQL中的參數(shù)格式是:[:參數(shù)名],參數(shù)在運行時需要使用USING傳值。
?????? 案例9:動態(tài)SQL
?
代碼演示:動態(tài)SQL
| DECLARE ?? sql_stmt??? VARCHAR2(200);? --動態(tài)SQL語句 ?? emp_id????? NUMBER(4) := 7566; ?? salary????? NUMBER(7,2); ?? dept_id???? NUMBER(2) := 90; ?? dept_name?? VARCHAR2(14) := 'PERSONNEL'; ?? location??? VARCHAR2(13) := 'DALLAS'; ?? emp_rec???? emp%ROWTYPE; BEGIN ?? --無子句的execute immediate ?? EXECUTE IMMEDIATE 'CREATE TABLE bonus1 (id NUMBER, amt NUMBER)';? ① ?? ----using子句的execute immediate ?? sql_stmt := 'INSERT INTO dept VALUES (:1, :2, :3)';? ?? EXECUTE IMMEDIATE sql_stmt USING dept_id, dept_name, location;? ② ?? ----into子句的execute immediate ?? sql_stmt := 'SELECT * FROM emp WHERE empno = :id'; ?? EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id;? ③ ? ?? ----returning into子句的execute immediate ?? sql_stmt := 'UPDATE emp SET sal = 2000 WHERE empno = :1 ????? RETURNING sal INTO :2'; ?? EXECUTE IMMEDIATE sql_stmt USING emp_id RETURNING INTO salary;? ④ ? ?? EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = :num' ????? USING dept_id;? ⑤ END; |
代碼解析:
①??動態(tài)執(zhí)行一個完整的SQL語句。
②??SQL語句中存在3個參數(shù)分別標(biāo)識為:[:1、:2、:3],因此需要用USING關(guān)鍵字對三個參數(shù)分別賦值。
③??對動態(tài)查詢語句可以使用INTO子句把查詢的結(jié)果保存到一個變量中,要求該結(jié)果只能是單行。
④??在Oracle的insert,update,delete語句都可以使用RETURNING子句把操作影響的行中的數(shù)據(jù)返回,對SQL語句中存在RETURNING子句時,在動態(tài)執(zhí)行時可以使用RETURNING INTO來接收。
⑤??動態(tài)執(zhí)行參數(shù)中可以是:[:數(shù)字]也可以是[:字符串]。
?
6.???PL/SQL的異常處理
在程序運行時出現(xiàn)的錯誤,稱為異常。發(fā)生異常后,語句將停止執(zhí)行,PL/SQL引擎立即將控制權(quán)轉(zhuǎn)到PL/SQL塊的異常處理部分。異常處理機(jī)制簡化了代碼中的錯誤檢測。PL/SQL中任何異常出現(xiàn)時,每一個異常都對應(yīng)一個異常碼和異常信息。比如:
?
?
圖1 ?PL/SQL中的異常
?
2??預(yù)定義異常
????????
為了Oracle開發(fā)和維護(hù)的方便,在Oracle異常中,為常見的異常碼定義了對應(yīng)的異常名稱,稱為預(yù)定義異常,常見的預(yù)定義異常有:
?
| 異常名稱 | 異常碼 | 描述 |
| DUP_VAL_ON_INDEX | ORA-00001 | 試圖向唯一索引列插入重復(fù)值 |
| INVALID_CURSOR | ORA-01001 | 試圖進(jìn)行非法游標(biāo)操作。 |
| INVALID_NUMBER | ORA-01722 | 試圖將字符串轉(zhuǎn)換為數(shù)字 |
| NO_DATA_FOUND | ORA-01403 | SELECT INTO語句中沒有返回任何記錄。 |
| TOO_MANY_ROWS | ORA-01422 | SELECT INTO語句中返回多于1條記錄。 |
| ZERO_DIVIDE | ORA-01476 | 試圖用0作為除數(shù)。 |
| CURSOR_ALREADY_OPEN | ORA-06511 | 試圖打開一個已經(jīng)打開的游標(biāo) |
表6 ?PL/SQL中預(yù)定義異常
?
???????? PL/SQL中用EXCEPTION關(guān)鍵字開始異常處理。具體語法是:
?
語法格式:異常處理
| BEGIN ???????? --可執(zhí)行部分 ???????? EXCEPTION?? --?異常處理開始 ?????????????????? WHEN?異常名1 THEN ??????????????????????????? ?--對應(yīng)異常處理 ??????? WHEN?異常名2 THEN ??????????????????????????? ?--對應(yīng)異常處理 ???????? …… ?????????????????? WHEN OTHERS THEN ???????????? --其他異常處理 ???????? END; |
語法解析:
?????????異常發(fā)生時,進(jìn)入異常處理部分,具體的異常與若干個WHEN子句中指明的異常名匹配,匹配成功就進(jìn)入對應(yīng)的異常處理部分,如果對應(yīng)不成功,則進(jìn)入OTHERS進(jìn)行處理。
?
?????????案例10 :異常處理
?
代碼演示:異常處理
| SQL> DECLARE ? 2??????? newSal emp.sal % TYPE; ? 3? BEGIN ? 4??????? SELECT sal INTO newSal FROM emp; ? 5? EXCEPTION ? 6??????? WHEN TOO_MANY_ROWS THEN ? 7??????????? dbms_output.put_line('返回的記錄太多了'); ? 8??????? WHEN OTHERS THEN ? 9??????????? dbms_output.put_line('未知異常'); ?10? END; ?11? / 返回的記錄太多了 PL/SQL procedure successfully completed |
?
2??自定義異常。
?
?????????除了預(yù)定義異常外,用戶還可以在開發(fā)中自定義異常,自定義異常可以讓用戶采用與PL/SQL引擎處理錯誤相同的方式進(jìn)行處理,用戶自定義異常的兩個關(guān)鍵點:
???異常定義:在PL/SQL塊的聲明部分采用EXCEPTION關(guān)鍵字聲明異常,定義方法與定義變量相同。比如聲明一個myexception異常方法是:
myexception EXCEPTION;
???異常引發(fā):在程序可執(zhí)行區(qū)域,使用RAISE關(guān)鍵字進(jìn)行引發(fā)。比如引發(fā)myexception方法是:
RAISE myexception;
?
?????? 案例11:自定義異常
?
代碼演示:自定義異常
| SQL> DECLARE ? 2????? sal emp.sal%TYPE; ? 3????? myexp EXCEPTION;? ① ? 4? BEGIN ? 5????? SELECT sal INTO sal FROM emp WHERE ename='JAMES'; ? 6????? IF sal<5000 THEN ? 7???????? RAISE myexp;? ② ? 8????? END IF; ? 9? EXCEPTION ?10????? WHEN NO_DATA_FOUND THEN ?11?????????? dbms_output.put_line('NO RECORDSET FIND!'); ?12????? WHEN MYEXP THEN? ③ ?13?????????? dbms_output.put_line('SAL IS TO LESS!'); ?14? END; ?15? / SAL IS TO LESS! PL/SQL procedure successfully completed |
代碼解析:
①??用EXCEPTION定義一個異常變量myexp
②??在一定條件下用RAISE引發(fā)異常myexp
③??在異常處理部分,捕獲異常,如果不處理異常,該異常就拋給程序執(zhí)行者。
?
2??引發(fā)應(yīng)用程序異常
?
在Oracle開發(fā)中,遇到的系統(tǒng)異常都有對應(yīng)的異常碼,在應(yīng)用系統(tǒng)開發(fā)中,用戶自定義的異常也可以指定一個異常碼和異常信息,Oracle系統(tǒng)為用戶預(yù)留了自定義異常碼,其范圍介于-20000到-20999之間的負(fù)整數(shù)。引發(fā)應(yīng)用程序異常的語法是:
RAISE_APPLICATION_ERROR(異常碼,異常信息)
?
案例12:引發(fā)系統(tǒng)異常
?
代碼演示:引發(fā)應(yīng)用系統(tǒng)異常
| SQL> DECLARE ? 2????? sal emp.sal%TYPE; ? 3????? myexp EXCEPTION; ? 4? BEGIN ? 5????? SELECT sal INTO sal FROM emp WHERE ename='JAMES'; ? 6????? IF sal<5000 THEN ? 7???????? RAISE myexp; ? 8????? END IF; ? 9? EXCEPTION ?10????? WHEN NO_DATA_FOUND THEN ?11?????????? dbms_output.put_line('NO RECORDSET FIND!'); ?12????? WHEN MYEXP THEN ?13?????????? RAISE_APPLICATION_ERROR(-20001,'SAL IS TO LESS!');? ① ?14? END; ?15? / ORA-20001: SAL IS TO LESS!? ② ORA-06512: 在 line 14 |
代碼解析:
①??引發(fā)應(yīng)用系統(tǒng)異常,指明異常碼和異常信息。
②??在控制臺上顯示異常碼和異常信息。
?
如果要處理未命名的內(nèi)部異常,必須使用OTHERS異常處理器。也可以利用PRAGMA EXCEPTION_INIT把一個異常碼與異常名綁定。
?
PRAGMA由編譯器控制,PRAGMA在編譯時處理,而不是在運行時處理。EXCEPTION_INIT告訴編譯器將異常名與ORACLE錯誤碼綁定起來,這樣可以通過異常名引用任意的內(nèi)部異常,并且可以通過異常名為異常編寫適當(dāng)?shù)漠惓L幚砥?。PRAGMA EXCEPTION_INIT的語法是:
PRAGMA EXCEPTION_INIT(異常名,異常碼)
?
這里的異常碼可以是用戶自定義的異常碼,也可以是Oracle系統(tǒng)的異常碼。
?
案例13:PRAGMA EXCEPTION_INIT異常
?
代碼演示:PRAGMA EXCEPTION_INIT異常
| <<outterseg>> DECLARE ? null_salary EXCEPTION; ? PRAGMA EXCEPTION_INIT(null_salary, -20101);? ① BEGIN ? <<innerStart>>? ② ? DECLARE ??? curr_comm NUMBER; ? BEGIN ??? SELECT comm INTO curr_comm FROM emp WHERE empno = &empno; ??? IF curr_comm IS NULL THEN??? ???????? RAISE_APPLICATION_ERROR(-20101, 'Salary is missing');? ③ ??? ELSE ????? dbms_output.put_line('有津貼'); ??? END IF; ? END;? EXCEPTION ? WHEN NO_DATA_FOUND THEN ????????? dbms_output.put_line('沒有發(fā)現(xiàn)行'); ? WHEN null_salary THEN ????????? dbms_output.put_line('津貼未知');? ④ ? WHEN OTHERS THEN ?????????? dbms_output.put_line('未知異常'); END; |
代碼解析:
①??把異常名稱null_salary與異常碼-20101關(guān)聯(lián),該語句由于是預(yù)編譯語句,必須放在聲明部分。也就是說-20101的異常名稱就是null_salary。
②??嵌套PL/SQL語句塊
③??在內(nèi)部PL/SQL語句塊中引發(fā)應(yīng)用系統(tǒng)異常-20101。
④??在外部的PL/SQL語句塊中就可以用異常名null_salary進(jìn)行捕獲。
?
7.???本章總結(jié)
???PL/SQL是一種塊結(jié)構(gòu)的語言,它將一組語句放在一個塊中,一次性發(fā)送給服務(wù)器,PL/SQL引擎把接收到PL/SQL語句塊中的內(nèi)容進(jìn)行分析,把其中的過程控制語句由PL/SQL引擎自身去執(zhí)行,把PL/SQL語句塊中的SQL語句交給服務(wù)器的SQL語句執(zhí)行器執(zhí)行。
???PL/SQL的數(shù)據(jù)類型包括標(biāo)量數(shù)據(jù)類型,引用數(shù)據(jù)類型和存儲文本、圖像、視頻、聲音等非結(jié)構(gòu)化得大數(shù)據(jù)類型(LOB數(shù)據(jù)類型)等。
???Oracle中存在兩種屬性類型:%TYPE和%ROWTYPE。
???PL/SQL程序可通過控制結(jié)構(gòu)來控制命令執(zhí)行的流程。PL/SQL中提供三種程序結(jié)構(gòu):順序結(jié)構(gòu)、條件結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。
???在PL/SQL程序開發(fā)中,可以使用DML語句和事務(wù)控制語句,還可以動態(tài)執(zhí)行SQL語句,動態(tài)執(zhí)行SQL語句的命令是:EXECUTE IMMEDIATE。
???在程序運行時出現(xiàn)的錯誤,稱為異常。發(fā)生異常后,語句將停止執(zhí)行,PL/SQL引擎立即將控制權(quán)轉(zhuǎn)到PL/SQL塊的異常處理部分。PL/SQL中任何異常出現(xiàn)時,每一個異常都對應(yīng)一個異常碼和異常信息。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
8.???本章練習(xí)
1.???????PL/SQL有哪些優(yōu)點?
2.???????請描述PL/SQL塊的結(jié)構(gòu)。
3.???????請描述多分枝判斷CASE的用法。
4.???????PL/SQL中有哪些循環(huán)控制語句?如何使用它們?
5.???????如何執(zhí)行動態(tài)SQL語句?
6.???????如何自定義異常,如何把自定義異常與異常碼綁定?
7.???????編寫一個程序,輸入一個整數(shù),使用循環(huán)結(jié)構(gòu)將該數(shù)字左右翻轉(zhuǎn),輸出翻轉(zhuǎn)后的結(jié)果。
8.???????編寫一個程序,在EMP表查找姓名為ALLEN員工,并獲取TOO_MANY_ROWS和NO_DATA_FOUND異常。
9.???????編寫一個過程為班級每位同學(xué)創(chuàng)建一個用戶,用戶名和密碼都是:“班級號+學(xué)號”,并為每位用戶授權(quán):CONNECT和RESOURCE。
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
?
?
?
?
第6章
?
?
Oracle應(yīng)用于.Net平臺
?
?
?
?
?
?
?
?
| ? | 主要內(nèi)容 |
| ? | ü? 回顧ADO.NET ü? 使用ADO.NET連接Oracle ü? 抽象工廠加入Oracle ? ? ? |
?
?
?
?
?
?
1.???回顧ADO.NET
ADO.NET是一組用于和數(shù)據(jù)源進(jìn)行交互的面向?qū)ο箢悗旒?#xff0c;它存在于.Net Framework中。通常情況下,數(shù)據(jù)源可以是各種類型的數(shù)據(jù)庫,利用ADO.NET可以訪問目前幾乎所有的主流數(shù)據(jù)庫,如Oracle、SQL Server、DB2、Access等,但數(shù)據(jù)源同樣也能夠是文本文件、Excel文件或者XML文件,因此,ADO.NET可以訪問的數(shù)據(jù)源是很多的。
?
ADO.NET由兩部分組成:.Net數(shù)據(jù)提供程序和數(shù)據(jù)集。
?
2??.Net數(shù)據(jù)提供程序
?
ADO.NET提供了與常用的各種數(shù)據(jù)源進(jìn)行交互的一些公共方法,但是對于不同的數(shù)據(jù)源由于它們各采用的協(xié)議是不一樣的,所以會采用不同的類庫,這些類庫稱為數(shù)據(jù)提供程序。主要的數(shù)據(jù)提供程序如表1所示:
?
| 數(shù)據(jù)提供程序 | 說明 | 對應(yīng)的命名空間 |
| SQL Server.NET | 訪問SQL Server數(shù)據(jù)庫的提供程序,由于是針對SQLServer數(shù)據(jù)源而設(shè)計,所以采用本提供程序訪問SQL Server數(shù)據(jù)源時要比采用其它的提供程序,如OLE DB.NET訪問SQL Server數(shù)據(jù)源,要快速得多 | System.Data.SqlClient |
| OLE DB.NET | 訪問基于OLE DB協(xié)議構(gòu)建的數(shù)據(jù)源 | System.Data.OleDb |
| Oracle.NET | 訪問Oracle數(shù)據(jù)庫 | System.Data.OracleClient |
| ODBC.NET | 訪問基于ODBC協(xié)議構(gòu)建的數(shù)據(jù)源 | System.Data.Odbc |
表1?主要的.NET數(shù)據(jù)提供程序
?
ADO.NET主要負(fù)責(zé)與數(shù)據(jù)庫服務(wù)器建立連接通道,并基于此連接通道實現(xiàn)從數(shù)據(jù)庫中檢索數(shù)據(jù),并將內(nèi)存中的數(shù)據(jù)回送到數(shù)據(jù)庫以提交更新或?qū)⒃趦?nèi)存中拼寫好的SQL語句提交到數(shù)據(jù)庫服務(wù)器并執(zhí)行以實現(xiàn)某種數(shù)據(jù)操作等等。
?
2??數(shù)據(jù)集
?
數(shù)據(jù)集可以被看作是一個存儲在內(nèi)存中的離線式的數(shù)據(jù)庫,它很像我們最終存儲數(shù)據(jù)的物理數(shù)據(jù)庫,它將很多物理數(shù)據(jù)庫的機(jī)制搬到了內(nèi)存中。
?
ADO.NET的主要部分已經(jīng)在之前的章節(jié)介紹過了,例如:利用SQL Server.NET鏈接SQL Server數(shù)據(jù)庫。本章將主要介紹利用ADO.NET連接Oracle數(shù)據(jù)庫,實現(xiàn)數(shù)據(jù)的存取。ADO.NET的結(jié)構(gòu)如圖1所示。
?
?
圖1? ADO.NET結(jié)構(gòu)圖
?
2.???使用ADO.NET連接Oracle
使用ADO.NET數(shù)據(jù)訪問技術(shù)連接Oracle數(shù)據(jù)庫和連接Sql Server數(shù)據(jù)庫的步驟基本相同:
1.?????????使用Connection對象建立數(shù)據(jù)庫連接。
2.?????????使用Command對象執(zhí)行數(shù)據(jù)庫操作。
3.?????????采用連線或者斷線的方式進(jìn)行數(shù)據(jù)的存取。
4.?????????使用Connection對象的Close方法關(guān)閉數(shù)據(jù)庫連接。
?
連接Sql Server數(shù)據(jù)庫和Oracle數(shù)據(jù)庫所使用的數(shù)據(jù)提供程序是不一樣的,連接Sql Server數(shù)據(jù)庫使用的是SqlServer.NET,包括SqlConnection、SqlCommand等數(shù)據(jù)訪問類。而連接Oracle數(shù)據(jù)庫則使用的是Oracle.NET,包括OracleConnection、OracleCommand等數(shù)據(jù)訪問類,包含在System.Data.OracleClient命名空間下,由于該命名空間默認(rèn)并沒有被添加到項目中來,所以在使用前需要如圖2所示添加響應(yīng)的引用才能使用。
?
圖2??添加System.Data.OracleClient引用
?
案例1:在Oracle數(shù)據(jù)庫中在System用戶下,創(chuàng)建UserInfo表,并插入一定數(shù)據(jù),使用ADO.NET數(shù)據(jù)訪問技術(shù)將UserInfo表中的數(shù)據(jù)檢索出來,并顯示在ASP.NET頁面中。UserInfo表中的數(shù)據(jù)如圖3所示。
?
?
圖2? UserInfo表中數(shù)據(jù)
?
實現(xiàn)步驟:
1.?????????使用OracleConnection對象建立與Oracle之間的連接。
?
代碼演示:建立連接
| //連接字符串 string connectionString = "Data Source=MYORCL;User ID=System;Password=accp;Unicode=True"; //創(chuàng)建Oracle連接對象 OracleConnection con = new OracleConnection(connectionString); //打開連接 con.Open(); |
?
2.?????????創(chuàng)建命令行對象,準(zhǔn)備執(zhí)行檢索數(shù)據(jù)庫操作。
?
代碼演示:建立命令行對象
| //建立Sql查詢語句 string sql = "select * from userinfo"; //創(chuàng)建Oracle命令行對象 OracleCommand cmd = new OracleCommand(sql, con); //執(zhí)行命令行對象 OracleDataReader odr = cmd.ExecuteReader(CommandBehavior.CloseConnection); |
?
3.?????????創(chuàng)建實體類,并遍歷結(jié)果集,將數(shù)據(jù)存放到集合中存儲。
?
代碼演示:創(chuàng)建實體類
| //實體類 public class UserInfo { ??? int userID; ? ??? public int UserID ??? { ??????? get { return userID; } ??????? set { userID = value; } ??? } ??? string userName; ? ??? public string UserName ??? { ??????? get { return userName; } ??????? set { userName = value; } ??? } ??? string userAge; ? ??? public string UserAge ??? { ??????? get { return userAge; } ??????? set { userAge = value; } ?? ?} } |
?
代碼演示:遍歷結(jié)果集
| //遍歷結(jié)果集 IList<UserInfo> users = new List<UserInfo>(); while (odr.Read()) { ??? UserInfo user = new UserInfo(); ??? user.UserID = Convert.ToInt32(odr["UserID"]); ??? user.UserName = Convert.ToString(odr["UserName"]); ??? user.UserAge = Convert.ToString(odr["UserAge"]); ? ??? users.Add(user); } |
?
4.?????????將集合中的數(shù)據(jù)綁定到GridView控件上顯示出來。
?
代碼演示:綁定數(shù)據(jù)
| //綁定DataGridView控件 this.GridView1.DataSource = users; this.GridView1.DataBind(); |
?
根據(jù)上面的操作,不難看出連接Oracle數(shù)據(jù)庫與連接SqlServer數(shù)據(jù)庫除了數(shù)據(jù)提供程序方面有所區(qū)別之外,從操作步驟和實現(xiàn)原理等方面看區(qū)別不大。按照上面步驟操作,在頁面中運行的效果如圖3所示。增刪改操作和檢索操作基本相似,在這里就不再敘述了。
?
圖3??案例效果
?
3.???抽象工廠中加入Oracle
在設(shè)計模式中介紹過抽象工廠設(shè)計模式(Abstract Factory),抽象工廠有四種關(guān)鍵角色:抽象工廠、實體工廠、抽象產(chǎn)品、實體產(chǎn)品。抽象工廠模式實現(xiàn)原理強(qiáng)調(diào)的是對象組合機(jī)制,由在“父工廠”內(nèi)定義不同的“子工廠”對象來負(fù)責(zé)不同的目標(biāo)對象的創(chuàng)建,也就是說利用實體產(chǎn)品由抽象產(chǎn)品來約束,而由實體工廠來創(chuàng)建,實體工廠則由抽象工廠約束,可以有效的發(fā)揮工廠模式管理清晰的優(yōu)點。
?
?????????案例2:采用抽象工廠模式實現(xiàn)在學(xué)員信息管理系統(tǒng)中支持Access、SQLServer以及Oracle三套數(shù)據(jù)庫的切換(以學(xué)員基本信息模塊為例),以學(xué)員基本信息模塊為例給出概要的實現(xiàn),并實現(xiàn)展示所有學(xué)生信息功能。
?
?????????案例分析:本例是抽象工廠課堂案例的延續(xù),需要在項目中多添加一個Oracle數(shù)據(jù)庫,實體產(chǎn)品是數(shù)據(jù)訪問對象,三套數(shù)據(jù)庫相當(dāng)于有三套數(shù)據(jù)庫訪問對象,通過三個實體工廠管理三套數(shù)據(jù)庫訪問對象,最后使用抽象工廠管理三個實體工廠。
實現(xiàn)步驟:
1.?????????在Oracle數(shù)據(jù)庫中使用Sql語句新建Infos表,并添加約束和表數(shù)據(jù),如圖3所示:
?
?
圖3 ?Student表數(shù)據(jù)
2.?????????在VS2008中創(chuàng)建空白解決方案,命名為Test.sln。
3.?????????在解決方案中添加表示層,并添加StudentList.aspx頁面。
4.?????????在解決方案中添加模型層,根據(jù)上面的表結(jié)構(gòu)新建Student.cs實體類。
?
代碼演示:Student類
| public class Student { ??? string stuID; ? ??? public string StuID ??? { ??????? get { return stuID; } ??? ????set { stuID = value; } ??? } ? ??? /** * 其他成員… … */ } |
?
5.?????????在解決方案中添加數(shù)據(jù)訪問層IDAL(抽象產(chǎn)品)。
?
代碼演示:抽象產(chǎn)品
| public interface IStudentService { ??? //獲取所有學(xué)生信息 ??? IList<Student> GetAllStudents(); } |
?
6.?????????在解決方案中添加數(shù)據(jù)訪問層DAL(實體產(chǎn)品),并利用文件夾將不同的實體產(chǎn)品分類,如圖4所示。
?
?
圖4 ?實體產(chǎn)品
?
代碼演示:實體產(chǎn)品
| /// <summary> /// 獲得所有學(xué)生信息 /// </summary> /// <returns>所有學(xué)生信息集合</returns> public IList<Student> GetAllStudents() { ??? //創(chuàng)建SQL語句 ??? string sql = "select * from sys.infos"; ??? //創(chuàng)建泛型集合 ??? IList<Student> students = new List<Student>(); ??? //執(zhí)行SQL語句得到結(jié)果集 ??? OracleDataReader odr = dbh.ExecuteReader(sql); ??? //遍歷結(jié)果集 ??? while(odr.Read()) ??? { ??????? Student student = new Student(); ? ??????? student.StuID = Convert.ToString(odr["StuID"]); ??????? student.StuName = Convert.ToString(odr["StuName"]); ????? ??student.StuAddress = Convert.ToString(odr["StuAddress"]); ??????? student.Seat = Convert.ToInt32(odr["Seat"]); ??????? student.Gender = Convert.ToString(odr["Gender"]); ??????? student.EnRollDate = Convert.ToDateTime(odr["EnRollDate"]); ??????? student.ClassNo = Convert. ToString (odr["ClassNo"]); ??????? //添加到泛型集合 ??????? students.Add(student); ??? } ??? //返回 ??? return students; } |
?
7.?????????在解決方案中添加業(yè)務(wù)邏輯層,命名為StudentManager.cs。
?
代碼演示:BLL層
| /// <summary> /// 獲取所有學(xué)生信息 /// </summary> /// <returns>所有學(xué)生信息集合</returns> public IList<Student> GetAllStudents() { ??? //利用抽象工廠創(chuàng)建實體工廠 ??? Factory factory = Factory.CreateFactory(); ??? //利用工廠創(chuàng)建產(chǎn)品 ??? IStudentService iss = factory.GetStudentService(); ??? return iss.GetAllStudents(); } |
?
8.?????????在解決方案中添加抽象工廠,并添加相應(yīng)實體工廠,如圖5所示。
?
圖5 ?抽象工廠
?
代碼演示:抽象工廠
| //抽象工廠 public abstract class Factory { ??? public static Factory CreateFactory() ??? { ??????? //采用反射技術(shù)得到配置文件中的配置信息 ??????? string factoryType = Config.FactoryType; ??????? Factory factory = ??????????? (Factory)System.Reflection.Assembly.Load("DBFactory").CreateInstance(factoryType); ??????? return factory; ??? } ? ??? //定義子類(實體工廠)的操作規(guī)則 ??? public abstract IStudentService GetStudentService(); } |
?
9.?????????在表示層添加數(shù)據(jù)展示控件,通過設(shè)定屬性綁定數(shù)據(jù)提取方法,實現(xiàn)案例目標(biāo)。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
4.???本章總結(jié)
???ADO.NET是一組用于和數(shù)據(jù)源進(jìn)行交互的面向?qū)ο箢悗旒?#xff0c;它存在于.Net Framework中。通常情況下,數(shù)據(jù)源可以是各種類型的數(shù)據(jù)庫,利用ADO.NET可以訪問目前幾乎所有的主流數(shù)據(jù)庫,如Oracle、SQL Server、DB2、Access等。
???使用ADO.NET技術(shù)訪問數(shù)據(jù)庫的大致步驟如下:
1.?????????使用Connection對象建立數(shù)據(jù)庫連接。
2.?????????使用Command對象執(zhí)行數(shù)據(jù)庫操作。
3.?????????采用連線或者斷線的方式進(jìn)行數(shù)據(jù)的存取。
4.?????????使用Connection對象的Close方法關(guān)閉數(shù)據(jù)庫連接。
???抽象工廠有四種關(guān)鍵角色:抽象工廠、實體工廠、抽象產(chǎn)品、實體產(chǎn)品。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
5.???本章練習(xí)
1.?????????利用本章所學(xué)知識,完成如下功能:
1)?????????在本章完成項目基礎(chǔ)上,繼續(xù)實現(xiàn)對Oracle數(shù)據(jù)庫的增刪改操作。
2)?????????在StudentList.aspx頁面添加查看詳細(xì)鏈接,編寫GetStudentById等方法。
3)?????????在StudentList.aspx頁面中添加刪除鏈接,編寫DeleteStudent等方法。
4)?????????在StudentList.aspx頁面中添加修改鏈接,編寫UpdateStudent等方法。
?
?
章節(jié)知識結(jié)構(gòu)圖
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
附錄
?
?
數(shù)據(jù)庫導(dǎo)入導(dǎo)出
?
?
?
?
?
???????????????????????????????????????????
?
?
| ? | 主要內(nèi)容 |
| ? | ü? 導(dǎo)出 ü? 導(dǎo)入 |
?
?
?
?
?
?
?
?
1.???Oracle導(dǎo)入導(dǎo)出
Oracle的備份是Oracle操作中常見的工作,常見的備份方案有:邏輯備份(IMP&EXP命令進(jìn)行備份)、物理文件備份(脫機(jī)及聯(lián)機(jī)備份)、利用RMAN(Recovery Manager)的增量物理文件系統(tǒng)備份。ORACLE數(shù)據(jù)庫的邏輯備份分為四種模式:表空間備份(tablespace)、表備份(table)、用戶備份(user)和完全備份(full)。Oracle的邏輯備份是使用IMP&EXP命令進(jìn)行數(shù)據(jù)導(dǎo)入導(dǎo)出的操作。使用EXP命令導(dǎo)出或者使用IMP命令導(dǎo)入時,需要Create Session系統(tǒng)權(quán)限,但是如果要導(dǎo)出其他的表,必須擁有權(quán)限:EXP_FULL_DATABASE。
?
調(diào)用導(dǎo)入導(dǎo)出命令時,首先要估計所需的空間。EXP命令導(dǎo)出的文件是二進(jìn)制文件(*.dmp)只能由對應(yīng)的IMP命令進(jìn)行讀取恢復(fù)。導(dǎo)入導(dǎo)出的用途是:
???備份與恢復(fù)
???Oracle平臺更換:可以在相同版本之間進(jìn)行備份與恢復(fù),Oracle較低版本的export數(shù)據(jù)文件可以import到高版本的Oracle數(shù)據(jù)庫中,但是Oracle的版本只能是相鄰的,不能垮版本。
?
2.???EXP導(dǎo)出數(shù)據(jù)
EXP命令可以在交互環(huán)境下導(dǎo)出數(shù)據(jù)庫中的數(shù)據(jù),也可以在非交互環(huán)境下執(zhí)行命令。交互環(huán)境下的命令執(zhí)行,是一步一步執(zhí)行的過程。
?
代碼演示:exp的交互環(huán)境
| D:\>exp scott/tiger@my_orcl? ① Export: Release 10.2.0.3.0 - Production on 星期一 10月 19 17:04:14 2009 Copyright (c) 1982, 2005, Oracle.? All rights reserved. 連接到: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production With the Partitioning, OLAP and Data Mining options 輸入數(shù)組提取緩沖區(qū)大小: 4096 >? ② ?導(dǎo)出文件: EXPDAT.DMP > scott.dmp? ③ (2)U(用戶), 或 (3)T(表): (2)U > 2? ④ 導(dǎo)出權(quán)限 (yes/no): yes > yes? ⑤ 導(dǎo)出表數(shù)據(jù) (yes/no): yes > yes? ⑥ 壓縮區(qū) (yes/no): yes > no? ⑦ 已導(dǎo)出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集 . 正在導(dǎo)出 pre-schema 過程對象和操作 . 正在導(dǎo)出用戶 SCOTT 的外部函數(shù)庫名 . 導(dǎo)出 PUBLIC 類型同義詞 . 正在導(dǎo)出專用類型同義詞 . 正在導(dǎo)出用戶 SCOTT 的對象類型定義 即將導(dǎo)出 SCOTT 的對象... . 正在導(dǎo)出數(shù)據(jù)庫鏈接 . 正在導(dǎo)出序號 . 正在導(dǎo)出簇定義 . 即將導(dǎo)出 SCOTT 的表通過常規(guī)路徑... . . 正在導(dǎo)出表?????????????????????????? BONUS導(dǎo)出了?????????? 0 行 . . 正在導(dǎo)出表??????????????????????????? DEPT導(dǎo)出了??????????? 10 行 . . 正在導(dǎo)出表???????????????????????????? EMP導(dǎo)出了??????????? 14 行 . . 正在導(dǎo)出表??????????????????????? SALGRADE導(dǎo)出了?????????? 5 行 . . 正在導(dǎo)出表????????????????????? TBLSTUDENT導(dǎo)出了?????????? 3 行 . 正在導(dǎo)出同義詞 . 正在導(dǎo)出視圖 . 正在導(dǎo)出存儲過程 . 正在導(dǎo)出運算符 . 正在導(dǎo)出引用完整性約束條件 . 正在導(dǎo)出觸發(fā)器 . 正在導(dǎo)出索引類型 . 正在導(dǎo)出位圖, 功能性索引和可擴(kuò)展索引 . 正在導(dǎo)出后期表活動 . 正在導(dǎo)出實體化視圖 . 正在導(dǎo)出快照日志 . 正在導(dǎo)出作業(yè)隊列 . 正在導(dǎo)出刷新組和子組 . 正在導(dǎo)出維 . 正在導(dǎo)出 post-schema 過程對象和操作 . 正在導(dǎo)出統(tǒng)計信息 成功終止導(dǎo)出, 沒有出現(xiàn)警告。 D:\> |
代碼解析:
①??Exp是導(dǎo)出命令,該命令后面緊跟“用戶名/密碼@服務(wù)器網(wǎng)絡(luò)連接”。
②??Exp程序?qū)С鰰r使用的緩沖區(qū)大小,緩沖區(qū)越大,導(dǎo)出速度越快。直接回車代表使用默認(rèn)值4096B。
③??Exp命令會把所有要到處的數(shù)據(jù)導(dǎo)出到一個Dmp文件中,該步驟是Exp詢問導(dǎo)出的數(shù)據(jù)文件名稱。
④??Exp程序詢問導(dǎo)出整個用戶還是導(dǎo)出某個表。默認(rèn)導(dǎo)出整個用戶。
⑤??Exp程序詢問是否導(dǎo)出每張表的訪問權(quán)限。默認(rèn)導(dǎo)出訪問權(quán)限。
⑥??Exp程序詢問是否導(dǎo)出表中的數(shù)據(jù)。默認(rèn)導(dǎo)出數(shù)據(jù)庫表中的數(shù)據(jù)。
⑦??Oracle表中的數(shù)據(jù)可能來自不同的分區(qū)中的數(shù)據(jù)塊,默認(rèn)導(dǎo)出時會把所有的數(shù)據(jù)壓縮在一個數(shù)據(jù)塊上,IMP導(dǎo)入時,如果不存在連續(xù)一個大數(shù)據(jù)塊,則會導(dǎo)入失敗。
?
也可以使用Exp命令時,設(shè)置各種參數(shù),使準(zhǔn)備就緒的Exp命令不需要與用戶交互,按照參數(shù)的要求,Exp命令會一次性執(zhí)行導(dǎo)出工作。要指定參數(shù),您可以使用關(guān)鍵字:
?
EXP KEYWORD=value?或?KEYWORD=(value1,value2,...,valueN)
?
例如: EXP SCOTT/TIGER GRANTS=Y TABLES=(EMP,DEPT,MGR)
?
| 參數(shù)名 | 說明 |
| USERID | 表示“用戶名/密碼”。 |
| BUFFER | 數(shù)據(jù)緩沖區(qū)大小。以字節(jié)為單位,一般在64000以上。 |
| FILE | 指定輸出文件的路徑和文件名。一般以.dmp為后綴名,注意該文件包括完整路徑,但是路徑必須存在,導(dǎo)出命令不能自動創(chuàng)建路徑。 |
| COMPRESS | 是否壓縮導(dǎo)出,默認(rèn)yes。 |
| GRANTS | 是否導(dǎo)出權(quán)限,默認(rèn)yes |
| INDEXES | 是否導(dǎo)出索引,默認(rèn)yes |
| DIRECT | 是否直接導(dǎo)出,默認(rèn)情況,數(shù)據(jù)先經(jīng)過Oracle的數(shù)據(jù)緩沖區(qū),然后再導(dǎo)出數(shù)據(jù)。 |
| LOG | 指定導(dǎo)出命令的日志所在的日志文件的位置。 |
| ROWS | 是否導(dǎo)出數(shù)據(jù)行,默認(rèn)導(dǎo)出所有數(shù)據(jù)。 |
| CONSTRAINTS | 是否導(dǎo)出表的約束條件,默認(rèn)yes |
| PARFILE | 可以把各種參數(shù)配置為一個文本鍵值形式的文件,該參數(shù)可以指定參數(shù)文件的位置。 |
| TRIGGERS | 是否導(dǎo)出觸發(fā)器,默認(rèn)值是yes。 |
| TABLES | 表的名稱列表,導(dǎo)出多個表可以使用逗號隔開。 |
| TABLESPACES | 導(dǎo)出某一個表空間的數(shù)據(jù)。 |
| Owner | 導(dǎo)出某一用戶的數(shù)據(jù)。 |
| Full | 導(dǎo)出數(shù)據(jù)庫的所有數(shù)據(jù)。默認(rèn)值是no。 |
| QUERY | 把查詢的結(jié)果導(dǎo)出。 |
表1? EXP參數(shù)說明
?
代碼演示:exp的非交互環(huán)境
| D:\>exp scott/tiger file=employee.dmp tables=(emp,dept) Export: Release 10.2.0.3.0 - Production on 星期一 10月 19 17:38:25 2009 Copyright (c) 1982, 2005, Oracle.? All rights reserved. 連接到: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production With the Partitioning, OLAP and Data Mining options 已導(dǎo)出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集 即將導(dǎo)出指定的表通過常規(guī)路徑... . . 正在導(dǎo)出表???????????????????????????? EMP導(dǎo)出了????????? 14 行 . . 正在導(dǎo)出表??????????????????????????? DEPT導(dǎo)出了????????? 10 行 成功終止導(dǎo)出, 沒有出現(xiàn)警告。 D:\> |
?
3.???IMP導(dǎo)入
IMP程序?qū)刖褪前袳xp導(dǎo)出的文件重新導(dǎo)入到數(shù)據(jù)庫的過程。導(dǎo)入時也有一些重要的參數(shù):
???Fromuser:指出導(dǎo)出時dmp文件中記載的用戶信息。
???Touser:dmp文件要導(dǎo)入到什么目標(biāo)用戶中。
???Commit:默認(rèn)是N,在緩沖區(qū)滿時是否需要commit,如果設(shè)為N,需要較大的回滾段。
???Igore: Oracle在恢復(fù)數(shù)據(jù)的過程中,當(dāng)恢復(fù)某個表時,該表已經(jīng)存在,就要根據(jù)ignore參數(shù)的設(shè)置來決定如何操作。若ignore=y,Oracle不執(zhí)行CREATE TABLE語句,直接將數(shù)據(jù)插入到表中,如果插入的記錄違背了約束條件,比如主鍵約束,則出錯的記錄不會插入,但合法的記錄會添加到表中。若ignore=n,Oracle不執(zhí)行CREATE TABLE語句,同時也不會將數(shù)據(jù)插入到表中,而是忽略該表的錯誤,繼續(xù)恢復(fù)下一個表。
?
代碼演示:Imp導(dǎo)入
| D:\>imp system/manager file=employee.dmp fromuser=scott touser=employee commit=y Import: Release 10.2.0.3.0 - Production on 星期一 10月 19 17:54:51 2009 Copyright (c) 1982, 2005, Oracle.? All rights reserved. 連接到: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production With the Partitioning, OLAP and Data Mining options 經(jīng)由常規(guī)路徑由 EXPORT:V10.02.01 創(chuàng)建的導(dǎo)出文件 警告: 這些對象由 SCOTT 導(dǎo)出, 而不是當(dāng)前用戶 已經(jīng)完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的導(dǎo)入 . 正在將 SCOTT 的對象導(dǎo)入到 EMPLOYEE . . 正在導(dǎo)入表?????????????????????????? "EMP"導(dǎo)入了????????? 14 行 . . 正在導(dǎo)入表????????????????????????? "DEPT"導(dǎo)入了????????? 10 行 即將啟用約束條件... 成功終止導(dǎo)入, 沒有出現(xiàn)警告。 D:\> |
?
4.???常見問題
???數(shù)據(jù)庫對象已經(jīng)存在
一般情況,?導(dǎo)入數(shù)據(jù)前應(yīng)該徹底刪除目標(biāo)數(shù)據(jù)下的表,序列,函數(shù)/過程,觸發(fā)器等。
數(shù)據(jù)庫對象已經(jīng)存在,?按缺省的imp參數(shù),則會導(dǎo)入失敗。
如果用了參數(shù)ignore=y,會把exp文件內(nèi)的數(shù)據(jù)內(nèi)容導(dǎo)入。
如果表有唯一關(guān)鍵字的約束條件,不合條件將不被導(dǎo)入。
如果表沒有唯一關(guān)鍵字的約束條件,將引起記錄重復(fù)。
?
???數(shù)據(jù)庫對象有主外鍵約束
不符合主外鍵約束時,數(shù)據(jù)會導(dǎo)入失敗。
解決辦法:?先導(dǎo)入主表,再導(dǎo)入依存表。
disable目標(biāo)導(dǎo)入對象的主外鍵約束,導(dǎo)入數(shù)據(jù)后,再enable它們。
?
???權(quán)限不夠
如果要把A用戶的數(shù)據(jù)導(dǎo)入B用戶下,?A用戶需要有imp_full_database權(quán)限。
?
???導(dǎo)入大表(?大于80M )?時,存儲分配失敗
默認(rèn)的EXP時,compress = Y,也就是把所有的數(shù)據(jù)壓縮在一個數(shù)據(jù)塊上。
導(dǎo)入時,如果不存在連續(xù)一個大數(shù)據(jù)塊,則會導(dǎo)入失敗。
導(dǎo)出80M以上的大表時,記得compress= N,則不會引起這種錯誤。
?
???Imp和Exp使用的字符集不同
如果字符集不同,導(dǎo)入會失敗,可以改變unix環(huán)境變量或者NT注冊表里NLS_LANG相關(guān)信息。
?
???Imp和Exp版本不能往上兼容
Imp可以成功導(dǎo)入低版本Exp生成的文件,?不能導(dǎo)入高版本Exp生成的文件根據(jù)情況我們可以用。
?
?[D1]/?'str?kt??/ /'kw?r?/
?[D2]/,d?f?'n???n?/
?[D3]m??nipju?lei??n
?[D4]k?n?streint
?[D5]在創(chuàng)建數(shù)據(jù)庫表時可以指定一個?DEFAULT?值(即默認(rèn)值)。對數(shù)據(jù)庫字段使用默認(rèn)值有助于將數(shù)據(jù)庫設(shè)計問題與應(yīng)用程序代碼隔離。
可以在以后某個時候通過一條?ALTER TABLE?命令改變一個字段的默認(rèn)值,改變之后應(yīng)用程序代碼會立即開始使用新值。
有一點是很重要的,即?DEFAULT?值只有當(dāng)一個字段沒有在?INSERT?或?MERGE?中指定值,或者使用了?DEFAULT?關(guān)鍵字時才會使用。如果你不顯式地聲明一個?DEFULAT?值,Oracle?將隱式地將默認(rèn)值定義為?NULL,而且?DEFAULT?關(guān)鍵字也是這樣。從?Oracle 9i開始,可以在?DEFAULT?子句中使用諸如?SYSDATE?或?CURRENT_TIMESTAMPE?之類的偽字段。
?[D6]主鍵約束:在表中定義一個主鍵來唯一確定表中每一行數(shù)據(jù)的標(biāo)識符。數(shù)據(jù)類型不限,但此列必須是唯一并且非空。
?[D7]CHECK?約束:定義列中可接受的數(shù)據(jù)值??梢詫?CHECK?約束應(yīng)用于多個列,也可以將多個?CHECK?約束應(yīng)用于單個列。當(dāng)除去某個表時,也將除去?CHECK?約束
?[D8]唯一約束保證在一個字段或者一組字段里的數(shù)據(jù)與表中其它行的數(shù)據(jù)相比是唯一的。
?[D9]可在創(chuàng)建字段之后CONSTRAINT PK_INFOS PRIMARY KEY (STUID)
?[D10]升序:ASC
??????????降序:DESC
?[D11]/tr???keit/v.??切去頭端, 截棱成平面, 縮短
?
?[D12]escape關(guān)鍵字經(jīng)常用于使某些特殊字符,如通配符'%','_'轉(zhuǎn)義為它們原來的字符的意義,被定義的轉(zhuǎn)義字符通常使用'\',但是也可以使用其他的符號。?[D13]/,?nt?'s?kt/
?[D14]/'ma?n?s/減去,負(fù)的
總結(jié)
以上是生活随笔為你收集整理的《Oracle经典教程》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python输出CSV乱码
- 下一篇: 流程图制作用这些软件,操作容易好上手