Oracle Database-基礎及查詢部分
Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關係數據庫管理系統。它是在數據庫領域一直處於領先地位的產品。能夠說Oracle數據庫系統是目前世界上流行的關係數據庫管理系統,系統可移植性好、使用方便、功能強,適用於各種大、中、小、微機環境。它是一種高效率、可靠性好的 適應高吞吐量的數據庫解決方案。
基本概念
一個Oracle服務器
- 是一個數據管理系統(RDBMS),提供開放的,全面的,近乎完整的信息管理
- 由一個Oracle數據庫和多個Oracle實例組成
- 數據庫對應物理上的文件存在,將數據庫文件讀取到內存中就成爲了實例
- 操做Oracle數據庫即經過操做實例來完成
- 數據庫與實例能夠爲一對一或一對多,若爲一對多,即稱集羣(cluster)
Oracle的體系結構
若爲一階段提交:
Database 數據庫
- Oracle數據庫是數據的物理存儲,包括數據文件ORA或DBF、控制文件(CTL)、聯機日誌和參數文件
- Oracle數據庫的概念與MySQL有所不一樣,一個操做系統只能由一個庫
Instance 實例
- 一個Oracle實例(Oracle Instance)又一系列的後臺進程和內存結構組成,一個數據庫能夠有多個實例
數據文件(dbf)
- 數據文件是數據庫的物理存儲單位,數據庫的數據是表面上存儲在表空間中的,其實是在某一個或多個數據文件中存放
- 一個表空間能夠由一個或多個數據文件組成
- 一個數據文件只能屬於一個表空間
- 一旦數據文件被加入到某個表空間後,就不能夠刪除這個文件,若是要上出這個文件必須先刪除其所屬表空間
表空間
- 表空間是Oracle對物理數據庫上的相關數據文件(ORA或DBF文件)的邏輯映射,一個數據庫在邏輯上被劃分爲一到若干個表空間,每一個表空間包含了在邏輯上相關聯的一組結構
- 每一個數據庫至少有一個表空間
- 每一個表空間由同一磁盤上的一個或多個文件組成,這些文件稱數據文件(datafile)
- 一個數據文件只能屬於一個表空間
-
-
表空間爲邏輯概念,數據文件爲物理概念
用戶
- 用戶實在實例下創建的,不一樣的實例中能夠建立相同名稱的用戶
- 表中的數據是由用戶放入某一個表空間的,而這個表空間會隨機把這些表數據放到一個或者多個數據文件中
- Oracle數據庫不是普通的概念,Oracle是由用戶和表空間對數據進行管理和存放的,但表不是由表空間去查詢二十由用戶來查詢的,故不一樣用戶能夠在同一個表空間創建同一個名字的表,這個表就是由建表用戶來區分了
SCOTT用戶和HR用戶
基本查詢
更改某行SQL語句
- 使用【edit/ed】命令,將自動用編輯器打開上一條執行的sql語句
SQL中的空值(null)問題
此處介紹兩個函數
- nvl(a,b):當a爲null時返回b
- nvl2(a,b)
查詢結果顯示格式
關於別名
三種方式都可以(【列名 as "xx"】或【列名 "xx"】或【列名 xx】)
加as和不加as徹底沒有區別,只是省略了as關鍵字
而加雙引號和不加雙引號有區別:具體在於不加雙引號只能填寫連續的別名,若中間有空格,則認爲別名已經結束,從而會把空格後的別名看成SQL語句的關鍵字來執行(通常會報關鍵字錯誤),中間有逗號等等同理,用
數字來道別名的話也要加雙引號
注意:單引號表示字符串
DISTINCT關鍵字
用於去重
若distinct關鍵字的位置如:
則去重做用於後面的
全部列,只要這些列組合起來是不相同的,則認爲不是重複的
僞表和僞列
Oracle中提供dual表等做爲僞表,用於適應SQL99標準的select語句中必須有from關鍵字,而僞表則僅僅是爲知足須要from關鍵字的要求,自己無心義
僞列同理
鏈接符||和concat函數
至關於Java中的'+'用於鏈接字符串
數據庫中的字符串
- 字符串能夠是SELECT列表中的一個字符,數字,日期
- 日期和字符只能在單引號中出現,雙引號表示列的別名
- 每當返回一行時,字符串被輸出一次
spool語句
Oracle提供的錄屏功能,能把本次命令行的全部輸入輸出轉存成一個文本文件
SQL和SQL*Plus
SQL
- 一種語言
- ANSI 標準
- 關鍵字不能縮寫
- 使用語句控制數據庫中的表的定義信息和表中的數據
SQL*Plus
- 一種環境
- Oracle 的特性之一
- 關鍵字能夠縮寫
- 命令不能改變數據庫中的數據的值
- 集中運行
區分SQL與SQLPlus命令的方法就是看這個命令
是否能夠縮寫
iSQL*Plus
使用iSQL*Plus能夠:
iSQL*Plus至關於網頁版的SQL*Plus
條件查詢和排序
條件查詢(過濾)
字符和日期
- 字符和日期要包含在單引號中
- 字符大小寫敏感(而MySQL不區分大小寫),日期格式敏感
- 默認的日期格式時DD-MON-RR
能夠修改日期的格式:
先查詢當前日期格式:select * from v$nls_parameters;
而後能夠經過alter修改參數的值
若僅對當前會話生效:alter session set NLS_DATE_FORMAT='yyyy-mm-dd';
若對全局生效:alter system
set NLS_DATE_FORMAT='yyyy-mm-dd';
比較運算
賦值使用'='
BETWEEN AND
IN
LIKE
在模糊查詢中,可使用ESCAPE標識符選擇‘%’和‘_’符號
若查詢條件中有下劃線做,則使用轉義字符'\'將下劃線轉義成字符串而不是標識符
轉義字符須要用escape關鍵字聲名:
邏輯運算
運算符的優先級
ORDER BY子句
序號從1開始
單個列排序
使用ORDER BY來排序
- ASC(ascend):升序
- DESC(descend):降序
ORDER BY 子句在SELECT語句的
結尾
降序以下
多個列排序
若須要降序排序,則在須要降序的列名後加desc關鍵字,若須要所有列都按降序排序,則須要在所有列名後加desc
排序的規則
- 能夠按照select語句中的列名排序
- 能夠按照別名列名排序
- 能夠按照select語句中的列名的順序值排序
- 若是要按照多列進行排序,則規則是先按照第一列排序,若是相同,則按照第二列排序;以此類推
考慮空值null的排序
默認升序時空值排最後,而降序時空值排最前,能夠加nulls last關鍵字來使空值在降序時仍然排在最後
函數
SQL函數的概念
兩種SQL函數
單行函數
這部分只列出了經常使用的函數,其餘函數見Oracle官方文檔
- 操做數據對象
- 接受參數返回一個結果
- 只對一行進行變換
- 每行返回一個結果
- 能夠轉換數據類型
- 能夠嵌套
- 參數能夠是一列或一個值
- 使用函數時函數名對大小寫不敏感
單行函數分爲五大類型(另外能夠說條件表達式是第六種單行函數)
字符函數
大小寫控制函數
用於改變字符的大小寫
示例:
字符控制函數
注意下表由1開始(而不是0)
數值函數
日期函數
- Oracle中的日期型數據類型(date類型)實際含有兩個值(而MySql有date-日期和datetime-日期時間兩種表示日期的數據類型): 日期和時間
- date=日期+時間
- 使用select sysdate from dual來查看當前時間
- 默認的日期格式是DD-MON-RR
日期的運算
- 在日期上加上或減去一個數字結果仍爲日期,直接加減單位是天
- 兩個日期相減返回日期之間相差的天數,兩個日期之間不能夠相加
- 能夠用數字除24來向日期中加上或減去小時
MONTHS_BETWEEN函數
NEXT_DAY函數
ROUND函數和TRUNC函數應用到日期
轉換函數(數據類型轉換)
隱式轉換
Oracle自動完成如下轉換
顯式轉換
TO_CHAR 函數對日期的轉換
格式
- 必須包含在單引號中並且大小寫敏感。
- 能夠包含任意的有效的日期格式。
- 日期之間用逗號隔開。
若精確到分秒,使用hh24或12:mi:ss
TO_CHAR 函數對數字的轉換
經常使用格式
示例:
TO_NUMBER 和TO_DATE 函數
通用函數
這些函數適用於
任何數據類型,同時也適用於空值
- NVL(expr1, expr2)
- NVL2(expr1,expr2,expr3):是NVL函數的加強
- NULLIF(expr1,expr2)
- COALESCE(expr1,expr2, ... ,exprn):可變參數
條件表達式
在SQL語句中使用IF-THEN-ELSE 邏輯能夠
使用兩種方法
- CASE表達式:SQL99的語法,相似Basic,比較繁瑣
- DECODE函數:Oracle本身的語法,相似Java,比較簡潔
CASE表達式
示例:
注意:這個表達式不會修改原來的值
DECODE函數
示例:
另外,條件表達式也適用於範圍條件
函數能夠嵌套使用
單行函數能夠嵌套,執行順序
由內到外
多行函數(或稱組函數、分組函數)
多行函數做用於多行數據,並對多行數據返回一個值
多行函數語法
經常使用的多行函數
- AVG:平均值
- COUNT:計數
- MAX:最大值
- MIN:最小值
- SUM:求和
COUNT(計數)函數
也可使用distinct關鍵字返回非空且不重複的記錄數
多行函數與空值
多行函數將忽略空值
可使用嵌套nvl函數來使多行函數對空值有效,以下
分組數據(GROUP BY)
語法
可使用GROUP BY子句將表中的數據分紅若干組
使用GRUOP BY子句的基本要求
在SELECT列表中全部未包含在多行函數中的列都應該包含在GROUP BY子句中
包含在GROUP BY子句中的列沒必要包含在SELECT列表中
非法使用示例
多個列分組
在GRUOP BY子句中包含多個列就能夠按照多個列分組
先按照第一個列分組,再按照第二個列分組,以此類推
過濾分組數據
HAVING子句
- 行已經被分組。
- 使用了組函數。
- 知足HAVING 子句中條件的分組將被顯示
使用注意
- 不能在WHERE子句中使用多行函數
- 能夠在HAVING子句中使用多行函數
GROUP BY語句的加強
結果分別是下列三條select語句的查詢結果組合
至關於下面這條語句
是爲
GROUP BY語句的加強
rollup函數的做用:
ROLLUP(A,B)
圖中結果有調整過格式,使用break on deptno skip 2就能夠調整格式了,若要取消,則使用break on null既能夠還原原來的格式了
多表查詢
笛卡爾積
笛卡爾積是兩(多)張表的簡單相乘,而多表查詢的目的的就是從笛卡爾積中查詢出正確的、對應的數據結果
而查詢出正確的數據結果的根據是鏈接條件,如上表的鏈接條件是deptno部門號
因此多表查詢便是在笛卡爾全積中根據鏈接條件查詢出正確的數據結果
鏈接條件至少有N-1個,N是表的個數
Oracle中鏈接條件的類型
Oracle中,根據鏈接條件的不一樣,分爲如下幾個類型
SQL99標準中的鏈接類型
- Cross joins
- Natural joins
- Using clause
- Full or two sided outer joins
不一樣類型的鏈接條件多表查詢的基本語法和做用
等值鏈接
不等值鏈接
外鏈接
- 使用外鏈接能夠查詢不知足鏈接條件的數據。
- 外鏈接的符號是"(+)"
右外鏈接語法
當等值條件不成立時,
等號右邊的列數據仍然被包含在查詢結果中
左外鏈接語法
當等值條件不成立時,
等號左邊的列數據
仍然被包含在查詢結果中
示例:
若按照簡單等值查詢,則會丟失沒有員工的OPERATIONS部門的記錄,應該使用外鏈接查詢
此處爲右外鏈接,相對地,左外鏈接應該在
自鏈接
即
單個表做爲
兩個表來鏈接
示例:
自鏈接查詢多表的缺陷
自鏈接查詢多表的笛卡爾積記錄數是這個表記錄數的平方,查詢記錄數龐大的表時,就會獲得龐大的笛卡爾積,形成性能浪費
因此自鏈接不適合操做大表,要避免龐大的笛卡爾積或者說避免笛卡爾積的出現,可使用層次查詢
*層次查詢
層次查詢其實是單表查詢,避免了笛卡爾積的出現
示例:
員工與經理的層次關係以下
層次查詢的語法
遍歷這棵層次樹須要有起始節點,以下
若起始節點爲根節點,能夠這樣書寫
具體以下
Oracle還提供了
僞列之一 level來表示層級
故查詢語句以下
查詢結果以下
SQL99標準中的鏈接類型
自查,附件pdf
多表查詢的注意事項
- 在WHERE字句中寫入鏈接條件。
- 在表中有相同列時,在列名以前加上表名前綴
- 在不一樣表中具備相同列名的列能夠用表的別名加以區分
使用表的別名
注意:若是使用了表的別名,則不能再使用表的真名
子查詢
子查詢又叫內查詢,相對的,主查詢也成爲外查詢
- 子查詢(內查詢) 在主查詢以前一次執行完成
- 子查詢的結果被主查詢使用(外查詢)
- 更多詳細示例見附件pdf(day02)
子查詢語法
示例:
子查詢使用細節
注意事項
- 子查詢要包含在括號內
- 將子查詢放在比較條件的右側
- 單行操做符對應單行子查詢,多行操做符對應多行子查詢
- 有必定的SQL語句格式便於閱讀
- 不能夠在GROUP BY子句後使用子查詢
- 主查詢和子查詢能夠是分別查詢兩(多)張不一樣的表
- 須要知足子查詢返回的結果主查詢可使用便可
- 通常不在子查詢中排序
- 在top-n分析問題中必須在子查詢中排序,關於top-n問題,見下文拓展內容
- 一般先執行子查詢,在執行主查詢
- 特殊狀況:在相關子查詢中有可能先執行主查詢再執行子查詢
- 子查詢的空值問題
- 當子查詢和多表查詢能夠獲得相同的結果時,儘可能使用多表查詢
子查詢能夠用於
- where關鍵字後
- select關鍵字後
- 須要子查詢返回一行數據,即子查詢應該是一個單行子查詢,若返回多行數據則報錯
- having關鍵字後
- from關鍵字後(特殊)
▲在FROM關鍵字後使用子查詢
子查詢返回的結果至關於一個新的表,把它看做一張獨立的表做查詢便可
利用在FROM關鍵字後加上子查詢能夠在現有查詢條件的基礎上增長更多的查詢條件
子查詢類型
單行子查詢
在HAVING子句後使用子查詢中
- 首先執行子查詢。
- 向主查詢中的HAVING子句返回結果
在SELECT關鍵字後使用單行子查詢
非法使用單行子查詢
單行子查詢中的空值問題
多行子查詢
- 返回多行記錄
- 使用多行比較操做符
- 若使用NOT IN操做符,則表中不能有空值,如有空值,則查詢將返回空值
- 若必定要使用NOT IN操做符,須要手動使用is not null來過濾掉空值記錄
在多行子查詢中使用ANY操做符
查詢SALES部門和ACCOUNTING部門的員工信息
兩種方式:
1.使用ANY關鍵字
2.使用IN關鍵字,可知"IN"至關於"= ANY"
在多行子查詢中使用ALL操做符
多行子查詢中的空值問題
正確解決方法以下
集合運算
語法示例:
集合運算符
並集
UNION
UINON ALL
交集
差集
集合運算中的注意事項
- select語句中參數類型和個數(即列的個數)要一致
- 若不一致,通常能夠按須要補上類型同樣的空值來符合這個語法
- 可使用括號改變集合執行的順序
- 若是有order by子句,必須放到最後一句查詢語句後
- 集合運算採用第一個語句的表頭做爲表頭
Oracle查詢拓展內容
SQL語句的優化要點
- 儘可能使用列名來查詢(用select 列名1,列名2,... 來代替select *)
- where 條件1 and 條件2,應該把常常返回假的條件放在右邊
- 由於where解析順序是從右到左,如有一個爲假則全爲假(至關與Java的&&)
- 同理,where 條件1 or 條件2,應該把常常返回真的條件放在右邊
- 當使用where子句或having子句均可以獲得結果時,儘可能使用where子句來完成查詢
- 由於where是先篩選後分組,having是先分組後篩選(對沒必要要的數據進行了分組)
- 當子查詢和多表查詢能夠獲得相同的結果時,儘可能使用多表查詢
- 由於子查詢會訪問兩(多)次數據庫
- 實際上Oracle中使用子查詢語句不少時候會被Oracle自動轉換成多表查詢
- 儘可能不要使用集合運算,參與集合的查詢越多,耗費性能越嚴重
若須要查看SQL執行的時間,可使用"set timing on"命令來打開顯示執行時間的配置,"set timing off"關閉
關於空值
判斷一個值是否爲空值(null)不能直接使用邏輯運算符,而應該使用is not null/is null關鍵字,詳細內容自查網絡博客
- 若是null參與算術運算,則該算術表達式的值爲null(例如:+,-,*,/ 加減乘除)
- 若是null參與比較運算,則結果不管如何將爲false(例如:>=,<=,<> 大於,小於,不等於)
- 若是null參與彙集運算,則彙集函數都置爲null。除count(*)以外
- 若是在not in子查詢中有null值的時候,則不會返回數據
SQL執行計劃
例題
TOP-N問題
如:
解:
按照工資排序,
使用ROWNUM(行號)僞列來只查詢前三個
由於子查詢的結果至關於一張表,再對已經這張排序的表進行查詢就能夠按照sal來排序行號了
關於ROWNUM行號的要點
- 行號永遠按照默認的順序生成
- 關於行號的默認排序
- Oracle中有三種表:標準表、索引表和臨時表
- 臨時表能夠被手動建立,也能夠被Oracle自動建立
- 當查詢語句中有排序操做時,會建立臨時表做爲排序後的表來顯示,故(子)查詢其實至關於建立了一張新的表
- 當事務或會話結束的時候,表和表中的數據自動刪除
- 關於行號的過濾條件只能使用"<"、"<=",不可使用">"、">="
- 那麼分頁就須要在外面嵌套一個外查詢並在其中中定義分頁條件了
- 如:須要查詢行號爲5到8的數據
- 此時r再也不是行號僞列,而是子查詢中的」真列「,故不須要在乎不可使用大於條件這條規則了、
相關子查詢
如:
解1:這種方法沒有使用相關子查詢
關鍵在於將子查詢看做是一張表,爲其定義別名並添加部門號相等的條件
解2:使用相關子查詢,且注意用子查詢結果做爲列
行轉列
多行函數wm_concat(varchar2)