Oracle高级SQL培训与讲解
1?????? With子句
1.1???? 學習目標
掌握with子句用法,并且了解with子句能夠提高查詢效率的原因。
1.2???? With子句要點
1.?? with子句的返回結果存到用戶的臨時表空間中,只做一次查詢,反復使用,提高效率。
2.?? 如果定義了with子句,而在查詢中不使用,那么會報ora-32035 錯誤:未引用在with子句中定義的查詢名。
3.?? 前面的with子句定義的查詢在后面的with子句中可以使用。但是一個with子句內部不能
嵌套with子句。
4.?? 當一個查詢塊名字和一個表名或其他的對象相同時,解析器從內向外搜索,優先使用子查詢塊名字。
5.???????? with查詢的結果列有別名,引用的時候必須使用別名或*。
6.???????? with有可能影響執行計劃。
1.3???? with子句語法
With alias_name as (select1), --as和select中的括號都不能省略
alias_name2 as (select2),--后面的沒有with,逗號分割,同一個主查詢同級別地方,with子
查詢只能定義一次
…
alias_namen as (select n) –與下面的實際查詢之間沒有逗號
Select ….
1.4????? with使用例子:
1.?? 最簡單的使用方法:
如查詢部門名稱包含“A”的所有員工信息
--with clause
with a as
(select deptno from dept where dname like '%A%')
select * from emp where deptno in (select * from a);
with a as
(select deptno from dept where dname like '%A%'),--a結果集
a2 as(select * from a where deptno>20)--a1結果集直接從a中篩選
select * from emp where deptno in (select * from a2);
?
2.?? 多層同級只能用一個with,并且后面的結果集可以使用前面的結果集:
查詢部門名稱包含“A”并且部門編號大于20的所有員工信息
with a as
(select deptno from dept where dname like '%A%'),--a結果集
a2 as(select * from a where deptno>20)--a1結果集直接從a中篩選
select * from emp where deptno in (select * from a2);
?
3.?? 不同級查詢可以使用多個with:
查詢部門名稱包含“A”并且部門編號大于20的所有員工信息的另外一種實現方式如下
with a as
(select deptno from dept where dname like '%A%')--a結果集
select * from emp where deptno in (--括號內層作為子查詢,為第二級
with a2 as(select * from a where deptno>20)--a1結果集直接從a中篩選
select * from a2
);
1.5???? 使用場景
那什么情況下能使用到with子句呢?以下我就舉幾個簡單的例子,簡單的說明以下:
1.???????? 我想測試一句sql,而我不想專門建立一個測試表:
我想測試成績大于90的學生,我不想建立學生表,可以用到with子句
with stu as(
select '張娜' sname,99 score from dual union
select '王杰' ,35? from dual union
select '宋麗' ,85? from dual union
select '陳曉' ,73? from dual union
select '李元' ,100? from dual
)--with 組成一個臨時的結果集,存放在用戶的臨時表空間
select? * from stu where score>90
2.???????? 當一個sql重復用到某個相同的結果集作為子查詢:
--查詢銷售部工資>1500或者銷售部工資小于1000的員工
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal >1500
union all
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal <1000
--以上sql select deptno from dept where dname ='SALES'需要執行兩次,影響效率
--可以使用with優化一下
with salno as(select deptno from dept where dname ='SALES')
select * from emp where deptno=(select * from salno) and sal >1500
union all
select * from emp where deptno=(select * from salno) and sal <1000
2?????? 集合操作
2.1???? 學習目標
掌握union,union all,minus,intersect的使用,能夠描述集合運算,了解內部運行原理。
2.2???? 要點
Union all 效率一般比union高。Union all內部不做排序工作,也不做剔除
重復行工作,而union則做這個工作。所以當數據量比較大的時候,能用union all的時候盡量用union all。除了union all 默認不做排序和剔除重復行的操作外,
union,minus,intersect都默認按第1個查詢結果的第1列進行升序排列,并且
不包含重復行。
2.3???? 語法
(select? resource 1)
Union/union all/minus/intersect
(select? resource 2)
Union/union all/minus/intersect
(select? resource 3)
……….
其中查詢結果集的各個字段的類型能夠互相兼容,并且總的結果集字段名與第一個結果集相同。
2.4???? 使用案例
數據準備:
create table t1 as select rownum rn from dual connect by rownum<7;
create table t2 as select rownum+3 rn from dual connect by rownum<7;
?????????????????
1.???????? 查詢t1和t2表的所有記錄,不去除重復。
2.???????? 查詢t1和t2表的所有記錄,去除重復。
3.???????? 查詢t1和t2表都存在的記錄
4.???????? 查詢t1表存在,t2表不存在的記錄
5.???????? 排序操作:
6.???????? 除了union all其他的全部會在總的結果集中剔除重復,例如:
insert into t1 values(1);
commit;
現在t1表中有兩條相同的記錄,其rn的值為1。
在進行集合運算時重復的記錄被剔除:
2.5???? 使用場景
當要對多個結果集進行集合操作時,可是使用集合操作。
3?????? case與decode
3.1???? 學習目標
會使用case表達式和decode函數,理解各個參數和返回值的含義。
3.2???? 要點
Case表達式:
1.???????? When后面的表達式類型應該全部保持一致,返回值類型也必須保持一致,或者能夠進行隱式轉換。
2.???????? case 表達式 when 值,如果值是null,就算表達式也是null,結果也是返回false。也就是case 后面的表達式如果值為null,不會與when null 匹配,只會與else 匹配。
Decode函數的使用方法與case when相似,但是decode只能用等號匹配。
3.3???? 語法
Case表達式第一種:
case exp when comexp then returnvalue
..when comexp then returnvalue
Else
Returnvalue
End
Case表達式第二種:
case when Boolean then returnvalue
..when Boolean then return value
Else
Returnvalue
End
Decode函數:
decode(exp,
value1,res1,
value2,res2,….,
valuen resn,
elsevalue)。
3.4???? 使用案例
Case 第一種用法:
Case 第二種用法:
Decode用法:
上文提到過null,碰到null的時候要注意,比如:
這種情況可以這樣處理:
如果用decode函數:
3.5???? 使用場景
當我們的sql要求根據不同的條件返回不同的值時,可以使用。
4?????? exists與in、not exists與not in
4.1???? 學習目標
掌握exists與in的、not exists與not in的用法,了解其內部的執行順序 與執行原理,知道什么情況下用exists,什么情況下用in。
4.2???? 要點
1.???????? Exists 用于只能用于子查詢,可以替代in,若匹配到結果,則退出內部
查詢,并將條件標志為true,傳回全部結果資料。
2.???????? 若子查詢結果集比較小,優先使用in,若外層查詢比子查詢小,優先使用exists。因為若用in,則oracle 會優先查詢子查詢,然后匹配外層查詢,若使用exists,則oracle 會優先查詢外層表,然后再與內層表匹配。最優化匹配原則,拿最小記錄匹配大記錄。
4.3???? 語法
In:Select select_fields from table_name where field_name in(select clause);
Exists:Select select_fields from table_name exists (select clause)
4.4???? 使用案例
查詢員工部門編號在部門表中存在的員工記錄:
以上語句可以用Exist替換:
另外not in和not exists在某些情況下也可以相互轉換,但是要注意一點,not in中的子查詢返回的結果集包含null值的時候,查詢會失效。例如我想查詢對應員工記錄數為0的部門。如下:
用not exists:
以上語句不能用not in替換:
查詢失效無記錄返回。注意這并不是oracle的bug,因為在oracle中null不表示空,而是表示未知,當使用not in的時候,如果子查詢返回的結果集中包含null值,我們并不知道外層查詢的記錄在不在子查詢返回的結果集之內,所以無記錄返回。雖然這樣,但是并不表示not in和not exists是完全不可以轉換的,比如子查詢所選的字段在對應的表中沒有null值,這時not in和not exists是可以相互轉換的。或者在某些情況下內層子查詢加上field_name is not null限制條件也是可以的。
4.5???? 使用場景
當內層查詢返回的結果集較小時,用in 或者not in效率較高。當內層子查詢返回的結果集比較大時,用exists或者not exists執行的效率較高。
5?????? 行列互換
5.1???? 學習目標
掌握列轉行技術和常用的行專列技術。
5.2???? 要點
行專列的情況有多種,不同的情況側重點也不一樣。
5.3???? 語法
5.4???? 使用案例
1.???????? 列轉行
第一種方法:需要用到union或者union all:
第二種方法:用到model
2.???????? 行專列,如我有escore表用來記錄每個學生每個科目的成績,如下:
如果我想將每個學生的成績統計在一行上,如:
3 語文 11 數學 55 英語 66
則我可以使用如下sql:
這個sql表面上看沒什么問題,但是仔細看一下三個結果集es、ys和ss,他們來源于同一個表,而且查詢方法也類似,都是根據type的值去篩選的,這樣就會對escore表查詢三遍,嚴重影響查詢速率,那這個sql我們如何去優化呢!
首先在你的腦海里面要有一種思路,根據需求,原先每個學生成績有多行記錄,現在要顯示到一行上,那一般情況下我們是需要根據學生分組的。所以group by sid 這個是一定要有的,既然分組那我們可是使用oracle的聚合函數去求其他行的數據。至于科目字段目前都是已知的,也就是第2,4,6列顯示的分別是英語、語文、數學這幾個字,是常量,我們不用去考慮,那剩下的也就是最關鍵的,我們去求三科的成績就可以了。
讓我們再看一下escore表,當指針移到某一行數據時,當type=e時,我們就取到score,加到第三列上,那第五列和第七列就加0,也就是sum(decode(type,’e’,score,0)),其他列類似,這樣group by時用到的聚合函數還有decode結合在一起使用,就可以完成我們的要求了,sql寫出來時這樣的:
3.???????? 字符串組合的多行轉一列,例如我有一張測試表如下:
我想根據id分組,將每一行的name連接起來,如下圖是我想要的結果:
這種行轉列不是真正意義的行轉列,是多行數據的值拼接后顯示到一列上,那這種情況怎么處理呢,首先分析一下:多行id相同的值轉換成一行,一般情況下需要用到group by,但是對于字符串,oracle中沒有一個聚合函數適合用到此處的字符串連接,那該怎么辦呢?
在oracle中,有sys_connect_by_path(field_name,concat_value)函數,可以通過connect by來依次連接每一行的數據,connect by 的語法是這樣的:
start with field1=1--以當前表達式返回true的行開始
connect by prior field2=field3--通過當前行查找下一行,也就是說某一行數據的field3字段等于當前行的field2,那就把這行數據作為下一行
??? 有了這個思路,我們就可以用connect by 通過使用sys_connect_by_path(field_name,concat_value)這個函數,并且根據id分組,將字符串連接在一起,然后通過max聚合函數,選出每組最長的字符轉就可以了,那剩下的也就是最關鍵的問題就是我怎樣去使用connect by,通過當前行找到下一行呢?充分發散一下你的思維,看一下如下結果集:
那我下一步用如下思路使用connect by將所要的結果查詢上來:
start with? lg is null--以lg為null的行作為起始行
connect by prior rn=lg and prior id=id --當前行與其他行比較,滿足這個條件的就作為下一行數據?????
總的查詢結果如下:
其實怎么使用connect by 方法很多,例如如下sql也能完成:
5.5???? 使用場景
當開發過程中,需要我們將多列轉換成多行或者將多行轉換成多列的時候,就需要用到行列轉換,要根據不同的情況確定不同的結果方案,典型的行列轉換就這幾種,還有一種比較復雜的是不定不定行專列,不定行轉列需要用到oracle的package,在次先不做講解。
6?????? merge into
6.1???? 學習目標
掌握merge into,學會使用merger into批量處理數據。
6.2???? 要點
1.???????? MERGE語句是Oracle9i新增的語法,用來合并UPDATE和INSERT語句。
2.???????? 過MERGE語句,根據一張表或子查詢的連接條件對另外一張表進行查詢,連接條件匹配上的進行UPDATE,無法匹配的執行INSERT。
3.???????? 這個語法僅需要一次全表掃描就完成了全部工作,執行效率要高于INSERT+UPDATE。
6.3???? 語法
MERGE [INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
6.4???? 使用案例
1.???????? 基于escore表創建escore2表,英語成績每個同學加上5分的課時分,新增政治成績,如下:
create table escore2 as select sid,type,score+5 score from escore where type='e'
insert into escore2 values(1,'z',31);
insert into escore2 values(2,'z',45);
insert into escore2 values(3,'z',66);
insert into escore2 values(4,'z',76);
commit;
根據escore2表更新escore表,根據sid和type匹配,對于已經存在的記錄進行更新操作,對于不存在的記錄進行插入操作。
merge into escore t
using escore2 t2--此處可以是表、視圖和查詢結果集
on (t.sid=t2.sid and t.type=t2.type)--匹配條件,需要加括號
when matched then
update set t.score=nvl(t2.score,decode(t.type,'e',5,0))--根據匹配條件,更新escore
when not matched then
insert values(t2.sid,t2.type,t2.score)--無匹配條件的記錄,插入新記錄
執行merge以后的escore表如下:
注意update的時候不能修改匹配的連接字段,否則就會報錯。
6.5???? 使用場景
當要依賴別的表、視圖或者結果集批量修改和插入目標表數據時,可以使用此方法,運行速率快,而且簡單。
7?????? group by高級特性
7.1???? 學習目標
學會使用group by語句,學會使用group by輸出小計、合計。
7.2???? 要點
1.???????? 在select?語句中可以使用group?by?子句將行劃分成較小的組,然后,使用聚合函數返回每一個組的匯總信息。
2.???????? 可以使用having子句限制返回的結果集。
3.???????? 在帶有group?by?子句的查詢語句中,在select?列表中指定的列要么是group?by?子句中指定的列,要么包含聚組函數語法。
4.???????? 使用rollup操作符產生subtotal(小計)的值,cube 操作符產生cross-tabulation(列聯交叉表)的值。
5.???????? 使用grouping函數標識通過rollup和cube 建立的行的值。
6.???????? 使用grouping sets產生一個single result set(結果集)。
7.???????? 使用grouping_id和group_id函數。
7.3???? 使用案例
1.???????? 查詢部門員工的最高工資大于1500的部門,如下:
相信這樣的案例大家已經很熟悉了,以下講解一下group by的高級特性。
2.???????? Rollup可以返回合計,例如:
rollup(a,b) 包括:(a,b)、(a)、()的合計
rollup(a,b,c) 包括:(a,b,c)、(a,b)、(a)、()的合計
我想按班級和學生分組,查詢班級下學生的總分,并且做一下小計,使用以上的escore表,并且新建學生班級的關系表如下:
create table refcs as
select 1 cid,1 sid from dual
union all select 1,2 from dual
union all select 2,1 from dual
union all select 2,2 from dual
則查詢的sql如下,紅色區域是每個班級的總分合適,藍色區域是所有的總分合計:
3.?? cube可以返回交叉的合計,例如:
cube(a,b) 包括:(a,b)、(a)、(b)、()
cube(a,b,c) 包括:(a,b,c)、(a,b)、(a,c)、(b,c)、(a)、(b)、(c)、()
與rollup相比,多了灰色區域,灰色區域是對分組的第二個字段sid的小計,用來統計每個學生的總分數,但在此是沒有多大意義的,因為學生和班級是1->n的關系,統計每個學生的總分數和統計每個班級下每個學生的總分數沒有區別。
4.???????? GROUPING函數可以接受一列,返回0或者1。如果列值為空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查詢中使用。當需要在返回空值的地方顯示某個值時,GROUPING()就非常有用。
看如下sql,紅色區域和藍色區域的grouping參數字段是null,因此grouping字段返回1,非null時返回0:
但是返回0和1似乎沒有多大意義,通常返回一些有意義的字符串可讀性能好一些,如下:
其實你可以再優化一下,讓第一行只顯示“總計”兩個字。
5.???????? Grouping sets:以上用GROUP BY ROLLUP或GROUP BY CUBE替代GROUP BY,來計算高級的統計,不過它們會生成所有可能的總數,而你可能不需要全部總數,可以用GROUP BY GROUPING SETS來代替GROUP BY CUBE。你可以應用來指定你感興趣的總數組合。因為它不必計算它不需要集合(也不會產生太多結果),所以對SQL引擎來說更為高效。例如:
在圖中我已經用不同顏色的邊框和箭頭指明某行數據來源于grouping sets之后的哪些集合。
7.4???? 使用場景
分組時常用。
8?????? 分析函數
8.1???? 學習目標
掌握分析函數的使用,能用分析函數解決復雜查詢等問題。
8.2???? 要點
1.???????? 分析函數可分為四類:等級函數(ranking),聚合函數(aggregate),行比較函數(row comparison),統計函數(statistical)。
2.????????
?
8.3???? 語法
函數名(參數)over(partition by …order by…windows clause)
8.4???? 使用案例
1.???????? Row_number,rank,dense_rank屬于等級函數,例如,我想根據部分分區,查詢部門內部員工公司的排名,看一下用這三個等級函數會有什么區別:
我們發現三個函數都是返回分區排序后的序號,不同之處在于排序字段相同時,row_number是從1到n連續不跳號的,rank是給予值相同的兩行相同的序號,而且跳號,dense_rank也是給予值相同的兩行同樣的序號,但是不跳號。
2.???????? 常用分析函數:看一下以下一個sql中包含了多個常用的分析函數,圖中需要注意的地方我已經圈出來并且標明了:
常用的分析函數還有lag、lead、percent_rank、PERCENTILE_COUNT等,大家可以自己回去研究一下。
3.???????? First、last返回通過dense_rank排序后的第一個或者最后一個。例如我想查詢員工的最小工資最小的部門和員工的最大工資最大的部門:
4.???????? Windows子句,用來指明分析函數的計算窗口,語法如下:
窗口的劃分方式有range和rows兩種,Rows 表示物理偏移量,range表示邏輯偏移量。用rows 或range劃分窗口,按照起點在上,終點在下的原則(如果違反這個原則,則分析函數的計算結果為null),對窗口中的每一行應用分析函數計算結果。如果我想取:當前sal-500到當前sal為一個窗口,并按照窗口來計算工資總和,可以用如下sal來實現:
5.???????? 分析函數與group by結合,進行topN查詢,例如我想查詢總工資前三名的部門,如下:
8.5???? 使用場景
邏輯比較復雜的查詢,往往需要用到分析函數。
9?????? rownum
9.1???? 學習目標
理解oracle內部rownum的原理,會使用rownum進行top-N查詢和其他范圍查詢。
9.2???? 要點
1.?? rownum 和where 在同一層查詢中,where 條件之后使用rownum 比較,只能使用<=,<,!=,<>,不能使用>,>=(>=1是可以的,和不加效果一樣),=(使用=,只能是where rownum=1才可以)。否則不返回任何數據。如果使用!=或<>,那么只是返回前n-1行,其他按照rownum工作原理推算。
2.?? 當rownum 和order by 在一個語句級別中(同一層)使用的時候.看這個查詢的數據是否從索引中獲取(或者根據索引先得到rowid然后定位行)的,如果不是,那么就是先查詢出來,每行標上rownum,然后order by 將結果重新排序,那么rownum的順序是亂的。如果排序的數據是從索引中查詢的,這樣結果有序。這取決于執行計劃,執行計劃又和oracle優化器相關。
3.?? 在執行語句時,有關rownum執行的順序是這樣的:
1)?? 執行查詢操作,初始化rownum值為1。
2)?? 指針指向第一行,將該行的rownum標記為1。
3)?? 進行where條件匹配,如果where條件返回false,則拋棄行,返回true,則返回該行,并且將rownum值自增1。
4)?? Oracle獲取下一行,將該行的rownum標記為當前rownum值。
5)?? 返回第三步。
9.3???? 語法
Rownum可以用在where條件中,如:
Select * from emp where rownum<5;
9.4???? 使用案例
1.???????? Top-N查詢:
2.???????? 查詢中間幾行:
看一下oracle執行的原理,當指針移動到第一行的時候,rownum=1,rownum between 3 and 5返回false,第一行被拋棄,指針指向第二行,此時rownum還是為1,第二行也被拋棄,以此類推,無結果返回。這種情況可以使用子查詢,先把rownum最為rn字段緩存到結果集里面,然后對結果集進行篩選:
3.???????? 上述查詢其實存在隱患,不知道大家注意沒有?子查詢中select rownum rn,empno from emp order by empno,oracle的執行順序是先取到結果集,標記上rownum,然后進行排序,這樣rownum的序號不一定是排序后的序號,所以取到的數據可能不是我想要的。那此處為什么我能取到正確的數據呢?這取決與執行計劃,在emp表中,empno作為表的主鍵,也就是唯一索引,在取得子查詢結果集得時候,oracle是根據索引讀取數據的,而索引一般是在oracle的內存中,并且索引是有序的,優化器選擇索引的方式訪問emp表,所以oracle讀取數據的同時為當前行標記上rownum,所以rownum順序不會錯亂。如果我是通過ename排序取3-8行,emp在ename上并沒有建立索引,所以讀取的數據時錯亂的,如下:
此時再用外層查詢取得rn between 3 and 8,就會取得錯誤的數據。
此時能夠保證數據是正確的。有關案例2的order by和rownum要慎用,因為即使在相關字段上有索引,oracle的優化器也不一定會選擇索引訪問數據,這根表的狀態和其他很多原因都有關系,有關索引和執行計劃的相關知識,這里不做講解,將會在以后的課程中放在oracle優化的科目中進行講解。
9.5???? 使用場景
在進行top-N查詢或者取中間數據時可能用到。
10???????????? rowid
10.1??????? 學習目標
了解rowid的組成部分,會使用rowid進行刪除重復行等查詢。
10.2??????? 要點
1.???????? rowid的是基于64位編碼的18個字符,由數據對象編號+文件編號+塊編號+行編號組成(數據對象編號(6) +文件編號(3) +塊編號(6)+行編號(3)=18位)。
10.3??????? 語法
10.4??????? 使用案例
1.???????? Rowid經常用于刪除重復行,如我用如下語句加入escore2兩條重復數據,如下:
insert into escore2? select * from escore2 where sid=1;
commit;
很顯然,圈出的數據為重復數據,如下我可以用rowid來刪除重復數據:
delete from escore2 where rowid not in(
select min(rowid) from escore2 group by sid ,type,score
);
commit;
再來看一下escore2表,重復數據沒有了:
2.???????? 分頁,例如我想取escore2表的第4-6條數據,也就是上圖4、5、6行,如下:
10.5??????? 使用場景
Rowid可用于刪除重復數據或者分頁,還可以用于其他的需要唯一標識行的sql。
11???????????? Dade的使用
11.1??????? 學習目標
掌握date數據類型,會使用date類型,并且掌握date類型的常用函數。
11.2??????? 要點
1.???????? 一些常用的數據格式要牢記,他們就像date對象的屬性,當你要訪問date對象的相應屬性時,需要將這個屬性作為參數傳入,屬性對應的值才能被返回,如:
1)????? Y或YY或YYY 年的最后一位,兩位或三位
2)????? Q 季度
3)????? MM 月份
4)????? Month 用9個字符長度表示的月份名
5)????? WW 當年第幾周
6)????? W 本月第幾周
7)????? DDD 當年第幾天
8)????? DD 當月第幾天
9)????? D 周內第幾天
10)??? DY 中文的星期幾
11)??? HH或HH12 12進制小時數 HH24 24小時制
例如今天是2011年7月18日,星期一,執行如下sql看一下結果:
2.???????? 一些常見函數的用法:
1)???????? 對于to_date和to_char函數大家應該很熟悉了,這應該是oracle里面最常用的函數了,如下:
需要強調一點的是,oracle有默認的顯示格式,對于這個格式的字符串,oracle是可以識別的,并且能通過隱式轉換將其轉換為date類型,如下sql(在命令行執行):
由以上結果的輸出可以看出我當前數據庫的時間匹配格式是18-JUL-11的,那oracle可以接收這種類型的字符串將其隱式轉換為date類型,如下sql:
如下我修改了當前session的默認時間格式,則執行不報錯,但是只在當前session有效:
2)???????? Last_day(mydate),此函數返回mydate所在月份的最后一天。
3)???????? Add_month(mydate,n),返回mydate推后n個月后的日期。
4)???????? Months_between(date1,date2),返回date1與date2間隔的月數。
5)???????? Next_day(mydate,dayofweek),返回自mydate日期起,下一個dayofweek(星期幾)的日期。
6)???????? Trunc(mydate,格式字符串),返回對mydate截斷到指定位置后的日期。Round(mydate,格式字符串),返回對mydate四舍五入到指定位置的字符串,如下sql:
11.3??????? 使用場景
對于日期的計算需要用到日期函數,如:
1)???????? 上個月末:trunc(sysdate,'mm')-1
2)???????? 本月最后一秒:trunc(last_day(sysdate)+1,'dd')-1/24/60/60
3)???????? 本月的天數:trunc(last_day(sysdate)+1)-trunc(sysdate,'mm')
12???????????? 字符串函數的使用
12.1??????? 學習目標
掌握常用的字符串函數,能夠用字符串函數解決相關問題。
12.2??????? 要點
1.???????? ascii(char):返回字符串首字符串的ASCII碼值。Chr(n):返回ASCII碼值n對應的字符。如下:
2.???????? concat(str1,str2,…),返回str1,str2,……連接后的字符串。
3.???????? initcap(str),返回每個單詞首字母大寫的字符串。
4.???????? instr(char1,char2[,n[,m]]):用于取得子串在字符串中的位置,其中數字n為起始搜索位置,數字m為子串出現次數。如果數字n為負數,則從尾部開始搜索。數字m必須為正整數,并且n和m的默認值為1。
5.???????? length(char):返回字符串的長度。如果字符串的類型為char,則其長度包括所有的后綴空格;如果char是null,則返回null。
6.???????? lower(char):用于將字符串轉換為小寫格式;upper(char):將字符串轉換為大寫格式。
7.???????? lpad(char1,n,char2):用于在字符串char1的左端填充字符串char2,直至字符串總長度為n,char2的默認值為空格。如果char1長度大于n,則該函數返回char1左端的n個字符;rpad(char1,n,char2)用于在字符串char1的右端填充字符串char2,直至字符串總長度為n,char2的默認值為空格。如果char1長度大于n,則該函數返回char1左端的n個字符。
8.???????? trim(char from string)用于從字符串的頭部、尾部或兩端截取特定字符;ltrim(char1[,set]):用于去掉字符串char1左端所包含的set中的任何字符。Oracle從左端第一個字符開始掃描,逐一去掉在set中出現的字符,當遇到不是set中出現的字符時終止,然后返回剩余結果;rtrim(char1[,set]):用于去掉字符串char1右端所包含的set中的任何字符。Oracle從右端第一個字符開始掃描,逐一去掉在set中出現的字符,當遇到不是set中出現的字符時終止,然后返回剩余結果。
9.???????? replace(char,search_string[,replacement_string]):用于將字符串的子串替換為其他子串。如果search_string為null,則返回原有字符串;如果replacement_string為null,則會去掉指定子串。
轉載于:https://www.cnblogs.com/oldcat/archive/2011/08/17/2142995.html
總結
以上是生活随笔為你收集整理的Oracle高级SQL培训与讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring中使用Spark连接的Dat
- 下一篇: 怎么配置SQLServer2005以允许