數(shù)據(jù)庫設(shè)計(jì)及開發(fā)規(guī)范,sql性能優(yōu)化

1 引言

1.1 編寫目的

本文檔用于規(guī)范數(shù)據(jù)庫設(shè)計(jì)、開發(fā)等方面的內(nèi)容。

1.2 預(yù)期讀者

本文檔的預(yù)期讀者為本項(xiàng)目組全體成員,以及其他與項(xiàng)目有關(guān)的管理人員。

1.3 術(shù)語定義

OMP:Operation Management Platform

1.4 參考文檔

《數(shù)據(jù)庫編碼規(guī)范.pdf》

2 數(shù)據(jù)庫規(guī)范

2.1 設(shè)計(jì)規(guī)范

2.1.1 命名規(guī)范

數(shù)據(jù)庫對(duì)象的命名規(guī)則的范圍為管理平臺(tái)設(shè)計(jì)開發(fā)所涉及的表,對(duì)于其他外部系統(tǒng)所創(chuàng)建的表不在本規(guī)范約束范圍內(nèi),
數(shù)據(jù)庫對(duì)象如表、列、序列、過程、函數(shù)等在命名時(shí)要遵循如下規(guī)則:

  • 命名要使用富有意義中文名稱縮寫,要以字母開頭,不能超過30個(gè)字符。
  • 數(shù)據(jù)庫對(duì)象名稱由如下部分組成:范圍、類型、名稱實(shí)體,各詞匯間采用“_”連接。
  • 其中各數(shù)據(jù)庫對(duì)象的范圍和類型的具體含義及取值詳見各數(shù)據(jù)庫對(duì)象的命名規(guī)則。
  • 數(shù)據(jù)庫對(duì)象的名稱不允許是數(shù)據(jù)庫的 保留字關(guān)鍵字。
圖例-1.png

2.1.2 表規(guī)范

2.1.2.1 建表的參數(shù)設(shè)計(jì)

  • 不允許將表建立在默認(rèn)系統(tǒng)表空間上
  • 表和索引建立在不同表空間上
  • 建表時(shí)必須指明所存儲(chǔ)的表空間
  • 生成表腳本時(shí)非空的列放在表的前部,可空的列放在表的后部
  • 數(shù)據(jù)緩沖池的類型:查詢頻繁且數(shù)據(jù)量較少的參數(shù)表 采用 buffer pool keep
  • INITIAL: 對(duì)初始化數(shù)據(jù)量大的表,設(shè)置的值要大于初始化數(shù)據(jù)
  • PARALLEL: 對(duì)于OLTP(聯(lián)機(jī)事務(wù)處理)系統(tǒng),不允許使用該參數(shù)

2.1.2.2 主外鍵設(shè)計(jì)

  • 數(shù)據(jù)約束優(yōu)先考慮利用數(shù)據(jù)庫提供的約束機(jī)制,在數(shù)據(jù)庫產(chǎn)品所提供的機(jī)制無法滿足的情況下,再考慮通過編程實(shí)現(xiàn)
  • 主鍵的設(shè)置通常不使用實(shí)際意義的列做主鍵,具體情況應(yīng)結(jié)合業(yè)務(wù)特性綜合考慮
  • 字表在外鍵的字段上必須建立索引
  • 由Sequence產(chǎn)生的ID列,不作為組合PK的列
  • 刪除約束時(shí)使用keep index參數(shù)

2.1.2.3 列設(shè)計(jì)

  • 定長(zhǎng)字符類型列使用CHAR類型,最大長(zhǎng)度為2000;不定長(zhǎng)字符類型列使用VARCHAR類型,最大長(zhǎng)度為4000
  • 日期字段需定義為DATE類型。如果定義為VARCHAR或者CHAR時(shí)需要進(jìn)行轉(zhuǎn)換,影響效率。需要數(shù)據(jù)精確到微秒的字段定義為TIMESTAMP類型
  • 列表為null時(shí),需要定義default值,避免因?yàn)閚ull而造成索引不能被用到的情況
  • 使用NUMBER類型是必須指定長(zhǎng)度。由NUMBER的到精度與密度來保障數(shù)據(jù)的一致性
  • 表中字段的命名長(zhǎng)度不應(yīng)該超過30個(gè)字節(jié)
  • 記錄數(shù)達(dá)到千萬級(jí)的表,必須進(jìn)行分區(qū),分區(qū)一般遵循以下原則:
    1. 數(shù)據(jù)具有明顯的范圍屬性,比如日期,大小等,且經(jīng)常進(jìn)行范圍條件查詢的表,采用范圍分區(qū)。
    2. 數(shù)據(jù)具有明顯的列表屬性,比如地點(diǎn),省份等,且經(jīng)常用列表?xiàng)l件查詢的表,采用列表分區(qū)。
    3. 數(shù)據(jù)不具有明顯的范圍屬性或者列表屬性,且數(shù)據(jù)量很大,則可以采用hash分區(qū)。

2.1.2.4 臨時(shí)表

  • 對(duì)于只對(duì)本事務(wù)有效的臨時(shí)表使用ON COMMIT DELETE ROWS關(guān)鍵字創(chuàng)建該表
  • 對(duì)于只對(duì)本會(huì)話有效的臨時(shí)表使用ON COMMIT PRESERVE ROWS 關(guān)鍵字建該表
  • 對(duì)于臨時(shí)表空間要求比較大的業(yè)務(wù)系統(tǒng),臨時(shí)表要存儲(chǔ)在獨(dú)立的表空間中,并且臨時(shí)表空間的數(shù)據(jù)文件需要放在獨(dú)立的磁盤上

2.1.3 索引規(guī)范

  • 選擇使用普通B樹索引
  • 小表(數(shù)據(jù)量小于10000條記錄為標(biāo)準(zhǔn))不需要建立索引
  • 創(chuàng)建或重建索引時(shí)需指定使用NOLOGGING子句,提高執(zhí)行效率
    對(duì)于分區(qū)索引,建全局分區(qū)或者本地分區(qū)規(guī)則如下:
分區(qū)規(guī)則圖
  • 建立分區(qū)索引必須指定表空間,并且指定的表空間要與數(shù)據(jù)表空間分開。
  • 對(duì)于OLTP應(yīng)用的業(yè)務(wù)系統(tǒng),單個(gè)表上索引的個(gè)數(shù)不超過5個(gè)
  • 將記錄差別數(shù)最多的列放在索引順序的最前面
  • 對(duì)于OLTP應(yīng)用的業(yè)務(wù)系統(tǒng)索引數(shù)據(jù)的重復(fù)率盡量不超過20%
  • 進(jìn)行order by column desc 排序時(shí),創(chuàng)建column desc索引
  • 頻繁使用的index需要放入庫緩存的keep池中

2.1.4 存儲(chǔ)過程、函數(shù)、包規(guī)范

  • 存儲(chǔ)過程、函數(shù)和包中不允許頻繁使用DDL語句
  • 存儲(chǔ)過程、函數(shù)和包中必須有相應(yīng)的出錯(cuò)處理功能
  • 存儲(chǔ)過程、函數(shù)和包中變量在引用表字段的時(shí)候,使用%rowtype類型

2.1.5 別名

  • 對(duì)于只讀用戶,必須創(chuàng)建與表相同名字的別名
  • 別名的訪問順序:public別名 -> private別名 -> 與表同名的對(duì)象

2.1.6 Database Link 別名

  • 只允許從其它數(shù)據(jù)庫中查詢少量數(shù)據(jù)時(shí)使用dblink
  • 不使用dblink更新其它數(shù)據(jù)庫的數(shù)據(jù)

開發(fā)規(guī)范

2.2.1 變量命名規(guī)范

變量的命名體現(xiàn)其作用域和數(shù)據(jù)類型,規(guī)則如下:

  • <變量作用域>_<有意義的變量名字>_<變量類型>_<后綴>
  • 變量名不能超過數(shù)據(jù)庫限制(30個(gè)字符)
  • 供別的文件或函數(shù)調(diào)用的函數(shù),不能使用全局變量交換數(shù)據(jù)


    圖例-2.png

2.2.2 SQL開發(fā)規(guī)范

2.2.2.1 SQL書寫規(guī)范

  • 每行不能寫超過80個(gè)字符
  • 使用兩個(gè)空格縮進(jìn)代碼,比如:
BEGIN
  FOR l_count IN 1..10 LOOP
    x_result := x_result + l_count;
  END LOOP;
END;

  • 關(guān)鍵詞要大寫(比如INSERT)
  • 常數(shù)符號(hào)要大寫,比如:
CONSTRAINT G_MAX_VALUE NUMBER :=10;
...
  IF(1_value > G_MAX_VALUE)
  THEN
    ...
  • 語句中出現(xiàn)的所有表名、列名全部小寫,系統(tǒng)保留字、內(nèi)置函數(shù)名、SQL保留字大寫,連接符OR、IN、AND、以及=、<=、>=等前后加上一個(gè)空格
  • SQL語句的縮進(jìn)風(fēng)格:

    一行有多列,基于列對(duì)齊原則,采用下行縮進(jìn)
    WHERE子句書寫時(shí),每個(gè)條件占一行,語句另起一行時(shí),以保留字或者連接符開始,連接符右對(duì)齊

  • SELECT語句中不可以用 * ,必須SELECT字段列表,以節(jié)省內(nèi)存,提高效率
  • 避免頻繁 COMMIT ,尤其是把 COMMIT 寫在循環(huán)體中每次循環(huán)都進(jìn)行 COMMIT 。避免在一個(gè)事務(wù)中出現(xiàn)2次 COMMIT現(xiàn)象。例如執(zhí)行一半執(zhí)行一次COMMIT,執(zhí)行完另外一半又執(zhí)行一次 COMMIT。
  • LIKE子句如果非必要時(shí)盡量使用前端匹配,如寫成 LIKE'STRING%',不要寫成 LIKE'%STRING%'
  • 批量INSERT大量數(shù)據(jù)時(shí)可以采用APPEND和NOLOGGING方式,提高處理速度
  • EXP時(shí)可以采用DIRECT=Y,INDEX=NO的方式提高處理效率,IMP時(shí)可以指定較大的buffer。如果是ORACLE 10g以上則可以使用EXPDP和IMPDP來提高處理的速度
  • EXP和IMP時(shí),如果系統(tǒng)中存在主外鍵約束,在IMP時(shí)可以設(shè)置CONSTRAINTS=N,避免在IMP時(shí)因?yàn)橹魍怄I而報(bào)錯(cuò)
  • SQL中盡量不要使用數(shù)據(jù)庫未文檔化的功能,比如WMSYS.WM_CONCAT

2.2.2.2 索引與分區(qū)使用規(guī)范

  • 表的記錄數(shù)少于10000條,執(zhí)行全表掃描
  • 在寫查詢條件時(shí)注意引用索引
  • 批量提取數(shù)據(jù),使用按分區(qū)掃描
  • 比較值與索引列數(shù)據(jù)類型要保持一致性
  • 查詢列與索引列次序保持一致
  • 拍序列與索引列次序保持一致
  • 對(duì)于復(fù)合索引,SQL語句必須使用主索引列,按照復(fù)合索引組成列的順序書寫
  • 盡量不要對(duì)索引列進(jìn)行計(jì)算,如有特例對(duì)索引列計(jì)算較多,則需要建立函數(shù)索引
  • IN、OP子句常會(huì)使索引失效,在表數(shù)據(jù)記錄數(shù)大于10000條的情況下,考慮把子句拆開
  • 對(duì)于索引的比較,不使用NOT
  • 刪除一個(gè)表的所有數(shù)據(jù)時(shí),使用TRUNCATE,而不是DELETE。不能在事務(wù)中使用該語句,并且務(wù)必確認(rèn)表中數(shù)據(jù)可以全部被刪除

2.2.2.3 SELECT列和WHERE條件規(guī)范

  • 在查詢語句中查詢表達(dá)式左邊不允許出現(xiàn)函數(shù)及其它運(yùn)算表達(dá)式,所有左邊的表達(dá)式都可以用其它的方法實(shí)現(xiàn)
  • WHERE條件中不要使用常量比較,將常量綁定到變量中使用
  • 查找數(shù)據(jù)時(shí)只取出確實(shí)需要的那些列,不要使用 * 來代替所有列名。要清楚明白地使用列名,而不能使用列的序號(hào)
  • 不要order by 和 group by 排序操作。必須使用排序操作時(shí),請(qǐng)遵循如下規(guī)則:

    排序盡量建立在有索引的列上
    查詢結(jié)果集不要求唯一時(shí),使用 union all 代替 union

2.2.2.4 多表連接規(guī)范

  • 在表中的記錄數(shù)低于10萬條的情況下,可以使用多表連接
  • 多表連接時(shí),必須使用表的別名來引用列
  • 使用EXISTS替代DISTINCT表達(dá)方式
#低效:
SELECT DISTINCT DEPT_NO,DEPT_NAME
    FROM DEPT D,EMP E
    WHERE D.DEPT_NO = E.DEPT_NO

#高效:
SELECT DEPT_NO,DEPT_NAME
    FROM DEPT D
    WHERE EXISTS ( SELECT 'X'
                    FROM EMP E
                    WHERE E.DEPT_NO = D.DEPT_NO);

  • 多張大表進(jìn)行JOIN 時(shí)一條 SQL 語句中關(guān)聯(lián)查詢的大表盡量不要超過3個(gè)

2.2.2.5 嵌套查詢規(guī)范

  • 使用 NOT EXIST 代替 NOT IN 子句進(jìn)行嵌套查詢
#例如:
SELECT …
FROM EMP
WHERE DEPT_NO NOT IN (SELECT DEPT_NO 
                         FROM DEPT 
                         WHERE DEPT_CAT='A');
#為了提高效率,改寫成:
SELECT ….
FROM EMP E
WHERE NOT EXISTS (SELECT 'X'
                    FROM DEPT D
                    WHERE D.DEPT_NO = E.DEPT_NO
                    AND DEPT_CAT = 'A');

  • 避免嵌套連接,子查詢(多級(jí)) 如:A = B AND B = C AND C = D

2.2.3 PL/SQL開發(fā)規(guī)范

2.2.3.1 包規(guī)范

  • 按照項(xiàng)目制定的文件組織劃分包內(nèi)容

2.2.3.2 游標(biāo)規(guī)范

  • 外部查詢的多行數(shù)據(jù)返回使用游標(biāo)進(jìn)行處理,通過傳遞游標(biāo)變量的形式返回?cái)?shù)據(jù)到外部接口,由外部程序自行FETCH數(shù)據(jù)
  • 打開游標(biāo)前,必須顯式檢查游標(biāo)的%ISOPEN 屬性
  • 使用FETCH語句后,要立即檢查%NOTFOUND 屬性,以便正常終止游標(biāo)FETCH循環(huán)
  • 無論P(yáng)L/SQL 程序是正常終止還是出錯(cuò)退出,都要關(guān)閉所有已打開的游標(biāo)。在出錯(cuò)退出時(shí),應(yīng)該在其異常處理部分所有游標(biāo),這可以釋放一部分的系統(tǒng)資源
  • 盡可能使用顯式游標(biāo),避免使用隱式游標(biāo)

2.2.3.3 事務(wù)處理規(guī)范

  • 在需要分割事務(wù)以使主事務(wù)的提交或者回滾獨(dú)立于子事務(wù)的提交及回滾時(shí),應(yīng)使用自治事務(wù)
  • 所有的存儲(chǔ)過程均統(tǒng)一在結(jié)束處 COMMIT 或者 ROLLBACK

2.2.3.4 數(shù)據(jù)封裝規(guī)范

  • 按照業(yè)務(wù)邏輯實(shí)現(xiàn)功能模塊的封裝,將業(yè)務(wù)邏輯集中的在更少量的、良好設(shè)計(jì)的、易于維護(hù)的函數(shù)或者過程,不必每條SQL 語句或者每天 PL/SQL程序中重復(fù)這些邏輯
  • 基于單一數(shù)據(jù)表的增、刪、改、查采用標(biāo)準(zhǔn)SP進(jìn)行封裝,不允許同邏輯的處理出現(xiàn)在多個(gè)SP中

2.2.3.5 數(shù)據(jù)訪問規(guī)范

  • 后臺(tái)數(shù)據(jù)按照邏輯劃分成多個(gè)SCHEMA,不同 SCHEMA的數(shù)據(jù)不可互相訪問
  • 需要相互訪問的表均存放在某一個(gè)的SCHEMA 中,通過訪問該SCHEMA 中的接口表實(shí)現(xiàn)跨SCHEMA 的數(shù)據(jù)訪問

2.2.3.6 日志書寫規(guī)范

  • 采用公共的API包完成后臺(tái)日志數(shù)據(jù)記錄(API完成輸出錯(cuò)誤信息提示、記錄錯(cuò)誤信息內(nèi)容到數(shù)據(jù)庫表、系統(tǒng)級(jí)的錯(cuò)誤代碼及錯(cuò)誤信息等)
  • 后臺(tái)日志的信息記錄級(jí)別包括 INFO、WARN、ERROR,其定義以及不同級(jí)別日志的采集標(biāo)準(zhǔn)如下:

    INFO-提示信息,供開發(fā)人員調(diào)試使用,由開發(fā)人員自行確定,主要是調(diào)試信息,程序運(yùn)行中普通信息提示
    WARN-警告信息,可能導(dǎo)致嚴(yán)重錯(cuò)誤的警告信息
    ERROR-錯(cuò)誤信息,導(dǎo)致系統(tǒng)運(yùn)行錯(cuò)誤的信息

  • 所有表操作的錯(cuò)誤處理部分均應(yīng)記錄日志信息

2.2.3.7 錯(cuò)誤處理規(guī)范

  • 凡是涉及到表操作(INSERT,UPDATE,SELECT,DELETE)的SQL語句,都必須進(jìn)行錯(cuò)誤捕捉,不能將錯(cuò)誤帶到后面的語句
  • 錯(cuò)誤信息必須準(zhǔn)確
  • 在每個(gè)異常錯(cuò)誤處理部分,捕捉到的錯(cuò)誤要寫入錯(cuò)誤日志系統(tǒng)
  • 寫入錯(cuò)誤日志函數(shù)統(tǒng)一提供

2.2.3.8 書寫規(guī)范

  • PL/SQL 語句的所有表名、字段名遵照數(shù)據(jù)字典的定義,系統(tǒng)保留字、內(nèi)置函數(shù)名、PL/SQL保留字\關(guān)鍵字大寫,用戶聲明的標(biāo)識(shí)符小寫
  • 對(duì)于子程序、觸發(fā)器、包等帶名的程序塊,使用結(jié)束標(biāo)識(shí)
  • 連接符OR、IN、AND、以及=、<=、>=等前后加上一個(gè)空格
  • 對(duì)較為復(fù)雜的SQL語句加上注釋,說明算法、功能
  • 注釋風(fēng)格:注釋單獨(dú)成行、放在語句前面

    應(yīng)對(duì)不易理解的分支條件表達(dá)式加注釋
    對(duì)重要的計(jì)算應(yīng)說明其功能
    過長(zhǎng)的行數(shù)出現(xiàn),應(yīng)將其語句按實(shí)現(xiàn)的功能分段加以概括性說明
    常量及變量注釋時(shí),應(yīng)注釋保存值的含義(必須),合法取值的范圍
    可采用單行/多行注釋。(-- 或 /* */ 或者 #)

  • SQL語句的縮進(jìn)風(fēng)格

    一行有多列,超過80個(gè)字節(jié)時(shí),基于列對(duì)齊原則,采用下行縮進(jìn)
    WHERE子句書寫時(shí),每個(gè)條件占一行,語句另起一行時(shí),以保留字或者連接符開始,連接符左對(duì)齊。例如:

       WHERE      f1 = 1
       AND        f2 = 2
       OR     f3 = 3
    

    INSERT 語句,必須書寫字段,字段可5個(gè)或者6個(gè)一組,中間用TAB分開
    多表連接時(shí),使用表的別名來引用列
    供別的文件或者函數(shù)調(diào)用的函數(shù),絕不應(yīng)該使用全局變量交換數(shù)據(jù)
    TAB 統(tǒng)一定義為4個(gè)空格,建議使用Ultraedit作為SQL書寫工具

2.2.3.9 書寫優(yōu)化性能建議

  • 避免嵌套連接。例如:A = B AND B = C AND C = D
  • WHERE條件中盡量減少使用常量比較,改用主機(jī)變量
  • 系統(tǒng)可能選擇基于規(guī)則的優(yōu)化器,所以將結(jié)果集返回?cái)?shù)據(jù)量小的表作為驅(qū)動(dòng)表(FROM后邊最后一個(gè)表)
  • 大量的排序操作影響系統(tǒng)性能,所以盡量減少ORDER BY和GROUP BY排序操作。如必須使用排序操作,請(qǐng)遵循如下規(guī)則:

    排序盡量建立在有索引的列上
    如結(jié)果集不需唯一,使用UNION ALL代替UNION

  • 索引的使用

    盡量避免對(duì)索引列進(jìn)行計(jì)算
    盡量注意比較值與索引列數(shù)據(jù)類型的一致性
    對(duì)于復(fù)合索引,SQL語句必須使用主索引列
    索引中,盡量避免使用NULL
    對(duì)于索引的比較,盡量避免使用!= 查詢列和排序列與索引列次序保持一致

  • 盡量避免相同語句由于書寫格式的不同,而導(dǎo)致多次語法分析
  • 盡量使用共享的SQL語句
  • 查詢的WHERE過濾原則,應(yīng)使過濾記錄數(shù)最多的條件放在最前面
  • 任何對(duì)列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫函數(shù)、計(jì)算表達(dá)式等等,查詢時(shí)要盡可能將操作移至等號(hào)右邊
  • IN、OR子句常會(huì)使用工作表,使索引失效;如果不產(chǎn)生大量重復(fù)值,可以考慮把子句拆開;拆開的子句中應(yīng)該包含索引

2.2.3.10 其他經(jīng)驗(yàn)性規(guī)則

  • 盡量少用嵌套查詢。如必須,請(qǐng)用not exist代替not in子句
#錯(cuò)誤寫法
SELECT ......
  FROM emp
  WHERE dept_no NOT IN ( SELECT dept_no  
            FROM dept  
            WHERE dept_cat='A');

#正確寫法
SELECT ......  
    FROM emp e  
    WHERE NOT EXISTS ( SELECT 'X'  
    FROM dept  
    WHERE dept_no=e.dept_no  
    AND dept_cat='A');

  • 用多表連接代替EXISTS子句
#錯(cuò)誤寫法
SELECT ......  
    FROM emp  
    WHERE EXISTS ( SELECT 'X'  
    FROM dept  
    WHERE dept_no=e.dept_no  
    AND dept_cat='A');

#正確寫法
SELECT ......  
    FROM emp e,dept d  
    WHERE e.dept_no=d.dept_no  
    AND dept_cat='A';

  • 少用DISTINCT,用EXISTS代替
#錯(cuò)誤寫法
SELECT DISTINCT d.dept_code,d.dept_name  
    FROM dept d ,emp e  
    WHERE e.dept_code=d.dept_code;


#正確寫法
SELECT dept_code,dept_name  
    FROM dept d  
    WHERE EXISTS ( SELECT 'X'  
    FROM emp e  
    WHERE e.dept_code=d.dept_code);

  • 使用UNION ALL、MINUS、INTERSECT提高性能
  • 使用ROWID提高檢索速度。對(duì)SELECT得到的單行記錄,需進(jìn)行DELETE、UPDATE操作時(shí),使用ROWID將會(huì)使效率大大提高
  • 使用優(yōu)化線索機(jī)制進(jìn)行訪問路徑控制
  • 使用CURSOR時(shí),顯示光標(biāo)優(yōu)于隱式光標(biāo)

3 拓展

3.1 Oracle 與 Mysql之間部分函數(shù)和語法對(duì)比

3.1.1 UUID生成

  • 在 Oracle 中生成隨機(jī)數(shù)UUID的方法是sys_guid()
SELECT sys_guid() FROM dual

SYS_GUID(),是Oracle 8i 后提供的函數(shù)。SYS_GUID產(chǎn)生并返回一個(gè)全球唯一的標(biāo)識(shí)符(原始值)由16個(gè)字節(jié)組成,在Oracle 9i和Oracle 10g生成的是32個(gè)字節(jié)。在大多數(shù)平臺(tái),生成的標(biāo)識(shí)符由主機(jī)標(biāo)符,執(zhí)行函數(shù)的進(jìn)程或者線程標(biāo)識(shí)符,和進(jìn)程或線程的一個(gè)非重復(fù)的值(字節(jié)序列)組成。
可以用來生成唯一標(biāo)識(shí)ID;

  • 在 Mysql 中生成隨機(jī)數(shù)UUID的方法是uuid()
SELECT uuid() FROM dual

MySQL 實(shí)現(xiàn)了 UUID,并且提供 UUID() 函數(shù)方便用戶生成 UUID。在 MySQL 的 UUID() 函數(shù)中,前三組數(shù)字從時(shí)間戳中生成,第四組數(shù)字暫時(shí)保持時(shí)間戳的唯一性,第五組數(shù)字是一個(gè) IEEE 802 節(jié)點(diǎn)標(biāo)點(diǎn)值,保證空間唯一。使用 UUID() 函數(shù),可以生成時(shí)間、空間上都獨(dú)一無二的值。據(jù)說只要是使用了 UUID,都不可能看到兩個(gè)重復(fù)的 UUID 值。當(dāng)然,這個(gè)只是在理論情況下。

比較:本質(zhì)上都是方便用戶生成隨機(jī)的唯一索引,SYS_GUID()生成的是32位的字節(jié);uuid()生成的則是帶4根- 的36位的字節(jié)。

3.1.2 表之間左右連接使用

在關(guān)系型數(shù)據(jù)庫中,左連接使用 LEFT JOIN ……ON……,右連接使用 RIGHT JOIN ……ON……

SELECT t1.* FROM TABLE1 t1 LEFT JOIN TABLE2 t2 ON t1.id = t2.id
SELECT t2.* FROM TABLE1 t1 RIGHT JOIN TABLE2 t2 ON t1.id = t2.id

但是在Oracle中卻有一種簡(jiǎn)化寫法,采用 += 、=+ 來替代左連接和右連接,寫法如下

SELECT t1.* FROM TABLE1 t1 , TABLE2 t2 t1.id += t2.id
SELECT t2.* FROM TABLE1 t1 , TABLE2 t2 t1.id =+ t2.id

3.1.3 判斷并替換null函數(shù)

在Mysql中判斷null函數(shù)并且替換null的函數(shù)是ifnull(exp1,result)

SELECT ifnull(t1.user_name,'張三') as user_name FROM TABLE1 t1

在Oracle中判斷null函數(shù)并且替換null的函數(shù)是nvl(exp1,result)

3.1.4 條件語句(函數(shù))

在Mysql中條件判斷語句可以使用 IF(exp1,exp2,exp3)函數(shù),缺陷是只能判斷單重條件

SELECT 
  IF(t1.user_name='',"zhang san",t1.user_name) as user_name
FROM TABLE1 t1

在Oracle中條件判斷語句可以使用 decode(exp1,result1,exp2,result2,result3)函數(shù),可支持多重判斷

SELECT 
  decode(t1.user_name='',"zhang san",t1.user_name is null,'li si',t1.user_name) as user_name
FROM TABLE1 t1

對(duì)于比較復(fù)雜的多重條件判斷,推薦使用通用的 CASE WHEN 條件 THEN 結(jié)果 WHEN 條件 THEN 結(jié)果 ELSE 結(jié)果 END 這種形式

SELECT 
  CASE WHEN t1.user_name=''THEN 
  "zhang san"
  WHEN t1.user_name is null THEN
  "li si"
  ELSE t1.user_name END as user_name
FROM TABLE1 t1

3.1.4 字符串拼接

字符串拼接是sql中常用到,在Mysql中提供了concat(str1,str2,…strn)和concat_ws(separator,str1,str2,...)

#無添加任何字符拼接
SELECT concat(column1,column2,……) as column_sttr FROM TABLE1;

#各個(gè)字符串之間以'-'拼接
SELECT concat_ws('-',column1,column2,……) as column_sttr FROM TABLE1;

在Oracle中,字符拼接是以 "||" 方式,此種方式顯得更靈活點(diǎn)

SELECT column1 ||column2 || column3 as column_sttr FROM TABLE1;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容