SQL編寫及其優(yōu)化培訓_第1頁
SQL編寫及其優(yōu)化培訓_第2頁
SQL編寫及其優(yōu)化培訓_第3頁
SQL編寫及其優(yōu)化培訓_第4頁
SQL編寫及其優(yōu)化培訓_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、軟腦軟件北京公司S QL 編 寫 及 其 優(yōu) 化 培 訓溫有飄2005年4月28日本培訓包含的內(nèi)容如下: 41. 表、索引相關(guān)知識及其在數(shù)據(jù)庫內(nèi)部相關(guān)的物理存儲 41.1. 數(shù)據(jù)庫中最小的物理存儲單位:塊 (block) 41.2. 表數(shù)據(jù)在塊中的存儲以及RowId 信息 41.3. 索引 41.4. Bitmap 索引介紹 52. 數(shù)據(jù)庫查詢操作的內(nèi)部處理過程 62.1. 數(shù)據(jù)庫的數(shù)據(jù)讀取是以塊為單位的 62.2. 查詢操作內(nèi)部過程以及索引的作用 62.3. 執(zhí)行計劃概念 72.4. 排序處理過程以及各種引起排序的操作 72.5. 多表join 操作的內(nèi)部過程 73. 寫 SQL 語句時在性

2、能方面的目標 83.1. select 列表中減少不需要的數(shù)據(jù) 83.2. from列表中去除不需要的表 83.3. where 條件中應(yīng)該考慮到索引的使用,防止一些寫法 83.3.1. 防止過濾字段中套用函數(shù),如果必須,則考慮函數(shù)索引 83.3.2. 防止把列放入表達式中去比較 93.4. 防止不需要的排序 93.5. 防止數(shù)據(jù)類型的隱式轉(zhuǎn)換 93.6. 程序代碼中的注意點 103.6.1. 由多個 SQL 語句完成的一個操作盡可能寫成一個SQL 就完成, 防止分解103.6.2. 使用數(shù)據(jù)庫提供的約束來判斷某些錯誤,如唯一性104. SQL 語句知識 114.1. SQL 語句串講 114

3、.1.1. select f1 from A 114.1.2. select f1 from A where f2=v_1 114.1.3. select f1 from A order by f2 114.1.4. select sum(f1) from A 124.1.5. select f2,sum(f1) from A group by f2 124.1.6. select a_f2,b_f2 from A,B where A.f1=B.f1 124.1.7. Select * from report where SALES_CODE in (select SALES_CODE fro

4、manken where:.); 144.1.8. Select * from report where SALES_CODE exists (select 1 from ankenwhere );144.1.9. in,exists 的選擇 144.1.10. select yadfw as t1,kopeew as t2 From A union all select uufger as t1,poeprvcx as t2 from B 144.2. 幾種常見操作或函數(shù) 154.2.1. 比較符 like 154.2.2. is null ,isnot null 154.2.3. to_c

5、har,to_date,to_number 154.2.4. nvl 154.2.5. 其他 165. 表設(shè)計的一些建議 16參考文獻 16本培訓包含的內(nèi)容如下:表、索引相關(guān)知識及其在數(shù)據(jù)庫內(nèi)部相關(guān)的物理存儲;數(shù)據(jù)庫查詢操作的內(nèi)部處理過程;寫SQL語句時在性能方面的目標;SQL語句知識;表設(shè)計的一些建議下面闡述的內(nèi)容以 Oracle為例來講述的,在排版方面可能有不妥當?shù)牡胤?,或有些?nèi)容前 后重復(fù),但各種知識應(yīng)該比較容易理解和接受;1 .表、索引相關(guān)知識及其在數(shù)據(jù)庫內(nèi)部相關(guān)的物理存儲1.1. 數(shù)據(jù)庫中最小的物理存儲單位:塊(block)數(shù)據(jù)庫最小的物理存儲單位是塊9i默認是8k,每個塊只能屬于一

6、個表;一行數(shù)據(jù)插入時會占用塊中的一些存儲,當塊不能再容納新數(shù)據(jù)時,則將啟用新的塊存儲數(shù)據(jù);數(shù)據(jù)緩沖池1.2. 表數(shù)據(jù)在塊中的存儲以及 RowId信息表的字段除了設(shè)計者設(shè)計的字段外, 還有個字段Rowid ; RowId是oracle為每個表自動 增加的一個字段。當表中插入一行記錄時,此記錄在塊就有一個唯一的物理位置, 這個位置信息就保存在此行記錄的RowId字段;1.3. 索引表中記錄的存儲順序是以先后插入順序存儲的,在一個數(shù)據(jù)量很大的表中, 如果不引入其他的手段,每次查找小部分記錄都是從第一條掃描到最后一條,這樣,系統(tǒng)將慢得不能使用;使用索引可以有效解決問題;如圖:Report表(100萬條

7、記錄)RowIdSession_codeSales_codeEmployee_codeJAaNs1AAQAAA7yTAah100061000017AAANslAAYAAAAmWAAX0007100015。 索引Employee_codeRowd_ |517AAANslAAYAAAAmWA aaansiaaqaaATytAA索引的本質(zhì)用途是通過它使讀取進程在掃描源表時的數(shù)據(jù)塊范圍大大減小了,因此性能 大幅度提高;一般情況下,當檢索的記錄與所有記錄數(shù)比較 <=4%時,索引是很有效的,當比例更大 時,索引反而有可能降低性能, 因為即使使用了索引, 讀取進程還是掃描了大部分的表 中的塊,如果這樣

8、,倒不如不用索引直接掃描源表,因為減少了讀取索引的塊的開銷;當索引建好后,oracle優(yōu)化器在執(zhí)行sql時會選擇是否使用索引,所以設(shè)計表者不用擔 憂此索引會影響檢索性能;創(chuàng)建索引的標準是那一列是否經(jīng)常在where條件中出現(xiàn),否則不應(yīng)該建立,因為,每次表記錄的增加、刪除以及修改那個字段值時,還要維護索引,增加了開銷;此節(jié)講的索引叫 B_tree索引,在內(nèi)部存儲中類似樹狀結(jié)構(gòu),有枝和葉,枝是 oracle內(nèi) 部存儲的一些連接數(shù)據(jù),葉才存儲實際的值,如圖:表中每條記錄只要那個列是非NULL值,在索引中都有一個條目entry來存儲如上圖,類似于表在塊中一條條記錄存儲;1.4. Bitmap索引介紹當表

9、中某列的distinct值比較少時,使用 B_tree索引效率就不高了,因為以此列來做 where條件過濾的話,結(jié)果集很可能超過總記錄數(shù)的4%,正如前面說過的,超過 4%記錄使用B_tree索引,效率反而下降。使用Bitmap位圖索引可以解決這個問題;Bitmap索引使用一個位圖來記錄數(shù)據(jù)情況,舉例:商品表product,有一個字段color存儲顏色值,在所有商品中最多就10種不同的顏色,創(chuàng)建的位圖圖示如下:Indexstart ROWIDA A AK Al A AI A ft AC AAAROWIDAMKMhAIAAAFNOARq AAAKAIAMAMFNQARq aAAEAI AAIAAA

10、F HQ ABq kAAIAlbitmap100010010GQ1001D1CO> OCOIOIQDOOI0Q100QC0> 310OOCOailQO0QO10Cl> ooiooaioooooiooooio?其中,Start ROWID是表中的第一條記錄的物理地址,end ROWID是表中最后一條記錄的物理地址,bitmap是一張位圖,存儲一連串的0或1;列值為blue的bitmap中,每個bit的位置在源表中都能找到某個位置與它一一對應(yīng),它們在各自對象中的相對位置一樣。bit值為1時,則源表對應(yīng)位置那個 rowid所在的記錄的color字段值為blue',為0時,則

11、非blue'值;類似的,Green, Red, Yellow 都有各自的bitmap;試想,當where條件中有過濾條件 A and B,條件A可以使用B_tree索引,條件B 可以使用bitmap索引,那么從A條件中可以得到一個 RowId的集合,從B條件也可以 得到RowId結(jié)合,這樣,只要從第一個rowid集中去除第二個rowid集中的值,得到結(jié) 果集Rowid ,我們就可以從源表得到數(shù)據(jù)了;Bitmap使用了壓縮技術(shù),節(jié)約了存儲,并且在一個bitmap上對某個位bit的值是1還是 0時速度是非??斓?;2 .數(shù)據(jù)庫查詢操作的內(nèi)部處理過程2.1. 數(shù)據(jù)庫的數(shù)據(jù)讀取是以塊為單位的Or

12、acle讀取表中的數(shù)據(jù)時,是以整個塊為單位的,有可能一次讀多個塊;從索引中得到 rowid的物理位置時,也要把含rowid這個位置的塊從磁盤中讀出, 然后才處理個別行;2.2. 查詢操作內(nèi)部過程以及索引的作用舉仞ij: select * from personal_function where employee_code= -200 ;上述查詢,如果 employee_code上沒有索引,則會把 personal_function表數(shù)據(jù)的塊全部 讀入內(nèi)存中,同時從第一條記錄查到最后一條記錄,對符合條件的記錄返回給用戶;如果employee_code有索引,則使用索引檢索出含符合條件的Rowid

13、的塊讀入內(nèi)存,然后定位到rowid指示的位置上把記錄返回給用戶;2.3. 執(zhí)行計劃概念2.2節(jié)中,如果 employee_code=-200的記錄數(shù)在占總記錄數(shù)超過4%,則有可能就不會用索引查找,而是直接全表掃描,這是oracle的優(yōu)化器經(jīng)過各種檢測后會自動選擇的;Oracle對已存在數(shù)據(jù)統(tǒng)計特征會選擇不同的執(zhí)行路徑或者全表,或者使用索引等,這就產(chǎn)生了不同的執(zhí)行計劃,使能到達最大的性能。執(zhí)行計劃選擇的模式有RBO和CBO方式,采用CBO方式時(這是oracle公司強烈建議使用的),sql語句中from后表的先后順序以及 where條件中各個條件的先后順序變得 不是很重要了,如果 RBO方式則不

14、然;CBO全稱 Cost-based Optimizer,基于代價的優(yōu)化。 2.2節(jié)提到的 SQL語句,Oracle是 否使用索引,其內(nèi)部會做各種比較,然后自動做出選擇;為了使 Oracle做出更精確的 比較,我們應(yīng)該周期性地對表進行統(tǒng)計,使 Oracle 了解到真實情況后做出更準確的判 斷。因為要統(tǒng)計,所以稱之為基于代價;RBO全稱Rule-based Optimizer,基于規(guī)則,就是說 Oracle定義的一套執(zhí)行先后順序, 如,有索引則一定會用索引,就如 2.2節(jié)的SQL語句,但這樣有時并不是最好的執(zhí)行 選擇。2.4. 排序處理過程以及各種引起排序的操作舉仞ij: select * fr

15、om personal_function where employee_code= -200 order by func_name;由2.2節(jié)可知,如果沒有 order by語句時,oracle只要檢索到一條符合條件的記錄就立 刻返回給用戶,直到所有數(shù)據(jù)返回完畢。當有 order by時,情況就不一樣了,oracle會把檢索到的每一條記錄先保存在一個用于排序的內(nèi)存中,當所有符合條件的記錄在那個區(qū)域完成排序后,再返回給用戶;通過排序這個操作,oracle中間多處理了一個步驟。數(shù)據(jù)量越大,排序時間則更長,當 數(shù)據(jù)量到達所找的內(nèi)存區(qū)域無法容納時,將使用磁盤做為臨時排序區(qū),此時,性能會大大降低,用戶將

16、等待更長的時間才能得到返回的結(jié)果;因此,在一個 SQL語句中,如果對返回的記錄集沒有順序要求時,應(yīng)該去除引起排序 的語句;弓I起排序的操作有:order by, distinct, union , group by2.5. 多表join操作的內(nèi)部過程舉例說明:Esm系統(tǒng)中的3張表結(jié)構(gòu)如下:Employee:EMPLOYEE_CODE職員代碼EMPLOYEE_NAME職員名稱EMPLOYEE_KANA職員全稱Emp_detialEMPLOYEE_CODE職員代碼DepartDepart_CODE部門代碼DEPART_NAME部門名稱DEPART_CODE職員部門代碼現(xiàn)在要求列出所有職員的名稱和其

17、對應(yīng)的部門名稱,SQL語句如下:select aa.employee_name,cc.depart_namefrom employee aa,emp_detail bb,depart ccwhere aa.employee_code=bb.employee_code and bb.depart_code=cc.depart_code;執(zhí)行時,oracle可以選擇如下的一個執(zhí)行計劃可參考4.1.6節(jié)的流程圖:Employe 表數(shù)據(jù)emp_detaildepart00001張三00002李四00003王五00002100、0000320000001300200開發(fā)2部300開發(fā)3部100開發(fā)1部1

18、) 讀取employee的第一條記錄,得到職員代碼 A;2) 再在emp_detail查找職員代碼為 A的第一條記錄,得到部門代碼 B;3) 在表depart中查找部門代碼為 B的記錄;4)在各個表的記錄中中取出需要的信息返回給用戶;5) ooo 2步和1步是個循環(huán)操作,2步嵌套于1步中,直到所有信息返回給用戶;Oracle如果有其他的執(zhí)行記錄更好的話,會選擇其他的;3. 寫SQL語句時在性能方面的目標3.1. select列表中減少不需要的數(shù)據(jù)select列表需要的信息應(yīng)該按需索取,不能因為圖方便用 *'把所有字段內(nèi)容取到客戶端,這樣,既增加服務(wù)器的負荷,又增加網(wǎng)絡(luò)流量;3.2. f

19、rom列表中去除不需要的表出現(xiàn)在from后的表,oracle都會對它檢索并與其他表進行join操作,如果把不需要的表不經(jīng)意間放在了 from后面,可能會增加幾倍甚至幾十倍的負荷;如果 where條件中也沒有加上進行join的條件,oracle將對它進行笛卡兒乘積的 join ,這種負荷可想而知;3.3. where條件中應(yīng)該考慮到索引的使用,防止一些寫法3.3.1. 防止過濾字段中套用函數(shù),如果必須,則考慮函數(shù)索引舉例:統(tǒng)計在某天的日報登記個數(shù),其中,某天這個值V_date是從程序外面以參數(shù)的形式傳遞進去的字符串,格式如yyyy-mm-dd ;比較兩種寫法:第一種:Select count(*

20、) from report where to_char(day, yyyy-mm-dd )=V_date第二種:Select count(*) from report where day=to_date(V_date , yyyy-mm-dd ) ;必須選擇第二種,因為如果day 上有索引,而day 作為函數(shù) to_char 的參數(shù), oracle將不使用它的索引, 因而進行全表掃描, 這樣的后果是, 也許 2 秒內(nèi)就能統(tǒng)計出來的結(jié)果,卻可能要花幾十分鐘甚至幾小時; report 表數(shù)據(jù)量越大,比照結(jié)果就更明顯;有些情況確實需要使用函數(shù),如:取出職員名稱為 V_name 的職員代碼,而V_na

21、me是從程序外面?zhèn)鬟M去的參數(shù);由于在最初增加職員記錄時, 每個存入的職員名稱沒有做大小寫轉(zhuǎn)化, 比方, 最初登 陸了一個ZhanSan'的職員,此時 V_name傳進來的是zhansan,如果用如下語句查詢將得不到記錄:Select employee_code from employee where employee_name=V_name ;可使用如下語句Select employee_code from employee where UPPER(employee_name)= UPPER (V_name);此時由于套用了函數(shù)UPPER 而列 employee_code 上的索引將不

22、被使用,可以考慮創(chuàng)建函數(shù)索引,就是把UPPER(employee_name) 當成一個字段去創(chuàng)建索引,當查詢時,則會使用此函數(shù)索引;3.3.2. 防止把列放入表達式中去比較請看下面 2 條語句:Select * from A where f1/5>300 ;Select * from A where f1>300*5 ;必須使用第二種,否則,如果f1 有索引,第一種情況將不使用;3.4. 防止不需要的排序2.4 節(jié)中已說明排序需要額外的負荷,所以,當不需要排序時,應(yīng)該防止;3.5. 防止數(shù)據(jù)類型的隱式轉(zhuǎn)換舉例:表 A ,有一字段code , varchar2 類型,此字段存儲的值都

23、是由數(shù)字組成的串;SQL 語句:Select * from A where code=v_number ; 其中, v_number 是由程序外面?zhèn)魅氲臄?shù)值;因為 v_number 是數(shù)值,而code 是 varchar2 類型,所以, Oracle 會進行類型的隱式轉(zhuǎn)換,把此語句轉(zhuǎn)化成如下形式執(zhí)行:Select * from A where to_number(code)= v_number ;把列嵌套在函數(shù)里索引不能使用 ,這個是我們不期望的,所以正確的做法是我們應(yīng)該進行顯式的轉(zhuǎn)換:Select * from A where code=to_char(v_number) ;3.6. 程序代

24、碼中的注意點3.6.1. 由多個 SQL 語句完成的一個操作盡可能寫成一個SQL 就完成,防止分解舉個例子:需要得到 2004 年中,每個季度(1-3 月, 4-6 月, 7-9 月, 10-12 月 ) 的日報個數(shù);第一種方法:比較容易想到的,用 4 個 SQL 語句分別去得到各個季度的統(tǒng)計:Select count(*) from report where day>=to_date(2004-01-01 , yyyy-mm-dd ) and day<=to_date( 2004-03-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select co

25、unt(*) from report where day>=to_date(2004-04-01 , yyyy-mm-dd ) and day<=to_date( 2004-06-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select count(*) from report where day>=to_date(2004-07-01 , yyyy-mm-dd ) and day<=to_date( 2004-09-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select count(*) from re

26、port where day>=to_date(2004-10-01 , yyyy-mm-dd ) and day<=to_date( 2004-12-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;第二種方法:一個SQL 語句完成SelectCount(case when day>=to_date( 2004-01-01 , yyyy-mm-dd ) to_date( 2004-03-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) as one,andday<=Count(case when day>=to_

27、date( 2004-04-01 , yyyy-mm-dd ) to_date( 2004-06-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) )as second,andday<=Count(case when day>=to_date( 2004-07-01 , yyyy-mm-dd ) to_date( 2004-09-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss )as third,andday<=Count(case when day>=to_date( 2004-10-01 , yyyy-mm-dd )an

28、dday<=to_date( 2004-12-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss )as forth,From report ;顯然,第二種方法可以提高4 倍的性能;要到達這種轉(zhuǎn)化,編碼人員需要對數(shù)據(jù)庫提供的 SQL 函數(shù)有充分的認識;3.6.2. 使用數(shù)據(jù)庫提供的約束來判斷某些錯誤,如唯一性有種情況,應(yīng)用程序中經(jīng)常出現(xiàn),舉個例子:有張全國居民身份表resident, 其中有個字段身份證號碼ID_card , 是主鍵, 在登記一個居民時,為了防止發(fā)生主鍵沖突,應(yīng)用程序往往保存之前用一個SqL 語句去查此ID_card 號是否已存在,存在則提示ID_car

29、d 沖突。上述情況完全可以防止使用寫 SQL 語句的方法去查,因為 oracle 的每個錯誤都有一個唯一的錯誤號,只要在程序中去捕捉違例 (exception) ,然后進行比照是否是主鍵沖突即可;有些時候非主鍵的字段也要保持唯一性, 則可以使用唯一索引。 當發(fā)生唯一性沖突時,也有一個錯誤號;Oracle 在自身版本升級的時候,錯誤號的含義是向后兼容的;4. SQL 語句知識4.1. SQL 語句串講4.1.1. select f1 from A這是一個最簡單的 SqL 語句,想象一下A 表的塊讀入內(nèi)存,然后從第1 條記錄掃描到最后一條記錄且每次立刻把f1 字段值返回給用戶,這個過程是全表掃描;

30、Sql 語句中,有列別名和表別名,對很長表名或列名可以簡化操作,如:表別名: Select aa. STATUS from REGULAR_REPORT_CONTENTS aa ;表別名前不應(yīng)該使用as, SQL SERVER 支持,但 Oracle 里不支持;列別名: Select MODIFIED_STATUS_CODE_OUT as mod from TIMEBOOK_LOG;程序代碼中引用的時候就可以使用 mod ,而非長串;如果在連接表中有同名表的時候,別名是必須的;4.1.2. select f1 from A where f2=v_1如果 f2 無索引,則第4 1 1 節(jié)中每次掃

31、描到一條記錄時會根據(jù)條件進行過濾,符合條件則立即返回給用戶,否則掃描下一條;F2 有索引且使用時,則從索引開始掃描,掃描時不象表一樣從第一條目掃描到最后一條, oracle 會根據(jù)內(nèi)部算法很快定位到符合條件的條目, 讀取 Rowid 后根據(jù)物理地址定位到源表的記錄上立即返回給用戶, 然后再在索引中定位到第二個符合條件的條目,直到全部;4.1.3. select f1 from A order by f2在 4.1.1 節(jié)中講到的每掃描的記錄立即返回給用戶,而當有排序時,則先發(fā)送到一個排序區(qū)中進行排序,等所有記錄掃描完后,再把排序區(qū)中的數(shù)據(jù)集返回給用戶;當 select 后帶 distinct

32、時, 內(nèi)部處理也有排序操作, 更靠近 distinct 的字段就更先排序,同時在排序過程發(fā)現(xiàn)有各個字段信息完全相同的行時, 只留一條記錄, 廢除其他相同的;排序完成后,再把排序區(qū)中的數(shù)據(jù)集返回給用戶;4.1.4. select sum(f1) from Aoracle 處理時類似這樣:使用一個變量V ,初始值0,每次掃描一個記錄時,v=v+f1 ,直到掃描到最后,把v 返回給用戶;類似的,函數(shù)avg,max,min,count 原理差不多,如果f1 有索引時,可能會掃描索引而不掃描表,因為索引的塊更少,而且包含了需要的全部信息;4.1.5. select f2,sum(f1) from A g

33、roup by f2上節(jié)中是把f1 值加如到一個變量中,這里多了一個字段,可以這樣理解:每掃描一條記錄時,如果f2 值未出現(xiàn)過,則定義一個數(shù)組變量A , A1=f1 , A2=f2 ;如果 f2值以前出現(xiàn)過,則把當前f1 值增加到對應(yīng)的數(shù)組變量中,這樣,直到表掃描完畢,按 f2 字段分組的各個統(tǒng)計值都記錄在了一堆的數(shù)組中, 最后, oracle 把數(shù)組的各個值按記錄的方式返回個用戶;Oracle 在處理每當一個新的 f2 的值出現(xiàn)時, 對應(yīng) f2 的數(shù)組變量都會按f2 值由小到大排序,因此,排序結(jié)果集中是按f2 排序的,用戶無須再排序;分組語法中,在select列表中出現(xiàn)的非統(tǒng)計字段,者B要在

34、group by后出現(xiàn);有時候需要對統(tǒng)計的結(jié)果進行過濾,例如 select f2,sum(f1) from A group by f2 中,用戶只需要 sum(f1)>10000 的組的統(tǒng)計,這時用 having 過濾條件,如下:select f2,sum(f1) from A group by f2 having sum(f1)>10000where 條件是針對記錄的過濾,被過濾掉的數(shù)據(jù)不參與統(tǒng)計。 having 是針對統(tǒng)計完成后,統(tǒng)計結(jié)果返回給用戶時的過濾;4.1.6. select a_f2,b_f2 from A,B where A.f1=B.f1oracle 對連接 jo

35、in 的操作的內(nèi)部處理過程,可以參考下列圖:上圖的流程只是執(zhí)行計劃當中的一種,但可以借助于理解, 當多于2張表時,情形是上述的連接也稱內(nèi)連接,其他連接還有左連接,右連接和全表連接的方式;左連接:select a_f2,b_f2 from A,B where A.f1=B.f1+,必須首先掃描 A 表以驅(qū)動 B掃描。此時,A標示的地方,如果針對 A表的一條記錄,在 B表中1條也沒有找到 符合條件的記錄,則會把 A.f1值和以NULL值作為B.f1的值返回給用戶;這樣, A 表中的所有記錄的且在select列表中的信息都會返回給用戶;右連接:select a_f2,b_f2 from A,B wh

36、ere A.f1+=B.f1 ,首先掃描 B 表以驅(qū)動 A 掃描,其他操作可參考左連接;全連接:select a_f2,b_f2 from A full outer join B on A.f1=B.f1 ;它的記錄集是 select a_f2,b_f2 from A,B where A.f1=B.f1的結(jié)果集加上A表中有,但在 B表中未找到符合條件的記錄的集合B表中的信息是以Null值返回,再加上B表中有,但A表中未找到符合條件的記錄的集合A表中的信息是以 Null值返回;各種連接通用寫法是:內(nèi)連接: select a_f2,b_f2 from A,B where A.f1=B.f1 或 s

37、elect a_f2,b_f2 from A inner joinB onA.f1=B.f1( 此標準在 symfoware 不支持,奇怪!)左連接:selecta_f2,b_f2 from A left outer join B on A.f1=B.f1右連接:selecta_f2,b_f2 from A right outer join B on A.f1=B.f1全連接:selecta_f2,b_f2 from A full outer join B on A.f1=B.f1 ;在symfoware 中不支持4.1.7. Select * from report where SALES_

38、CODE in (select SALES_CODE from anken where );上節(jié)講的所有的表都在from 后的列表中,數(shù)據(jù)源都是直接的表,不含子查詢,而這條是典型的含子查詢的語句,內(nèi)部執(zhí)行時,可以有這種方式:首先,執(zhí)行子查詢語句,把結(jié)果集臨時保存,作為外層查詢的一個數(shù)據(jù)源;其次,類似4.1.6 節(jié)中的流程圖,先檢索report 表第一條記錄,然后再檢索上一個步驟得到的數(shù)據(jù)源,如果包含sales_code值,則返回report當前檢索到的記錄,如果沒有,則 report 繼續(xù)掃描下一條記錄,重復(fù)上步操作,直到表的結(jié)尾;很多含子查詢的語句 oracle 內(nèi)部處理的時候會先轉(zhuǎn)換成等價

39、的不含子查詢的語句去執(zhí)行,如:Select A.f1,B.f1 from A,(select * from C where C.f3=V_1) B where A.f2=B.f2;轉(zhuǎn)換成:Select A.f1,B.f1 from A,C where A.f2=C.f2 and C.f3=V_1;4.1.8. Select * from report where SALES_CODE exists (select 1 from anken where );Oracle 先掃描 report 的一個記錄, 然后去執(zhí)行里層子查詢里的語句, 只要能檢索到一條記錄,則立即返回給外層一個true 的值,

40、 report 的當前記錄就可以返回給用戶,掃描一下一條記錄;如果子查詢執(zhí)行完畢都還沒有檢索到一條記錄,則返回 false 給外層,則表示report 當前記錄不符合條件,則繼續(xù)掃描下一條記錄,直到結(jié)尾;4.1.9. in,exists 的選擇一般情況下, in 的子查詢都可以寫成exists 的子查詢,以下兩種選擇可以優(yōu)化性能:1) 當內(nèi)層子查詢的過濾條件有很強的過濾作用時,考慮使用in ,因為內(nèi)層子查詢返回的數(shù)據(jù)源比較少;2) 當外層查詢的過濾條件有很強的過濾作用時,且內(nèi)存查詢可以使用索引快速定位,則考慮使用 exists ;4.1.10. select yadfw as t1,kopee

41、w as t2 From A union all select uufger as t1,poeprvcx as t2 from Bunion all 前后是兩個獨立的查詢,它的作用是合并2 個記錄集。內(nèi)部處理時, oracle先執(zhí)行 union all 之前的查詢返回記錄給用戶,執(zhí)行完畢后,接著執(zhí)行union all 后面的查詢,把查詢結(jié)果返回給用戶;應(yīng)用程序中, 有很多報表或網(wǎng)格顯示的上下行內(nèi)容來自于互不相干的表, 但由于使用綁定數(shù)據(jù)源的方式,顯示數(shù)據(jù)只能由一次SQL 語句檢索得到,此時union all 就派上用場了;Union all 兩端查詢的字段個數(shù)以及對應(yīng)的數(shù)據(jù)類型要一致;Uni

42、on 也有把多個查詢的記錄集合并的功能, 但它與 union all 的不同之處是, 當 oracle 檢索到的每條記錄時不會馬上返回給用戶, 會把它送到一個排序區(qū)中進行排序, 排序 中以字段在select列表中更靠前的則先排序,當不同記錄中各個字段信息全部相同時,oracle 只留下一條記錄,廢除其他相同記錄;所以,當不需要排序且允許相同記錄存在時,使用 union all 性能比 union 好;4.2. 幾種常見操作或函數(shù)4.2.1. 比較符 like這是一個模糊查詢操作的字符串比較符,如 where A like Ww%',通配任意字符的符號%,如果單個字符通配是_ 。作比較的

43、串中,如果 % 或_放于最前面,oracle 將不用索引;4.2.2. is null , is not null當比較一個字段是否為 null 或非 null 時,應(yīng)該使用 where f1 is null 或 where f1 is not null ,而不能用=或<> 比較符;任何值與 Null 做=,>,< , <> 比較時,都返回false ;任何值與null 進行+-*/數(shù)字運算操作時,得到的還是null ;字符串與null 值使用 |連接還是那個字符串值;4.2.3. to_char,to_date,to_numberto_char 可以把一個數(shù)字值轉(zhuǎn)換成字符串,這個簡單,不多講;to_char 把日期型轉(zhuǎn)換成字符串時, 最通用的格式 yyyy-mm-dd hh24:mi:ss , 其中 yyyy是 4 字符年份, mm 是 2 字符月份, dd 是 2 字符日期, hh24 是 24 小時制的時間,如果12小時制則用hh, mi是2字符分鐘,ss是2字符秒數(shù).格式可以靈活使用

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論