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