小菜鳥之數據庫

數據庫複習提綱之文字版(這個只是本身整理文案,答案是查的,勿噴,謝謝,但願給別人一些幫助)

 

1Oracle和SQL server2005的區別

Oracle數據庫:Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關係數據庫管理系統html

它是在數據庫領域一直處於領先地位的產品。能夠說Oracle數據庫系統是目前世界上流行的關係數據庫管理系統,系統可移植性好、使用方便、功能強,適用於各種大、中、小、微機環境。它是一種高效率、可靠性好的 適應高吞吐量的數據庫解決方案。java

sql server數據庫:美國Microsoft公司推出的一種關係型數據庫系統。SQL Server是一個可擴展的、高性能的、爲分佈式客戶機/服務器計算所設計的數據庫管理系統,實現了與WindowsNT的有機結合,提供了基於事務的企業級信息管理系統方案程序員

二者的區別:正則表達式

(1)操做的平臺不一樣  redis

  •        Oracle可在全部主流平臺上運行,Oracle數據庫採用開放的策略目標,它使得客戶能夠選擇一種最適合他們特定須要的解決方案。客戶能夠利用不少種第三方應用程序、工具。而SQL Server卻只能在Windows上運行了。
  •   但SQL Sever在Window平臺上的表現,和Windows操做系統的總體結合程度,使用方便性,和Microsoft開發平臺的整合性都比Oracle強的不少。但Windows操做系統的穩定性及可靠性你們是有目共睹的,再說Microsoft公司的策略目標是將客戶都鎖定到Windows平臺的環境當中,只有隨着Windows性能的改善,SQL Server才能進一步提升。從操做平臺這點上Oracle是徹底優勝於SQL Server的了。
  • 也就是說Oracle支持多種操做系統,sql server支持window系統

(2)文體結構不一樣sql

  •    oracle的文件體系結構爲:

    數據文件 .dbf(真實數據)數據庫

    日誌文件 .rdoexpress

    控制文件 .ctl編程

    參數文件 .orawindows

    sql server的文件體系結構爲:

    .mdf (數據字典)

    .ndf (數據文件)

    .ldf (日誌文件)

(3)存儲結構不一樣

  • oracle存儲結構:

    在oracle裏有兩個塊參數pctfree(填充因子)和pctused(複用因子),可控制塊肯定塊自己什麼時候有,什麼時候沒有足夠的空間接受新信息(對塊的存儲狀況的分析機制)

    這樣可下降數據行鏈接與行遷移的可能性。塊的大小可設置(oltp塊和dss塊)

    在oracle中,將連續的塊組成區,可動態分配區(區的分配能夠是等額的也能夠是自增加的)可減小空間分配次數

    在oraclel裏表能夠分爲多個段,段由多個區組成,每一個段可指定分配在哪一個表空間裏(段的類型分爲:數據段、索引段、回滾段、臨時段、cash段。oracle裏還可對錶進行分區,可按照用戶定義的業務規則、條件或規範,物理的分開磁盤上的數據。

    這樣大大下降了磁盤爭用的可能性。

    oracle有七個基本表空間:

    ·system表空間(存放數據字典和數據管理自身所需的信息)

    ·rbs回滾表空間

    ·temp臨時表空間

    ·tools交互式表空間

    ·users用戶默認表空間

    ·indx索引表空間

    ·dbsys福數據表空間

    不一樣的數據分別放在不一樣的表空間(數據字典與真實數據分開存放),在oracle裏基表(存儲系統參數信息)是加密存儲,任何人都沒法訪問。只能經過用戶可視視圖查看。

     

  • sql server 存儲結構

    以頁爲最小分配單位,每一個頁爲8k(不可控制,缺少對頁的存儲狀況的分析機制),可將8個連續的頁的組成一個‘擴展’,以進一步減小分配時所耗用的資源。(分配缺少靈活性),在sql server裏數據以表的方式存放,而表是存放在數據庫裏。

    sql server有五個基本數據庫:  www.2cto.com 

    ·master(數據字典)

    ·mode(存放樣版)

    ·tempdb(臨時數據庫)

    ·msdb(存放調度信息和日誌信息)

    ·pubs(示例數據庫)

    真實數據與數據字典存放在一塊兒。對系統參數信息無安全機制。

(4)安全性

          Oracle的安全認證得到最高認證級別的ISO標準認證,而SQL Server並無得到什麼安全認證。這方面證實了Oracle的安全性是高於SQL Server的。

(5)性能不一樣

SQL Server 多用戶時性能不佳

Oracle 性能最高, 保持windowsNT下的TPC-D和TPC-C的世界記錄。

(6)開放性

SQL Server 只能在windows 上運行,沒有絲毫的開放性,操做系統的系統的穩定對數據庫是十分重要的。Windows9X系列產品是偏重於桌面應用,NT server只適合中小型企業。並且windows平臺的可靠性,安全性和伸縮性是很是有限的。它不象unix那樣久經考驗,尤爲是在處理大數據量的關鍵業務時。

Oracle 能在全部主流平臺上運行(包括 windows)。徹底支持全部的工業標準。採用徹底開放策略。能夠使客戶選擇最適合的解決方案。對開發商全力支持

(7)客戶端支持及應用模式

SQL Server C/S結構,只支持windows客戶,能夠用ADO,DAO,OLEDB ,ODBC鏈接.

Oracle 多層次網絡計算,支持多種工業標準,能夠用ODBC, JDBC,OCI等網絡客戶鏈接

意見:

SQL server 徹底重寫的代碼,經歷了長期的測試,不斷延遲,許多功能須要時間來證實。並不十分兼容早期產品。使用須要冒必定風險。

Oracle 長時間的開發經驗,徹底向下兼容。獲得普遍的應用。徹底沒有風險。

2. 如何使用Oracle的遊標?

遊標的概念:
    遊標是SQL的一個內存工做區,由系統或用戶以變量的形式定義。遊標的做用就是用於臨時存儲從數據庫中提取的數據塊。在某些狀況下,須要把數據從存放在磁盤的表中調到計算機內存中進行處理,最後將處理結果顯示出來或最終寫回數據庫。這樣數據處理的速度纔會提升,不然頻繁的磁盤數據交換會下降效率。
遊標有兩種類型:顯式遊標和隱式遊標。在前述程序中用到的SELECT...INTO...查詢語句,一次只能從數據庫中提取一行數據,對於這種形式的查詢和DML操做,系統都會使用一個隱式遊標。可是若是要提取多行數據,就要由程序員定義一個顯式遊標,並經過與遊標有關的語句進行處理。顯式遊標對應一個返回結果爲多行多列的SELECT語句。
遊標一旦打開,數據就從數據庫中傳送到遊標變量中,而後應用程序再從遊標變量中分解出須要的數據,並進行處理。
隱式遊標
如前所述,DML操做和單行SELECT語句會使用隱式遊標,它們是:
* 插入操做:INSERT。
* 更新操做:UPDATE。
* 刪除操做:DELETE。
* 單行查詢操做:SELECT ... INTO ...。
當系統使用一個隱式遊標時,能夠經過隱式遊標的屬性來了解操做的狀態和結果,進而控制程序的流程。隱式遊標能夠使用名字SQL來訪問,但要注意,經過SQL遊標名老是隻能訪問前一個DML操做或單行SELECT操做的遊標屬性。因此一般在剛剛執行完操做以後,當即使用SQL遊標名來訪問屬性。遊標的屬性有四種,以下所示。

Sql代碼

  1. 隱式遊標的屬性 返回值類型   意    義   
  2. SQL%ROWCOUNT    整型  表明DML語句成功執行的數據行數   
  3. SQL%FOUND   布爾型 值爲TRUE表明插入、刪除、更新或單行查詢操做成功  
  4. SQL%NOTFOUND    布爾型 與SQL%FOUND屬性返回值相反   
  5. SQL%ISOPEN  布爾型 DML執行過程當中爲真,結束後爲假 

【訓練1】 使用隱式遊標的屬性,判斷對僱員工資的修改是否成功。
步驟1:輸入和運行如下程序:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. BEGIN
  3. UPDATE emp SET sal=sal+100 WHERE empno=1234;  
  4.          IF SQL%FOUND THEN
  5.         DBMS_OUTPUT.PUT_LINE('成功修改僱員工資!');  
  6. COMMIT;   
  7. ELSE
  8.         DBMS_OUTPUT.PUT_LINE('修改僱員工資失敗!');  
  9. END IF;   
  10. END; 

運行結果爲:

Sql代碼

  1. 修改僱員工資失敗!   
  2.         PL/SQL 過程已成功完成。 

步驟2:將僱員編號1234改成7788,從新執行以上程序:
運行結果爲:

Sql代碼

  1. 成功修改僱員工資!   
  2.         PL/SQL 過程已成功完成。 

說明:本例中,經過SQL%FOUND屬性判斷修改是否成功,並給出相應信息。
顯式遊標
遊標的定義和操做
遊標的使用分紅如下4個步驟。
1.聲明遊標
在DECLEAR部分按如下格式聲明遊標:
CURSOR 遊標名[(參數1 數據類型[,參數2 數據類型...])]
IS SELECT語句;
參數是可選部分,所定義的參數能夠出如今SELECT語句的WHERE子句中。若是定義了參數,則必須在打開遊標時傳遞相應的實際參數。
SELECT語句是對錶或視圖的查詢語句,甚至也能夠是聯合查詢。能夠帶WHERE條件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT語句中能夠使用在定義遊標以前定義的變量。
2.打開遊標
在可執行部分,按如下格式打開遊標:
OPEN 遊標名[(實際參數1[,實際參數2...])];
打開遊標時,SELECT語句的查詢結果就被傳送到了遊標工做區。
3.提取數據
在可執行部分,按如下格式將遊標工做區中的數據取到變量中。提取操做必須在打開遊標以後進行。
FETCH 遊標名 INTO 變量名1[,變量名2...];

FETCH 遊標名 INTO 記錄變量;
遊標打開後有一個指針指向數據區,FETCH語句一次返回指針所指的一行數據,要返回多行需重複執行,能夠使用循環語句來實現。控制循環能夠經過判斷遊標的屬性來進行。
下面對這兩種格式進行說明:
第一種格式中的變量名是用來從遊標中接收數據的變量,須要事先定義。變量的個數和類型應與SELECT語句中的字段變量的個數和類型一致。
第二種格式一次將一行數據取到記錄變量中,須要使用%ROWTYPE事先定義記錄變量,這種形式使用起來比較方便,沒必要分別定義和使用多個變量。
定義記錄變量的方法以下:
變量名 表名|遊標名%ROWTYPE;
其中的表必須存在,遊標名也必須先定義。
4.關閉遊標
CLOSE 遊標名;
顯式遊標打開後,必須顯式地關閉。遊標一旦關閉,遊標佔用的資源就被釋放,遊標變成無效,必須從新打開才能使用。
如下是使用顯式遊標的一個簡單練習。
【訓練1】  用遊標提取emp表中7788僱員的名稱和職務。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.          v_ename VARCHAR2(10);   
  4.          v_job VARCHAR2(10);   
  5. CURSOR emp_cursor IS
  6. SELECT ename,job FROM emp WHERE empno=7788;  
  7. BEGIN
  8. OPEN emp_cursor;  
  9. FETCH emp_cursor INTO v_ename,v_job;  
  10.         DBMS_OUTPUT.PUT_LINE(v_ename||','||v_job);  
  11. CLOSE emp_cursor;  
  12. END; 

執行結果爲:

Sql代碼

  1. SCOTT,ANALYST   
  2.         PL/SQL 過程已成功完成。  

說明:該程序經過定義遊標emp_cursor,提取並顯示僱員7788的名稱和職務。
做爲對以上例子的改進,在如下訓練中採用了記錄變量。
【訓練2】  用遊標提取emp表中7788僱員的姓名、職務和工資。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. CURSOR emp_cursor IS SELECT ename,job,sal FROM emp WHERE empno=7788;  
  4.          emp_record emp_cursor%ROWTYPE;   
  5. BEGIN
  6. OPEN emp_cursor;      
  7. FETCH emp_cursor INTO emp_record;  
  8.            DBMS_OUTPUT.PUT_LINE(emp_record.ename||','|| emp_record.job||','|| emp_record.sal);  
  9. CLOSE emp_cursor;  
  10. END; 

執行結果爲:

Sql代碼

  1. SCOTT,ANALYST,3000   
  2.         PL/SQL 過程已成功完成。  

說明:實例中使用記錄變量來接收數據,記錄變量由遊標變量定義,須要出如今遊標定義以後。
注意:可經過如下形式得到記錄變量的內容:
記錄變量名.字段名。
【訓練3】  顯示工資最高的前3名僱員的名稱和工資。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.          V_ename VARCHAR2(10);   
  4.         V_sal NUMBER(5);   
  5. CURSOR emp_cursor IS SELECT ename,sal FROM emp ORDER BY sal DESC;  
  6. BEGIN
  7. OPEN emp_cursor;  
  8. FOR I IN 1..3 LOOP  
  9. FETCH emp_cursor INTO v_ename,v_sal;  
  10.          DBMS_OUTPUT.PUT_LINE(v_ename||','||v_sal);  
  11. END LOOP;  
  12. CLOSE emp_cursor;  
  13. END; 

執行結果爲:

Sql代碼

  1. KING,5000   
  2.      SCOTT,3000   
  3.      FORD,3000   
  4.      PL/SQL 過程已成功完成。 

  說明:該程序在遊標定義中使用了ORDER BY子句進行排序,並使用循環語句來提取多行數據。
遊標循環
【訓練1】  使用特殊的FOR循環形式顯示所有僱員的編號和名稱。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. CURSOR emp_cursor IS
  4. SELECT empno, ename FROM emp;  
  5. BEGIN
  6. FOR Emp_record IN emp_cursor LOOP     
  7.     DBMS_OUTPUT.PUT_LINE(Emp_record.empno|| Emp_record.ename);   
  8. END LOOP;  
  9. END; 

執行結果爲:

Sql代碼

  1. 7369SMITH   
  2. 7499ALLEN   
  3. 7521WARD   
  4. 7566JONES   
  5.          PL/SQL 過程已成功完成。 

  說明:能夠看到該循環形式很是簡單,隱含了記錄變量的定義、遊標的打開、提取和關閉過程。Emp_record爲隱含定義的記錄變量,循環的執行次數與遊標取得的數據的行數相一致。
【訓練2】  另外一種形式的遊標循環。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. BEGIN
  3. FOR re IN (SELECT ename FROM EMP)  LOOP  
  4.   DBMS_OUTPUT.PUT_LINE(re.ename)   
  5. END LOOP;  
  6. END; 

執行結果爲:

Sql代碼

  1. SMITH   
  2. ALLEN   
  3. WARD   
  4. JONES 

    說明:該種形式更爲簡單,省略了遊標的定義,遊標的SELECT查詢語句在循環中直接出現。
顯式遊標屬性
雖然能夠使用前面的形式得到遊標數據,可是在遊標定義之後使用它的一些屬性來進行結構控制是一種更爲靈活的方法。顯式遊標的屬性以下所示。

Sql代碼

  1. 遊標的屬性   返回值類型   意    義   
  2. %ROWCOUNT   整型  得到FETCH語句返回的數據行數  
  3. %FOUND  布爾型 最近的FETCH語句返回一行數據則爲真,不然爲假  
  4. %NOTFOUND   布爾型 與%FOUND屬性返回值相反   
  5. %ISOPEN 布爾型 遊標已經打開時值爲真,不然爲假 

可按照如下形式取得遊標的屬性:
遊標名%屬性
要判斷遊標emp_cursor是否處於打開狀態,能夠使用屬性emp_cursor%ISOPEN。若是遊標已經打開,則返回值爲「真」,不然爲「假」。具體可參照如下的訓練。
【訓練1】  使用遊標的屬性練習。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.   V_ename VARCHAR2(10);   
  4. CURSOR emp_cursor IS
  5. SELECT ename FROM emp;  
  6. BEGIN
  7. OPEN emp_cursor;  
  8. IF emp_cursor%ISOPEN THEN
  9. LOOP   
  10. FETCH emp_cursor INTO v_ename;  
  11.    EXIT WHEN emp_cursor%NOTFOUND;  
  12.    DBMS_OUTPUT.PUT_LINE(to_char(emp_cursor%ROWCOUNT)||'-'||v_ename);  
  13. END LOOP;  
  14. ELSE
  15.   DBMS_OUTPUT.PUT_LINE('用戶信息:遊標沒有打開!');  
  16. END IF;  
  17. CLOSE  emp_cursor;  
  18. END; 

執行結果爲:

Sql代碼

  1. 1-SMITH   
  2. 2-ALLEN   
  3. 3-WARD   
  4. PL/SQL 過程已成功完成。 

    說明:本例使用emp_cursor%ISOPEN判斷遊標是否打開;使用emp_cursor%ROWCOUNT得到到目前爲止FETCH語句返回的數據行數並輸出;使用循環來獲取數據,在循環體中使用FETCH語句;使用emp_cursor%NOTFOUND判斷FETCH語句是否成功執行,當FETCH語句失敗時說明數據已經取完,退出循環。
【練習1】去掉OPEN emp_cursor;語句,從新執行以上程序。
遊標參數的傳遞
【訓練1】  帶參數的遊標。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.             V_empno NUMBER(5);   
  4.             V_ename VARCHAR2(10);   
  5. CURSOR  emp_cursor(p_deptno NUMBER,     p_job VARCHAR2) IS
  6. SELECT  empno, ename FROM emp  
  7. WHERE   deptno = p_deptno AND job = p_job;  
  8. BEGIN
  9. OPEN emp_cursor(10, 'CLERK');  
  10.     LOOP   
  11. FETCH emp_cursor INTO v_empno,v_ename;  
  12.      EXIT WHEN emp_cursor%NOTFOUND;  
  13.      DBMS_OUTPUT.PUT_LINE(v_empno||','||v_ename);  
  14. END LOOP;  
  15. END; 

執行結果爲:

Sql代碼

  1. 7934,MILLER   
  2.         PL/SQL 過程已成功完成。 

說明:遊標emp_cursor定義了兩個參數:p_deptno表明部門編號,p_job表明職務。語句OPEN emp_cursor(10, 'CLERK')傳遞了兩個參數值給遊標,即部門爲十、職務爲CLERK,因此遊標查詢的內容是部門10的職務爲CLERK的僱員。循環部分用於顯示查詢的內容。
【練習1】修改Open語句的參數:部門號爲20、職務爲ANALYST,並從新執行。
也能夠經過變量向遊標傳遞參數,但變量須要先於遊標定義,並在遊標打開以前賦值。對以上例子從新改動以下:
  【訓練2】  經過變量傳遞參數給遊標。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.         v_empno NUMBER(5);   
  4.         v_ename VARCHAR2(10);   
  5.         v_deptno NUMBER(5);   
  6. v_job VARCHAR2(10);   
  7. CURSOR emp_cursor IS
  8. SELECT empno, ename FROM emp  
  9. WHERE   deptno = v_deptno AND job = v_job;  
  10. BEGIN
  11.          v_deptno:=10;   
  12.          v_job:='CLERK';  
  13. OPEN emp_cursor;  
  14.         LOOP   
  15. FETCH emp_cursor INTO v_empno,v_ename;  
  16.            EXIT WHEN emp_cursor%NOTFOUND;  
  17. DBMS_OUTPUT.PUT_LINE(v_empno||','||v_ename);  
  18. END LOOP;  
  19. END; 

執行結果爲:

Sql代碼

  1. 7934,MILLER   
  2.         PL/SQL 過程已成功完成。 

說明:該程序與前一程序實現相同的功能。
動態SELECT語句和動態遊標的用法
Oracle支持動態SELECT語句和動態遊標,動態的方法大大擴展了程序設計的能力。
對於查詢結果爲一行的SELECT語句,能夠用動態生成查詢語句字符串的方法,在程序執行階段臨時地生成並執行,語法是:
execute immediate 查詢語句字符串 into 變量1[,變量2...];
如下是一個動態生成SELECT語句的例子。
【訓練1】  動態SELECT查詢。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.         str varchar2(100);   
  4.         v_ename varchar2(10);   
  5. begin
  6.         str:='select ename from scott.emp where empno=7788';  
  7. execute immediate str into v_ename;   
  8.         dbms_output.put_line(v_ename);   
  9. END;  

執行結果爲:

Sql代碼

  1. SCOTT   
  2.         PL/SQL 過程已成功完成。 

說明:SELECT...INTO...語句存放在STR字符串中,經過EXECUTE語句執行。
在變量聲明部分定義的遊標是靜態的,不能在程序運行過程當中修改。雖然能夠經過參數傳遞來取得不一樣的數據,但仍是有很大的侷限性。經過採用動態遊標,能夠在程序運行階段隨時生成一個查詢語句做爲遊標。要使用動態遊標須要先定義一個遊標類型,而後聲明一個遊標變量,遊標對應的查詢語句能夠在程序的執行過程當中動態地說明。
定義遊標類型的語句以下:
TYPE 遊標類型名 REF CURSOR;
聲明遊標變量的語句以下:
遊標變量名 遊標類型名;
在可執行部分能夠以下形式打開一個動態遊標:
OPEN 遊標變量名 FOR 查詢語句字符串;
【訓練2】  按名字中包含的字母順序分組顯示僱員信息。
輸入並運行如下程序:

Sql代碼

  1. declare
  2. type cur_type is ref cursor;  
  3. cur cur_type;   
  4. rec scott.emp%rowtype;   
  5. str varchar2(50);   
  6. letter char:= 'A';  
  7. begin
  8.         loop           
  9.          str:= 'select ename from emp where ename like ''%'||letter||'%''';  
  10. open cur for str;  
  11.          dbms_output.put_line('包含字母'||letter||'的名字:');  
  12.           loop   
  13. fetch cur into rec.ename;  
  14.          exit when cur%notfound;  
  15.         dbms_output.put_line(rec.ename);   
  16. end loop;  
  17.   exit when letter='Z';  
  18.   letter:=chr(ascii(letter)+1);   
  19. end loop;  
  20. end; 

運行結果爲:

Sql代碼

  1. 包含字母A的名字:   
  2. ALLEN   
  3. WARD   
  4. MARTIN   
  5. BLAKE   
  6. CLARK   
  7. ADAMS   
  8. JAMES   
  9. 包含字母B的名字:   
  10. BLAKE   
  11. 包含字母C的名字:   
  12. CLARK   
  13. SCOTT 

說明:使用了二重循環,在外循環體中,動態生成遊標的SELECT語句,而後打開。經過語句letter:=chr(ascii(letter)+1)可得到字母表中的下一個字母。
異常處理
錯誤處理
錯誤處理部分位於程序的可執行部分以後,是由WHEN語句引導的多個分支構成的。錯誤處理的語法以下:
EXCEPTION
WHEN 錯誤1[OR 錯誤2] THEN
語句序列1;
WHEN 錯誤3[OR 錯誤4] THEN
語句序列2;
WHEN OTHERS
語句序列n;
END;
其中:
錯誤是在標準包中由系統預約義的標準錯誤,或是由用戶在程序的說明部分自定義的錯誤,參見下一節系統預約義的錯誤類型。
語句序列就是不一樣分支的錯誤處理部分。
凡是出如今WHEN後面的錯誤都是能夠捕捉到的錯誤,其餘未被捕捉到的錯誤,將在WHEN OTHERS部分進行統一處理,OTHENS必須是EXCEPTION部分的最後一個錯誤處理分支。如要在該分支中進一步判斷錯誤種類,能夠經過使用預約義函數SQLCODE( )和SQLERRM( )來得到系統錯誤號和錯誤信息。
若是在程序的子塊中發生了錯誤,但子塊沒有錯誤處理部分,則錯誤會傳遞到主程序中。
下面是因爲查詢編號錯誤而引發系統預約義異常的例子。
【訓練1】  查詢編號爲1234的僱員名字。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. v_name VARCHAR2(10);   
  4. BEGIN
  5. SELECT   ename  
  6. INTO     v_name  
  7. FROM     emp  
  8. WHERE    empno = 1234;  
  9. DBMS_OUTPUT.PUT_LINE('該僱員名字爲:'|| v_name);  
  10. EXCEPTION   
  11. WHEN NO_DATA_FOUND THEN
  12.     DBMS_OUTPUT.PUT_LINE('編號錯誤,沒有找到相應僱員!');  
  13. WHEN OTHERS THEN
  14.     DBMS_OUTPUT.PUT_LINE('發生其餘錯誤!');  
  15. END; 

執行結果爲:

Sql代碼

  1. 編號錯誤,沒有找到相應僱員!   
  2.         PL/SQL 過程已成功完成。 

說明:在以上查詢中,由於編號爲1234的僱員不存在,因此將發生類型爲「NO_DATA_
FOUND」的異常。「NO_DATA_FOUND」是系統預約義的錯誤類型,EXCEPTION部分下的WHEN語句將捕捉到該異常,並執行相應代碼部分。在本例中,輸出用戶自定義的錯誤信息「編號錯誤,沒有找到相應僱員!」。若是發生其餘類型的錯誤,將執行OTHERS條件下的代碼部分,顯示「發生其餘錯誤!」。
【訓練2】  由程序代碼顯示系統錯誤。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. v_temp NUMBER(5):=1;   
  4. BEGIN
  5. v_temp:=v_temp/0;   
  6. EXCEPTION   
  7. WHEN OTHERS THEN
  8. DBMS_OUTPUT.PUT_LINE('發生系統錯誤!');  
  9.     DBMS_OUTPUT.PUT_LINE('錯誤代碼:'|| SQLCODE( ));  
  10.     DBMS_OUTPUT.PUT_LINE('錯誤信息:' ||SQLERRM( ));  
  11. END; 

執行結果爲:

Sql代碼

  1. 發生系統錯誤!   
  2.         錯誤代碼:?1476   
  3.         錯誤信息:ORA-01476: 除數爲 0   
  4.         PL/SQL 過程已成功完成。 

說明:程序運行中發生除零錯誤,由WHEN OTHERS捕捉到,執行用戶本身的輸出語句顯示錯誤信息,而後正常結束。在錯誤處理部分使用了預約義函數SQLCODE( )和SQLERRM( )來進一步得到錯誤的代碼和種類信息。
預約義錯誤
Oracle的系統錯誤不少,但只有一部分常見錯誤在標準包中予以定義。定義的錯誤能夠在EXCEPTION部分經過標準的錯誤名來進行判斷,並進行異常處理。常見的系統預約義異常以下所示。

Sql代碼

  1. 錯 誤 名 稱 錯誤代碼    錯 誤 含 義   
  2. CURSOR_ALREADY_OPEN ORA_06511   試圖打開已經打開的遊標   
  3. INVALID_CURSOR  ORA_01001   試圖使用沒有打開的遊標   
  4. DUP_VAL_ON_INDEX    ORA_00001   保存重複值到唯一索引約束的列中   
  5. ZERO_DIVIDE ORA_01476   發生除數爲零的除法錯誤   
  6. INVALID_NUMBER  ORA_01722   試圖對無效字符進行數值轉換   
  7. ROWTYPE_MISMATCH    ORA_06504   主變量和遊標的類型不兼容   
  8. VALUE_ERROR ORA_06502   轉換、截斷或算術運算髮生錯誤   
  9. TOO_MANY_ROWS   ORA_01422   SELECT…INTO…語句返回多於一行的數據  
  10. NO_DATA_FOUND   ORA_01403   SELECT…INTO…語句沒有數據返回  
  11. TIMEOUT_ON_RESOURCE ORA_00051   等待資源時發生超時錯誤   
  12. TRANSACTION_BACKED_OUT  ORA_00060   因爲死鎖,提交失敗   
  13. STORAGE_ERROR   ORA_06500   發生內存錯誤   
  14. PROGRAM_ERROR   ORA_06501   發生PL/SQL內部錯誤   
  15. NOT_LOGGED_ON   ORA_01012   試圖操做未鏈接的數據庫   
  16. LOGIN_DENIED    ORA_01017   在鏈接時提供了無效用戶名或口令 

好比,若是程序向表的主鍵列插入重複值,則將發生DUP_VAL_ON_INDEX錯誤。
若是一個系統錯誤沒有在標準包中定義,則須要在說明部分定義,語法以下:
錯誤名 EXCEPTION;
定義後使用PRAGMA EXCEPTION_INIT來將一個定義的錯誤同一個特別的Oracle錯誤代碼相關聯,就能夠同系統預約義的錯誤同樣使用了。語法以下:
PRAGMA EXCEPTION_INIT(錯誤名,- 錯誤代碼);
【訓練1】  定義新的系統錯誤類型。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.         V_ENAME VARCHAR2(10);   
  4.         NULL_INSERT_ERROR EXCEPTION;   
  5.         PRAGMA EXCEPTION_INIT(NULL_INSERT_ERROR,-1400);   
  6. BEGIN
  7. INSERT INTO EMP(EMPNO) VALUES(NULL);  
  8. EXCEPTION   
  9. WHEN NULL_INSERT_ERROR THEN
  10.     DBMS_OUTPUT.PUT_LINE('沒法插入NULL值!');  
  11. WHEN OTHERS  THEN
  12.     DBMS_OUTPUT.PUT_LINE('發生其餘系統錯誤!');  
  13. END; 

執行結果爲:

Sql代碼

  1. 沒法插入NULL值!  
  2.         PL/SQL 過程已成功完成。 

  說明:NULL_INSERT_ERROR是自定義異常,同系統錯誤1400相關聯。
自定義異常
程序設計者能夠利用引起異常的機制來進行程序設計,本身定義異常類型。能夠在聲明部分定義新的異常類型,定義的語法是:
錯誤名 EXCEPTION;
用戶定義的錯誤不能由系統來觸發,必須由程序顯式地觸發,觸發的語法是:
RAISE 錯誤名;
RAISE也能夠用來引起模擬系統錯誤,好比,RAISE ZERO_DIVIDE將引起模擬的除零錯誤。
使用RAISE_APPLICATION_ERROR函數也能夠引起異常。該函數要傳遞兩個參數,第一個是用戶自定義的錯誤編號,第二個參數是用戶自定義的錯誤信息。使用該函數引起的異常的編號應該在20 000和20 999之間選擇。
自定義異常處理錯誤的方式同前。
【訓練1】  插入新僱員,限定插入僱員的編號在7000~8000之間。

Java代碼

  1. SET SERVEROUTPUT ON   
  2. DECLARE   
  3. new_no NUMBER(10);  
  4. new_excp1 EXCEPTION;   
  5. new_excp2 EXCEPTION;   
  6. BEGIN   
  7. new_no:=6789;  
  8. INSERT INTO emp(empno,ename)   
  9.   VALUES(new_no, '小鄭');  
  10.   IF new_no<7000 THEN  
  11.     RAISE new_excp1;   
  12.   END IF;   
  13.   IF new_no>8000 THEN  
  14.     RAISE new_excp2;   
  15.   END IF;   
  16.   COMMIT;   
  17. EXCEPTION   
  18. WHEN new_excp1  THEN   
  19.     ROLLBACK;   
  20.     DBMS_OUTPUT.PUT_LINE('僱員編號小於7000的下限!');  
  21.     WHEN new_excp2  THEN   
  22.     ROLLBACK;   
  23.     DBMS_OUTPUT.PUT_LINE('僱員編號超過8000的上限!');  
  24.     END; 

執行結果爲:
僱員編號小於7000的下限!
PL/SQL 過程已成功完成。
說明:在此例中,自定義了兩個異常:new_excp1和new_excp2,分別表明編號小於7000和編號大於8000的錯誤。在程序中經過判斷編號大小,產生對應的異常,並在異常處理部分回退插入操做,而後顯示相應的錯誤信息。
【訓練2】  使用RAISE_APPLICATION_ERROR函數引起系統異常。

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. New_no NUMBER(10);   
  4. BEGIN
  5.   New_no:=6789;   
  6. INSERT INTO    emp(empno,ename)  
  7. VALUES(new_no, 'JAMES');  
  8. IF new_no<7000 THEN
  9. ROLLBACK;  
  10.     RAISE_APPLICATION_ERROR(-20001, '編號小於7000的下限!');  
  11. END IF;  
  12.   IF new_no>8000 THEN
  13. ROLLBACK;  
  14.     RAISE_APPLICATION_ERROR (-20002, '編號大於8000的下限!');  
  15. END IF;  
  16. END; 

執行結果爲:

Sql代碼

  1. DECLARE
  2.         *   
  3.         ERROR 位於第 1 行:   
  4.         ORA-20001: 編號小於7000的下限!   
  5.         ORA-06512: 在line 9 

  說明:在本訓練中,使用RAISE_APPLICATION_ERROR引起自定義異常,並以系統錯誤的方式進行顯示。錯誤編號爲20001和20002。
注意:同上一個訓練比較,此種方法不須要事先定義異常,可直接引起。
能夠參考下面的程序片段將出錯信息記錄到表中,其中,errors爲記錄錯誤信息的表,SQLCODE爲發生異常的錯誤編號,SQLERRM爲發生異常的錯誤信息。
DECLARE
  v_error_code      NUMBER;
  v_error_message   VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
    v_error_code := SQLCODE ;
    v_error_message := SQLERRM ;
    INSERT INTO errors
    VALUES(v_error_code, v_error_message);
END;
  【練習1】修改僱員的工資,經過引起異常控制修改範圍在600~6000之間。
階段訓練
【訓練1】  將僱員從一個表複製到另外一個表。
步驟1:建立一個結構同EMP表同樣的新表EMP1:
CREATE TABLE emp1 AS SELECT * FROM SCOTT.EMP WHERE 1=2;
步驟2:經過指定僱員編號,將僱員由EMP表移動到EMP1表:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. v_empno NUMBER(5):=7788;   
  4. emp_rec emp%ROWTYPE;   
  5. BEGIN
  6. SELECT * INTO emp_rec FROM emp WHERE empno=v_empno;  
  7. DELETE FROM emp WHERE empno=v_empno;  
  8. INSERT INTO emp1 VALUES emp_rec;  
  9. IF SQL%FOUND THEN
  10. COMMIT;  
  11.   DBMS_OUTPUT.PUT_LINE('僱員複製成功!');  
  12. ELSE
  13. ROLLBACK;  
  14.   DBMS_OUTPUT.PUT_LINE('僱員複製失敗!');  
  15. END IF;  
  16. END; 

執行結果爲:
僱員複製成功!
PL/SQL 過程已成功完成。
步驟2:顯示覆制結果:
SELECT empno,ename,job FROM emp1;
執行結果爲:

Sql代碼

  1. EMPNO ENAME      JOB   
  2. ------------- -------------- ----------------  
  3.     7788  SCOTT      ANALYST 

說明:emp_rec變量是根據emp表定義的記錄變量,SELECT...INTO...語句將整個記錄傳給該變量。INSERT語句將整個記錄變量插入emp1表,若是插入成功(SQL%FOUND爲真),則提交事務,不然回滾撤銷事務。試修改僱員編號爲7902,從新執行以上程序。
【訓練2】  輸出僱員工資,僱員工資用不一樣高度的*表示。
輸入並執行如下程序:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. BEGIN
  3. FOR re IN (SELECT ename,sal FROM EMP)  LOOP  
  4.   DBMS_OUTPUT.PUT_LINE(rpad(re.ename,12,' ')||rpad('*',re.sal/100,'*'));  
  5. END LOOP;  
  6. END; 

輸出結果爲:

Sql代碼

  1. SMITH       ********   
  2. ALLEN           ****************   
  3. WARD        *************   
  4. JONES           ******************************   
  5. MARTIN      *************   
  6. BLAKE       *****************************   
  7. CLARK           *****************************   
  8. SCOTT           ******************************   
  9. KING            **************************************************   
  10. TURNER      ***************   
  11. ADAMS       ***********   
  12. JAMES           **********   
  13. FORD            ******************************   
  14. MILLER          *************   
  15.          執行結果爲:   
  16.         PL/SQL 過程已成功完成。 

  說明:第一個rpad函數產生對齊效果,第二個rpad函數根據工資額產生不一樣數目的*。該程序採用了隱式的簡略遊標循環形式。
【訓練3】  編寫程序,格式化輸出部門信息。
輸入並執行以下程序:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.          v_count number:=0;   
  4. CURSOR dept_cursor IS SELECT * FROM dept;  
  5. BEGIN
  6.           DBMS_OUTPUT.PUT_LINE('部門列表');  
  7. DBMS_OUTPUT.PUT_LINE('---------------------------------');  
  8. FOR Dept_record IN dept_cursor LOOP     
  9.          DBMS_OUTPUT.PUT_LINE('部門編號:'|| Dept_record.deptno);  
  10.          DBMS_OUTPUT.PUT_LINE('部門名稱:'|| Dept_record.dname);  
  11.             DBMS_OUTPUT.PUT_LINE('所在城市:'|| Dept_record.loc);  
  12. DBMS_OUTPUT.PUT_LINE('---------------------------------');  
  13.       v_count:= v_count+1;   
  14. END LOOP;  
  15.          DBMS_OUTPUT.PUT_LINE('共有'||to_char(v_count)||'個部門!');  
  16. END; 

輸出結果爲:

Sql代碼

  1. 部門列表   
  2. ------------------------------------  
  3. 部門編號:10   
  4. 部門名稱:ACCOUNTING   
  5. 所在城市:NEW YORK   
  6. ------------------------------------  
  7. 部門編號:20   
  8. 部門名稱:RESEARCH   
  9. 所在城市:DALLAS   
  10. ...   
  11. 共有4個部門!   
  12. PL/SQL 過程已成功完成。 

  說明:該程序中將字段內容垂直排列。V_count變量記錄循環次數,即部門個數。
【訓練4】  已知每一個部門有一個經理,編寫程序,統計輸出部門名稱、部門總人數、總工資和部門經理。
輸入並執行以下程序:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3. v_deptno number(8);   
  4. v_count number(3);   
  5. v_sumsal number(6);   
  6. v_dname  varchar2(15);   
  7. v_manager  varchar2(15);   
  8. CURSOR list_cursor IS
  9. SELECT deptno,count(*),sum(sal) FROM emp group by deptno;  
  10. BEGIN
  11. OPEN list_cursor;   
  12.   DBMS_OUTPUT.PUT_LINE('----------- 部 門 統 計 表 -----------');  
  13. DBMS_OUTPUT.PUT_LINE('部門名稱   總人數  總工資   部門經理');  
  14. FETCH list_cursor INTO v_deptno,v_count,v_sumsal;   
  15.   WHILE list_cursor%found LOOP     
  16. SELECT dname INTO v_dname FROM dept  
  17. WHERE deptno=v_deptno;  
  18. SELECT ename INTO v_manager FROM emp   
  19. WHERE deptno=v_deptno and job='MANAGER';  
  20. DBMS_OUTPUT.PUT_LINE(rpad(v_dname,13)||rpad(to_char(v_count),8)   
  21.       ||rpad(to_char(v_sumsal),9)||v_manager);   
  22. FETCH list_cursor INTO v_deptno,v_count,v_sumsal;   
  23. END LOOP;  
  24.         DBMS_OUTPUT.PUT_LINE('--------------------------------------');  
  25. CLOSE list_cursor;  
  26. END; 

輸出結果爲:

Sql代碼

  1. -------------------- 部 門 統 計 表 -----------------  
  2.         部門名稱     總人數  總工資     部門經理   
  3.         ACCOUNTING    3      8750       CLARK   
  4.         RESEARCH      5     10875       JONES   
  5.         SALES             6      9400       BLAKE   
  6. -------------------------------------------------------------  
  7.         PL/SQL 過程已成功完成。  

說明:遊標中使用到了起分組功能的SELECT語句,統計出各部門的總人數和總工資。再根據部門編號和職務找到部門的經理。該程序假定每一個部門有一個經理。
【訓練5】  爲僱員增長工資,從工資低的僱員開始,爲每一個人增長原工資的10%,限定所增長的工資總額爲800元,顯示增長工資的人數和餘額。
輸入並調試如下程序:

Sql代碼

  1. SET SERVEROUTPUT ON
  2. DECLARE
  3.   V_NAME CHAR(10);  
  4.   V_EMPNO NUMBER(5);   
  5.   V_SAL NUMBER(8);   
  6.   V_SAL1 NUMBER(8);   
  7.   V_TOTAL NUMBER(8) := 800;     --增長工資的總額  
  8. V_NUM NUMBER(5):=0;     --增長工資的人數  
  9. CURSOR emp_cursor IS
  10. SELECT EMPNO,ENAME,SAL FROM EMP ORDER BY SAL ASC;  
  11. BEGIN
  12. OPEN emp_cursor;  
  13.         DBMS_OUTPUT.PUT_LINE('姓名      原工資  新工資');   
  14.         DBMS_OUTPUT.PUT_LINE('---------------------------');   
  15.          LOOP   
  16. FETCH emp_cursor INTO V_EMPNO,V_NAME,V_SAL;  
  17. EXIT WHEN emp_cursor%NOTFOUND;  
  18.          V_SAL1:= V_SAL*0.1;   
  19.             IF V_TOTAL>V_SAL1 THEN
  20.             V_TOTAL := V_TOTAL - V_SAL1;   
  21.             V_NUM:=V_NUM+1;   
  22.     DBMS_OUTPUT.PUT_LINE(V_NAME||TO_CHAR(V_SAL,'99999')||  
  23.         TO_CHAR(V_SAL+V_SAL1,'99999'));  
  24. UPDATE EMP SET SAL=SAL+V_SAL1  
  25. WHERE EMPNO=V_EMPNO;  
  26. ELSE
  27. DBMS_OUTPUT.PUT_LINE(V_NAME||TO_CHAR(V_SAL,'99999')||TO_CHAR(V_SAL,'99999'));  
  28. END IF;  
  29. END LOOP;  
  30.         DBMS_OUTPUT.PUT_LINE('---------------------------');  
  31.         DBMS_OUTPUT.PUT_LINE('增長工資人數:'||V_NUM||' 剩餘工資:'||V_TOTAL);    
  32. CLOSE emp_cursor;   
  33. COMMIT;  
  34. END; 

輸出結果爲:

Sql代碼

  1. 姓名        原工資  新工資   
  2. ---------------------------------------------  
  3. SMITH       1289   1418   
  4. JAMES       1531   1684   
  5. MARTIN      1664   1830   
  6. MILLER          1730   1903   
  7. ALLEN           1760   1936   
  8. ADAMS       1771   1771   
  9. TURNER      1815   1815   
  10. WARD        1830   1830   
  11. BLAKE       2850   2850   
  12. CLARK       2850   2850   
  13. JONES           2975   2975   
  14. FORD            3000   3000   
  15. KING            5000   5000   
  16. -----------------------------------------------  
  17. 增長工資人數:5 剩餘工資:3   
  18. PL/SQL 過程已成功完成。 

 

3. Oracle中function和procedure的區別?

Oracle 存儲過程(procedure)和函數(Function)的區別

一、返回值的區別

函數有1個返回值,而存儲過程是經過參數返回的,能夠有多個或者沒有

2. 調用的區別,函數能夠在查詢語句中直接調用,而存儲過程必須單獨調用.

函數:通常狀況下是用來計算並返回一個計算結果;

存儲過程: 通常是用來完成特定的數據操做(好比修改、插入數據庫表或執行某些DDL語句等等)

下圖說明它們之間的區別:

Oracle 存儲過程(procedure)和函數(Function)的區別

 

4. Oracle的導入導出有幾種方式,有何區別?

1.dmp文件方式

描述:dmp文件是二進制的,能夠跨平臺,而且包含權限,支持大字段數據,是用的最普遍的一種。

導出語法:exp 用戶名/密碼@監聽器路徑/數據庫實例名稱 file=e:數據庫文件.dmp full=y ignore=y ;其中full = y ,表示整個數據庫操做; ignore=y,忽略錯誤,繼續操做;
重點內容
導出舉例:exp jojo/jojo@localhost/my_database file=e:my_database.dmp full=y ignore=y

導入語法:imp 用戶名/密碼@監聽器路徑/數據庫實例名稱 file=e:數據庫文件.dmp full=y ignore=y ;

導入舉例:imp jojo/jojo@localhost/my_database file=e:my_database.dmp full=y ignore=y

 

2.sql文件方式

SQL文件可用文本編輯器查看,有利於可讀性,但效率不如dmp文件,適合小數據量導入導出。尤爲注意的是表中不能有大字段(blob,clob,long),若是有,會提示不能導出(提示以下: table contains one or more LONG columns cannot export in sql format,user Pl/sql developer format instead)

 

3.pde文件

第三種是導出爲pde格式,pde格式是PL/SQL 自帶的文件格式,且且適用於PL/SQL工具,編輯器沒法查看,通常不經常使用。
---------------------
版權聲明:本文爲CSDN博主「導哥」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/jingtianyiyi/article/details/80432626

5. Oracle中有哪幾種文件?

Oracle單實例下一共有8種主要的文件類型,分別是
參數文件:這些文件告訴oracle在哪裏能夠找到控制文件,並定義一些參數
跟蹤文件:這一般是一個服務器進程對某種異常錯誤作出響應時產生的診斷文件
警告文件:與跟蹤文件相似,可是包含」指望「事件的有關信息,並經過一個集中式文件警告DBA
數據文件:存放數據表,索引以及其餘段的文件
臨時文件:這些文件用於完成基於磁盤的排序和臨時存儲
控制文件:這些文件能告訴你數據文件,臨時文件以及重作日誌文件在哪裏,還會指出與文件狀態有關的其餘元數據
重作日誌文件:這些就是事物日誌
密碼文件:這些文件用於經過網絡完成管理活動的用戶進行認證。
從oracle10g開始又增長了2種可選的文件
修改跟蹤文件:這個文件有利於對oracle數據創建真正的增量備份。它不必定要放在閃回區,可是它只與數據庫的備份與恢復有關
閃回日誌文件:這些文件存儲數據塊的「前映像」,以便完成新增長的FLASHBACK DATABASE命令
與數據庫有關的其餘類型文件
轉儲文件:這些文件有exp導出並由imp導入
數據泵文件:這些文件有expdp導出並由inpdp導入
---------------------
版權聲明:本文爲CSDN博主「loveofmylife」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/viszl/article/details/7765133

6. Oracle中字符串用什麼符號連接?

1.和其餘數據庫系統相似,Oracle字符串鏈接使用「||」進行字符串拼接,其使用方式和MSSQLServer中的加號「+」同樣。

例如:

SELECT '工號爲'||FNumber||'的員工姓名爲'||FName FROM T_Employee WHERE FName IS NOT NULL

2.除了「||」,Oracle還支持使用CONCAT()函數進行字符串拼接,好比執行下面的SQL語句:

SELECT CONCAT('工號:',FNumber) FROM T_Employee

若是CONCAT中鏈接的值不是字符串,Oracle會嘗試將其轉換爲字符串,好比執行下面的SQL語句:

SELECT CONCAT('年齡:',FAge) FROM T_Employee

與MYSQL的CONCAT()函數不一樣,Oracle的CONCAT()函數只支持兩個參數,不支持兩個以上字符串的拼接,好比下面的SQL語句在Oracle中是錯誤的:

SELECT CONCAT('工號爲',FNumber,'的員工姓名爲',FName) FROM T_Employee WHERE FName IS NOT NULL

運行之後Oracle會報出下面的錯誤信息:

參數個數無效

3.若是要進行多個字符串的拼接的話,能夠使用多個CONCAT()函數嵌套使用,上面的SQL能夠以下改寫:

SELECT CONCAT(CONCAT(CONCAT('工號爲',FNumber),'的員工姓名爲'),FName) FROM T_Employee WHERE FName IS NOT NULL

轉:http://www.jb51.net/article/36428.htm

7. Oracle是怎樣分頁的?

在Oracle中實現分頁的方法大體分爲兩種,用ROWNUM關鍵字和用ROWID關鍵字,下面來詳細介紹一下:
一、ROWNUM
其代碼爲:
SELECT *
   FROM (SELECT ROW_.*, ROWNUM ROWNUM_
           FROM (SELECT *
                   FROM TABLE1
                  WHERE TABLE1_ID = XX
                  ORDER BY GMT_CREATE DESC) ROW_
          WHERE ROWNUM <= 20)
  WHERE ROWNUM_ >= 10;
12345678
這應該是咱們大部分程序裏所用到的版本,由於這個版本很容易實現複用,中間ROW_部分,就是咱們日常寫到的sql語句,而後再將起始條數和終止條數做爲專門的分頁sql語句傳入便可查詢出咱們想要的結果。
     從效率上看,上面的SQL語句在大多數狀況擁有較高的效率,主要體如今WHERE ROWNUM <= 20這句上,這樣就控制了查詢過程當中的最大記錄數,而在查詢的最外層控制最小值。但最大值意味着若是查到了很大的範圍(如百萬級別的數據),查詢就會從很大範圍內往裏減小,效率就會很低,所以,當面對大數據量時或者優化查詢效率時,若是你用了ROWNUM,能夠換第二種方法。
1
由以上的方法,又能夠引伸出3種方式:
A、結合BETWEEN AND
代碼以下:
SELECT *
   FROM (SELECT A.*, ROWNUM RN
           FROM (SELECT *
                   FROM TABLE1
                  WHERE TABLE1_ID = XX
                  ORDER BY GMT_CREATE DESC) A)
  WHERE RN BETWEEN 10 AND 20;
1234567
這個就是換湯不換藥了,並且查詢效率更低,由於:
     Oracle能夠將外層的查詢條件推到內層查詢中,以提升內層查詢的執行效率,但不能跨越多層。
1
因爲查詢條件BETWEEN 10 AND 20是存在於查詢的第三層,而Oracle沒法將第三層的查詢條件推到最內層(即便推到最內層也沒有意義,由於最內層查詢不知道RN表明什麼)。所以,這個查詢語句,Oracle最內層返回給中間層的是全部知足條件的數據,而中間層返回給最外層的也是全部數據。數據的過濾在最外層完成,顯然這個效率要比原始的查詢低得多。
B、結合MINUS
SELECT *
   FROM TABLE1
  WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE1 WHERE ROWNUM <= 10;
12345
查詢了兩次,效率上更差了一些。
C、ROW_NUMBER() OVER( ORDER BY ORDER_DATE DESC)
這個和ROWNUM關鍵字相似,生成的順序和rownum的語句同樣,效率也同樣(對於一樣有ORDER BY 的ROWNUM語句來講),因此在這種狀況下兩種用法是同樣的。
而對於分組後查詢作分頁的話,則是ROWNUM沒法實現的,這時只有ROW_NUMBER能夠實現,ROW_NUMBER() OVER(PARTITION BY 分組字段 ORDER BY 排序字段)就能實現分組後編號,其代碼爲:
SELECT *
   FROM (SELECT a.*,
                ROW_NUMBER() OVER(PARTITION BY TRUNC(order_date) ORDER BY order_date DESC) rn
           FROM TABLE1 a)
  WHERE rn <= 10;
12345
二、ROWID
ROWID仍舊需求ROWNUM,但方式不一樣,所以我將其歸爲另外一大類,其代碼爲:
SELECT *
   FROM (SELECT RID
           FROM (SELECT R.RID, ROWNUM LINENUM
                   FROM (SELECT ROWID RID
                           FROM TABLE1
                          WHERE TABLE1_ID = XX
                          ORDER BY order_date DESC) R
                  WHERE ROWNUM <= 20)
          WHERE LINENUM >= 10) T1,
        TABLE1 T2
  WHERE T1.RID = T2.ROWID;
1234567891011
從語句上看,共有4層Select嵌套查詢,最內層爲可替換的不分頁原始SQL語句,可是他查詢的字段只有ROWID,而沒有任何待查詢的實際表字段,具體查詢實際字段值是在最外層實現的;
這種方式的原理大體爲:
     首先經過ROWNUM查詢到分頁以後的10條實際返回記錄的ROWID,最後經過ROWID將最終返回字段值查詢出來並返回;
1
和前面ROWNUM實現方式相比,該SQL的實現方式更加繁瑣,通用性也不是很是好,由於要將原始的查詢語句分紅兩部分(查詢字段在最外層,表及其查詢條件在最內層),想要複用就很困難了;
但這種實如今特定場景下仍是有優點的:好比咱們常常要翻頁到很後面,好比10000條記錄中咱們常常須要查9000-9100及其之後的數據;此時該方案效率可能要比前面的高;
由於前面的方案中是經過ROWNUM <= 9100來控制的,這樣就須要查詢出9100條數據,而後取最後9000-9100之間的數據,而這個方案直接經過ROWID取須要的那100條數據;
從不斷向後翻頁這個角度來看,第一種實現方案的成本會愈來愈高,基本上是線性增加,而第三種方案的成本則不會像前者那樣快速,他的增加只體如今經過查詢條件讀取ROWID的部分;
所以,在咱們實際項目中,基本分頁都是能夠單靠ROWNUM就能夠實現,而在數據量只有幾十萬的狀況下,效率也是夠的,若是必定要優化,則能夠考慮ROWID。
---------------------
版權聲明:本文爲CSDN博主「death05」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/death05/article/details/78744250

1. Oracle跟SQL Server 2005的區別?
宏觀上:
1). 最大的區別在於平臺,oracle能夠運行在不一樣的平臺上,sql server只能運行在windows平臺上,因爲windows平臺的穩定性和安全性影響了sql server的穩定性和安全性
2). oracle使用的腳本語言爲PL-SQL,而sql server使用的腳本爲T-SQL
微觀上: 從數據類型,數據庫的結構等等回答

2. 如何使用Oracle的遊標?
1).  oracle中的遊標分爲顯示遊標和隱式遊標
2).  顯示遊標是用cursor...is命令定義的遊標,它能夠對查詢語句(select)返回的多條記錄進行處理;隱式遊標是在執行插入 (insert)、刪除(delete)、修改(update)和返回單條記錄的查詢(select)語句時由PL/SQL自動定義的。
3). 顯式遊標的操做:打開遊標、操做遊標、關閉遊標;PL/SQL隱式地打開SQL遊標,並在它內部處理SQL語句,而後關閉它

3. Oracle中function和procedure的區別?
1). 能夠理解函數是存儲過程的一種
2). 函數能夠沒有參數,可是必定須要一個返回值,存儲過程能夠沒有參數,不須要返回值
3). 函數return返回值沒有返回參數模式,存儲過程經過out參數返回值, 若是須要返回多個參數則建議使用存儲過程
4). 在sql數據操縱語句中只能調用函數而不能調用存儲過程

4. Oracle的導入導出有幾種方式,有何區別?
1). 使用oracle工具 exp/imp
2). 使用plsql相關工具
方法1. 導入/導出的是二進制的數據, 2.plsql導入/導出的是sql語句的文本文件
5. Oracle中有哪幾種文件?
數據文件(通常後綴爲.dbf或者.ora),日誌文件(後綴名.log),控制文件(後綴名爲.ctl)

6. 怎樣優化Oracle數據庫,有幾種方式?
我的理解,數據庫性能最關鍵的因素在於IO,由於操做內存是快速的,可是讀寫磁盤是速度很慢的,優化數據庫最關鍵的問題在於減小磁盤的IO,就我的理解應該分爲物理的和邏輯的優化, 物理的是指oracle產品自己的一些優化,邏輯優化是指應用程序級別的優化
物理優化的一些原則:
1). Oracle的運行環境(網絡,硬件等)
2). 使用合適的優化器
3). 合理配置oracle實例參數
4). 創建合適的索引(減小IO)
5). 將索引數據和表數據分開在不一樣的表空間上(下降IO衝突)
6). 創建表分區,將數據分別存儲在不一樣的分區上(以空間換取時間,減小IO)
   邏輯上優化:
1). 能夠對錶進行邏輯分割,如中國移動用戶表,能夠根據手機尾數分紅10個表,這樣對性能會有必定的做用
2). Sql語句使用佔位符語句,而且開發時候必須按照規定編寫sql語句(如所有大寫,所有小寫等)oracle解析語句後會放置到共享池中
如: select * from Emp where name=?  這個語句只會在共享池中有一條,而若是是字符串的話,那就根據不一樣名字存在不一樣的語句,因此佔位符效率較好
3). 數據庫不只僅是一個存儲數據的地方,一樣是一個編程的地方,一些耗時的操做,能夠經過存儲過程等在用戶較少的狀況下執行,從而錯開系統使用的高峯時間,提升數據庫性能
4). 儘可能不使用*號,如select * from Emp,由於要轉化爲具體的列名是要查數據字典,比較耗時
5). 選擇有效的表名
對於多表鏈接查詢,可能oracle的優化器並不會優化到這個程度, oracle 中多表查詢是根據FROM字句從右到左的數據進行的,那麼最好右邊的表(也就是基礎表)選擇數據較少的表,這樣排序更快速,若是有link表(多對多中間表),那麼將link表放最右邊做爲基礎表,在默認狀況下oracle會自動優化,可是若是配置了優化器的狀況下,可能不會自動優化,因此平時最好能按照這個方式編寫sql
6). Where字句 規則
Oracle 中Where字句時從右往左處理的,表之間的鏈接寫在其餘條件以前,能過濾掉很是多的數據的條件,放在where的末尾, 另外!=符號比較的列將不使用索引,列通過了計算(如變大寫等)不會使用索引(須要創建起函數), is null、is not null等優化器不會使用索引
7). 使用Exits Not Exits 替代 In  Not in
8). 合理使用事務,合理設置事務隔離性
數據庫的數據操做比較消耗數據庫資源的,儘可能使用批量處理,以下降事務操做次數

7. Oracle中字符串用什麼符號連接?
Oracle中使用 || 這個符號鏈接字符串 如 ‘abc’ || ‘d’
8. Oracle分區是怎樣優化數據庫的?
Oracle的分區能夠分爲:列表分區、範圍分區、散列分區、複合分區。
1).  加強可用性:若是表的一個分區因爲系統故障而不能使用,表的其他好的分區仍能夠使用;
2).  減小關閉時間:若是系統故障隻影響表的一部份分區,那麼只有這部份分區須要修復,可能比整個大表修復花的時間更少;
3).  維護輕鬆:若是須要得建表,獨產管理每一個公區比管理單個大表要輕鬆得多;
4).  均衡I/O:能夠把表的不一樣分區分配到不一樣的磁盤來平衡I/O改善性能;
5).  改善性能:對大表的查詢、增長、修改等操做能夠分解到表的不一樣分區來並行執行,可以使運行速度更快
6).  分區對用戶透明,最終用戶感受不到分區的存在。

9. Oracle是怎樣分頁的?
Oracle中使用rownum來進行分頁, 這個是效率最好的分頁方法,hibernate也是使用rownum來進行oralce分頁的
select * from
  ( select rownum r,a from tabName where rownum <= 20 )
where r > 10
10. Oralce怎樣存儲文件,可以存儲哪些文件?
Oracle 能存儲 clob、nclob、 blob、 bfile
Clob  可變長度的字符型數據,也就是其餘數據庫中提到的文本型數據類型
Nclob 可變字符類型的數據,不過其存儲的是Unicode字符集的字符數據
Blob  可變長度的二進制數據
Bfile  數據庫外面存儲的可變二進制數據
11. Oracle中使用了索引的列,對該列進行where條件查詢、分組、排序、使用匯集函數,哪些用到了索引?
均會使用索引, 值得注意的是複合索引(如在列A和列B上創建的索引)可能會有不一樣狀況
12. 數據庫怎樣實現每隔30分鐘備份一次?
經過操做系統的定時任務調用腳本導出數據庫

13. Oracle中where條件查詢和排序的性能比較?
Order by使用索引的條件極爲嚴格,只有知足以下狀況才能夠使用索引,
1). order by中的列必須包含相同的索引而且索引順序和排序順序一致
2). 不能有null值的列
因此排序的性能每每並不高,因此建議儘可能避免order by

14. 解釋冷備份和熱備份的不一樣點以及各自的優勢?
冷備份發生在數據庫已經正常關閉的狀況下,將關鍵性文件拷貝到另外位置的一種說法
熱備份是在數據庫運行的狀況下,採用歸檔方式備份數據的方法
冷備的優缺點
1).是很是快速的備份方法(只需拷貝文件) 
2).容易歸檔(簡單拷貝便可) 
3).容易恢復到某個時間點上(只需將文件再拷貝回去) 
4).能與歸檔方法相結合,做數據庫「最新狀態」的恢復。 
5).低度維護,高度安全。 
冷備份不足: 
1).單獨使用時,只能提供到「某一時間點上」的恢復。 
2).在實施備份的全過程當中,數據庫必需要做備份而不能做其它工做。也就是說,在冷備份過程當中,數據庫必須是關閉狀態。 
3).若磁盤空間有限,只能拷貝到磁帶等其它外部存儲設備上,速度會很慢。 
4).不能按表或按用戶恢復。 
熱備的優缺點
1).可在表空間或數據文件級備份,備份時間短。 
2).備份時數據庫仍可以使用。 
3).可達到秒級恢復(恢復到某一時間點上)。 
4).可對幾乎全部數據庫實體做恢復。 
5).恢復是快速的,在大多數狀況下在數據庫仍工做時恢復。 
熱備份的不足是: 
  1).不能出錯,不然後果嚴重。 
  2).若熱備份不成功,所得結果不可用於時間點的恢復。 
  3).因難於維護,因此要特別仔細當心,不容許「以失敗而了結」。

15. 解釋data block , extent 和 segment的區別?
data block 數據塊,是oracle最小的邏輯單位,一般oracle從磁盤讀寫的就是塊
extent 區,是由若干個相鄰的block組成
segment段,是有一組區組成
tablespace表空間,數據庫中數據邏輯存儲的地方,一個tablespace能夠包含多個數據文件
16. 比較truncate和delete命令 ?
1). Truncate 和delete均可以將數據實體刪掉,truncate 的操做並不記錄到 rollback日誌,因此操做速度較快,但同時這個數據不能恢復
2). Delete操做不騰出表空間的空間
3). Truncate 不能對視圖等進行刪除
4). Truncate是數據定義語言(DDL),而delete是數據操縱語言(DML)
17. 解釋什麼是死鎖,如何解決Oracle中的死鎖?
簡言之就是存在加了鎖而沒有解鎖,多是使用鎖沒有提交或者回滾事務,若是是表級鎖則不能操做表,客戶端處於等在狀態,若是是行級鎖則不能操做鎖定行
解決辦法:
1). 查找出被鎖的表
select b.owner,b.object_name,a.session_id,a.locked_mode
from v$locked_object a,dba_objects b
where b.object_id = a.object_id;
select b.username,b.sid,b.serial#,logon_time
from v$locked_object a,v$session b
where a.session_id = b.sid order by b.logon_time;
2). 殺進程中的會話
alter system kill session "sid,serial#";
18. 簡述oracle中 dml、ddl、dcl的使用
Dml 數據操縱語言,如select、update、delete,insert
Ddl 數據定義語言,如create table 、drop table 等等
Dcl 數據控制語言, 如 commit、 rollback、grant、 invoke等
19. 說說oracle中的常用到得函數
Length 長度、 lower 小寫、upper 大寫, to_date 轉化日期, to_char轉化字符
Ltrim 去左邊空格、 rtrim去右邊空格,substr取字串,add_month增長或者減掉月份、to_number轉變爲數字
20. 怎樣建立一個存儲過程, 遊標在存儲過程怎麼使用, 有什麼好處?
附:存儲過程的通常格式,遊標使用參考問題
1 .使用遊標能夠執行多個不相關的操做.若是但願當產生告終果集後,對結果集中的數據進行多種不相關的數據操做
2. 使用遊標能夠提供腳本的可讀性
3. 使用遊標能夠創建命令字符串,使用遊標能夠傳送表名,或者把變量傳送到參數中,以便創建能夠執行的命令字符串.
可是我的認爲遊標操做效率不過高,而且使用時要特別當心,使用完後要及時關閉
存儲過程優缺點:
優勢:
1. 存儲過程加強了SQL語言的功能和靈活性。存儲過程能夠用流控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。
2. 可保證數據的安全性和完整性。
3. 經過存儲過程能夠使沒有權限的用戶在控制之下間接地存取數據庫,從而保證數據的安全。
      經過存儲過程能夠使相關的動做在一塊兒發生,從而能夠維護數據庫的完整性。
3. 再運行存儲過程前,數據庫已對其進行了語法和句法分析,並給出了優化執行方案。這種已經編譯好的過程可極大地改善SQL語句的性能。 因爲執行SQL語句的大部分工做已經完成,因此存儲過程能以極快的速度執行。
4. 能夠下降網絡的通訊量, 不須要經過網絡來傳送不少sql語句到數據庫服務器了
5. 使體現企業規則的運算程序放入數據庫服務器中,以便集中控制
       當企業規則發生變化時在服務器中改變存儲過程便可,無須修改任何應用程序。企業規則的特色是要常常變化,若是把體現企業規則的運算程序放入應用程序中,則當企業規則發生變化時,就須要修改應用程序工做量很是之大(修改、發行和安裝應用程序)。若是把體現企業規則的 運算放入存儲過程當中,則當企業規則發生變化時,只要修改存儲過程就能夠了,應用程序無須任何變化。
缺點:
1. 可移植性差
2. 佔用服務器端多的資源,對服務器形成很大的壓力
3. 可讀性和可維護性很差
Create  [or replace]  procedure 過程名字(參數 …)as
vs_ym_sn_end CHAR(6);     --同期終止月份
CURSOR cur_1 IS   --定義遊標(簡單的說就是一個能夠遍歷的結果集)
SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn,SUM(usd_amt)/10000 usd_amt_sn
FROM BGD_AREA_CM_M_BASE_T
  WHERE ym >= vs_ym_sn_beg
  AND ym <= vs_ym_sn_end
GROUP BY area_code,CMCODE;
BEGIN
--用輸入參數給變量賦初值,用到了Oralce的SUBSTR TO_CHAR ADD_MONTHS TO_DATE 等很經常使用的函數。
vs_ym_beg := SUBSTR(is_ym,1,6);
vs_ym_end := SUBSTR(is_ym,7,6);
vs_ym_sn_beg := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_beg,"yyyymm"), -12),"yyyymm");
vs_ym_sn_end := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_end,"yyyymm"), -12),"yyyymm");
--先刪除表中特定條件的數據。
DELETE FROM xxxxxxxxxxx_T WHERE ym = is_ym;
  --而後用內置的DBMS_OUTPUT對象的put_line方法打印出影響的記錄行數,其中用到一個系統變量SQL%rowcount
DBMS_OUTPUT.put_line("del上月記錄="||SQL%rowcount||"條");
INSERT INTO xxxxxxxxxxx_T(area_code,ym,CMCODE,rmb_amt,usd_amt)
SELECT area_code,is_ym,CMCODE,SUM(rmb_amt)/10000,SUM(usd_amt)/10000
FROM BGD_AREA_CM_M_BASE_T
  WHERE ym >= vs_ym_beg
  AND ym <= vs_ym_end
GROUP BY area_code,CMCODE;
DBMS_OUTPUT.put_line("ins當月記錄="||SQL%rowcount||"條");
--遍歷遊標處理後更新到表。遍歷遊標有幾種方法,用for語句是其中比較直觀的一種。
FOR rec IN cur_1 LOOP
  UPDATE xxxxxxxxxxx_T
  SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn
   WHERE area_code = rec.area_code
   AND CMCODE = rec.CMCODE
   AND ym = is_ym;
END LOOP;
COMMIT;
--錯誤處理部分。OTHERS表示除了聲明外的任意錯誤。SQLERRM是系統內置變量保存了當前錯誤的詳細信息。
EXCEPTION
   WHEN OTHERS THEN
      vs_msg := "ERROR IN xxxxxxxxxxx_p("||is_ym||"):"||SUBSTR(SQLERRM,1,500);
   ROLLBACK;
   --把當前錯誤記錄進日誌表。
   INSERT INTO LOG_INFO(proc_name,error_info,op_date)
   VALUES("xxxxxxxxxxx_p",vs_msg,SYSDATE);
   COMMIT;
   RETURN;
END;
21. 怎樣建立一個一個索引,索引使用的原則,有什麼優勢和缺點
建立標準索引:
CREATE  INDEX 索引名 ON 表名 (列名)  TABLESPACE 表空間名;
建立惟一索引:
CREATE unique INDEX 索引名 ON 表名 (列名)  TABLESPACE 表空間名;
建立組合索引:
CREATE INDEX 索引名 ON 表名 (列名1,列名2)  TABLESPACE 表空間名;
建立反向鍵索引:
CREATE INDEX 索引名 ON 表名 (列名) reverse TABLESPACE 表空間名;
索引使用原則:
索引字段建議創建NOT NULL約束
常常與其餘表進行鏈接的表,在鏈接字段上應該創建索引;
常常出如今Where子句中的字段且過濾性很強的,特別是大表的字段,應該創建索引;
可選擇性高的關鍵字 ,應該創建索引;
可選擇性低的關鍵字,但數據的值分佈差別很大時,選擇性數據比較少時仍然能夠利用索引提升效率
複合索引的創建須要進行仔細分析;儘可能考慮用單字段索引代替:
A、正確選擇複合索引中的第一個字段,通常是選擇性較好的且在where子句中經常使用的字段上;
B、複合索引的幾個字段常常同時以AND方式出如今Where子句中能夠創建複合索引;不然單字段索引;
C、若是複合索引中包含的字段常常單獨出如今Where子句中,則分解爲多個單字段索引;
D、若是複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減小複合的字段;
E、若是既有單字段索引,又有這幾個字段上的複合索引,通常能夠刪除複合索引;
頻繁DML的表,不要創建太多的索引;
不要將那些頻繁修改的列做爲索引列;
索引的優缺點:
有點:
1. 建立惟一性索引,保證數據庫表中每一行數據的惟一性
2. 大大加快數據的檢索速度,這也是建立索引的最主要的緣由
3. 加速表和表之間的鏈接,特別是在實現數據的參考完整性方面特別有意義。
4. 在使用分組和排序子句進行數據檢索時,一樣能夠顯著減小查詢中分組和排序的時間。
缺點:
1. 索引建立在表上,不能建立在視圖上
2. 建立索引和維護索引要耗費時間,這種時間隨着數據量的增長而增長
3. 索引須要佔物理空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是要創建聚簇索引,那麼須要的空間就會更大
4. 當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,下降了數據的維護速度
22. 怎樣建立一個視圖,視圖的好處, 視圖能夠控制權限嗎?
create view 視圖名 as select 列名 [別名]  …  from 表 [unio [all] select … ] ]
好處:
1. 能夠簡單的將視圖理解爲sql查詢語句,視圖最大的好處是不佔系統空間
2. 一些安全性很高的系統,不會公佈系統的表結構,可能會使用視圖將一些敏感信息過慮或者重命名後公佈結構
3. 簡化查詢
能夠控制權限的,在使用的時候須要將視圖的使用權限grant給用戶
23. 怎樣建立一個觸發器, 觸發器的定義, 觸發器的遊標怎樣定義
CREATE [OR REPLACE] TIGGER觸發器名 觸發時間 觸發事件
 ON表名
 [FOR EACH ROW]
 BEGIN
  pl/sql語句
    CURSOR  遊標名 is  SELECT * FROM 表名 (定義遊標)
  END
 其中:
 觸發器名:觸發器對象的名稱。
 因爲觸發器是數據庫自動執行的,所以該名稱只是一個名稱,沒有實質的用途。
觸發時間:指明觸發器什麼時候執行,該值可取:
before---表示在數據庫動做以前觸發器執行;
after---表示在數據庫動做以後出發器執行。
觸發事件:指明哪些數據庫動做會觸發此觸發器:                      
   insert:數據庫插入會觸發此觸發器; 
24. oracle建立表的幾種方式;應該注意些什麼
不知道這個題目是否是記錯了,感受很怪
1. 使用圖形工具建立表
2. 使用數據ddl語句建立表
3. 能夠在plsql代碼中動態建立表
應該注意: 是否有建立表的權限, 使用什麼表空間等
25. 怎樣將一箇舊數據庫數據移到一個新的數據庫
1. Imp/exp將數據庫中的數據導入到新的庫中
2. 若是是存儲遷移直接將存儲設備掛到新機器上
26. 主鍵有幾種;
字符型,整數型、複合型
27. oracle的鎖又幾種,定義分別是什麼;
1.  行共享鎖 (ROW SHARE)
2.  行排他鎖(ROW EXCLUSIVE)
3 . 共享鎖(SHARE)
4.  共享行排他鎖(SHARE ROW EXCLUSIVE)
5.  排他鎖(EXCLUSIVE)
使用方法:
SELECT * FROM order_master WHERE vencode="V002"
FOR UPDATE WAIT 5;
LOCK TABLE order_master IN SHARE MODE;
LOCK TABLE itemfile IN EXCLUSIVE MODE NOWAIT;
ORACLE鎖具體分爲如下幾類:
1.按用戶與系統劃分,能夠分爲自動鎖與顯示鎖
自動鎖:當進行一項數據庫操做時,缺省狀況下,系統自動爲此數據庫操做得到全部有必要的鎖。
顯示鎖:某些狀況下,須要用戶顯示的鎖定數據庫操做要用到的數據,才能使數據庫操做執行得更好,顯示鎖是用戶爲數據庫對象設定的。
2 . 按鎖級別劃分,可分爲共享鎖與排它鎖
共享鎖:共享鎖使一個事務對特定數據庫資源進行共享訪問——另外一事務也可對此資源進行訪問或得到相同共享鎖。共享鎖爲事務提供高併發性,但如拙劣的事務設計+共享鎖容易形成死鎖或數據更新丟失。
排它鎖:事務設置排它鎖後,該事務單獨得到此資源,另外一事務不能在此事務提交以前得到相同對象的共享鎖或排它鎖。
3.按操做劃分,可分爲DML鎖、DDL鎖
DML鎖又能夠分爲,行鎖、表鎖、死鎖
行鎖:當事務執行數據庫插入、更新、刪除操做時,該事務自動得到操做表中操做行的排它鎖。
表級鎖:當事務得到行鎖後,此事務也將自動得到該行的表鎖(共享鎖),以防止其它事務進行DDL語句影響記錄行的更新。事務也能夠在進行過程當中得到共享鎖或排它鎖,只有當事務顯示使用LOCK TABLE語句顯示的定義一個排它鎖時,事務纔會得到表上的排它鎖,也可以使用LOCK TABLE顯示的定義一個表級的共享鎖(LOCK TABLE具體用法請參考相關文檔)。
死鎖:當兩個事務須要一組有衝突的鎖,而不能將事務繼續下去的話,就出現死鎖。
如事務1在表A行記錄#3中有一排它鎖,並等待事務2在表A中記錄#4中排它鎖的釋放,而事務2在表A記錄行#4中有一排它鎖,並等待事務; 1在表A中記錄#3中排它鎖的釋放,事務1與事務2彼此等待,所以就形成了死鎖。死鎖通常是因拙劣的事務設計而產生。死鎖只能使用SQL下:alter system kill session "sid,serial#";或者使用相關操做系統kill進程的命令,如UNIX下kill -9 sid,或者使用其它工具殺掉死鎖進程。
DDL鎖又能夠分爲:排它DDL鎖、共享DDL鎖、分析鎖
排它DDL鎖:建立、修改、刪除一個數據庫對象的DDL語句得到操做對象的 排它鎖。如使用alter table語句時,爲了維護數據的完成性、一致性、合法性,該事務得到一排它DDL鎖。
共享DDL鎖:需在數據庫對象之間創建相互依賴關係的DDL語句一般需共享得到DDL鎖。
如建立一個包,該包中的過程與函數引用了不一樣的數據庫表,當編譯此包時,該事務就得到了引用表的共享DDL鎖。
分析鎖:ORACLE使用共享池存儲分析與優化過的SQL語句及PL/SQL程序,使運行相同語句的應用速度更快。一個在共享池中緩存的對象得到它所引用數據庫對象的分析鎖。分析鎖是一種獨特的DDL鎖類型,ORACLE使用它追蹤共享池對象及它所引用數據庫對象之間的依賴關係。當一個事務修改或刪除了共享池持有分析鎖的數據庫對象時,ORACLE使共享池中的對象做廢,下次在引用這條SQL/PLSQL語句時,ORACLE從新分析編譯此語句。
4.內部閂鎖
內部閂鎖:這是ORACLE中的一種特殊鎖,用於順序訪問內部系統結構。當事務需向緩衝區寫入信息時,爲了使用此塊內存區域,ORACLE首先必須取得這塊內存區域的閂鎖,才能向此塊內存寫入信息。
28. 在java種怎樣調用oracle存儲過程;
在java中使用 CallableStatement調用存儲過程
建立須要的測試表:create table Test(tid varchar2(10),tname varchar2(10));
  第一種狀況:無返回值.
      create or replace procedure test_a(param1 in varchar2,param2 in varchar2) as
       begin
            insert into test value(param1,param2);
     end;
Java調用代碼:
package com.test;
import java.sql.*;
import java.io.*;
import java.sql.*;
public class TestProcA
{
   public TestProcA(){
   }
   public static void main(String []args)
   {
        ResultSet rs = null;
        Connection conn = null;
        CallableStatement proc = null;
        try{
       Class.forName("oracle.jdbc.driver.OracleDriver");
conn =  DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:test", "test", "test");
          proc = conn.prepareCall("{ call test_a(?,?) }");
          proc.setString(1, "1001");
          proc.setString(2, "TestA");
          proc.execute();
        }catch(Exception e){
     e.printStackTrace();
}finally{
           try{
       if(null!=rs){
                 rs.close();
          if(null!=proc){
                    proc.close();
          }
          if(null!=conn){
                    conn.close();
          }
       } 
           }catch(Exception ex){
           }
        }
   }
}
第二種狀況:有返回值的存儲過程(返回值非列表).
存儲過程爲:
create or replace procedure test_b(param1 in varchar2,param2 out varchar2)
as
begin
    select tname into param2 from test where tid=param1;
end;
Java調用代碼:
package com.test;
import java.sql.*;
import java.io.*;
import java.sql.*;
public class TestProcB
{
   public TestProcB(){
   }
   public static void main(String []args)
   {
        Connection conn = null;
        CallableStatement proc = null;
        try{
          Class.forName("oracle.jdbc.driver.OracleDriver");
          conn =  DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:test", "test", "test");
          proc = conn.prepareCall("{ call test_b(?,?) }");
          proc.setString(1, "1001");
          proc.registerOutParameter(2, Types.VARCHAR);
          proc.execute();
          System.out.println("Output is:"+proc.getString(2));
        }catch(Exception e){
     e.printStackTrace();
}finally{
           try{
          if(null!=proc){
                    proc.close();
          }
          if(null!=conn){
                    conn.close();
          }
           }catch(Exception ex){
           }
        }
   }
}
第三種狀況:返回列表.
因爲oracle存儲過程沒有返回值,它的全部返回值都是經過out參數來替代的,列表一樣也不例外,但因爲是集合,因此不能用通常的參數,必需要用pagkage了.要分兩部分來寫:
create or replace package tpackage as
type t_cursor is ref cursor;
procedure test_c(c_ref out t_cursor);
end ;
create or replace package body tpackage as
procedure test_c(c_ref out t_cursor) is
   begin
      open c_ref for select * from test;
  end test_c;
end tpackage;
Java調用代碼:
package com.test;
import java.sql.*;
import java.io.*;
import java.sql.*;
public class TestProcB
{
   public TestProcB(){
   }
   public static void main(String []args)
   {
        Connection conn = null;
        CallableStatement proc = null;
        ResultSet rs =  null;
        try{
          Class.forName("oracle.jdbc.driver.OracleDriver");
          conn =  DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:test", "test", "test");
          proc = conn.prepareCall("{? = call tpackage.test_b(?) }");
          proc.registerOutParameter(1, OracleTypes.CURSOR);
          proc.execute();
          while(rs.next()){
              System.out.println(rs.getObject(1) + "\t" + rs.getObject(2));
          }
        }catch(Exception e){
     e.printStackTrace();
}finally{
           try{
          if(null!=rs){
              rs.close();
             if(null!=proc){
                    proc.close();
             }
             if(null!=conn){
                    conn.close();
             }
          }
          }catch(Exception ex){
           }
        }
   }
}
29. rowid, rownum的定義
1. rowid和rownum都是虛列
2. rowid是物理地址,用於定位oracle中具體數據的物理存儲位置
3. rownum則是sql的輸出結果排序,從下面的例子能夠看出其中的區別。
30. oracle中存儲過程,遊標和函數的區別
遊標相似指針,遊標能夠執行多個不相關的操做.若是但願當產生告終果集後,對結果集中的數據進行多 種不相關的數據操做
函數能夠理解函數是存儲過程的一種; 函數能夠沒有參數,可是必定須要一個返回值,存儲過程能夠沒有參數,不須要返回值;二者均可以經過out參數返回值, 若是須要返回多個參數則建議使用存儲過程;在sql數據操縱語句中只能調用函數而不能調用存儲過程
31. 使用oracle 僞列刪除表中重複記錄:
Delete  table t  where t.rowid!=(select  max(t1.rowid)  from  table1 t1 where  t1.name=t.name)

30. 常見的關係型數據庫有哪些

關係型數據庫:

Oracle、DB二、Microsoft SQL Server、Microsoft Access、MySQL

非關係型數據庫:

NoSql、Cloudant、MongoDb、redis、HBase

兩種數據庫之間的區別:

關係型數據庫

  關係型數據庫的特性

一、關係型數據庫,是指採用了關係模型來組織數據的數據庫;

二、關係型數據庫的最大特色就是事務的一致性

三、簡單來講,關係模型指的就是二維表格模型,而一個關係型數據庫就是由二維表及其之間的聯繫所組成的一個數據組織

  關係型數據庫的優勢

  一、容易理解:二維表結構是很是貼近邏輯世界一個概念,關係模型相對網狀、層次等其餘模型來講更容易理解;
  二、使用方便:通用的SQL語言使得操做關係型數據庫很是方便;
  三、易於維護:豐富的完整性(實體完整性、參照完整性和用戶定義的完整性)大大減低了數據冗餘和數據不一致的機率;
  四、支持SQL,可用於複雜的查詢。

  關係型數據庫的缺點

  一、爲了維護一致性所付出的巨大代價就是其讀寫性能比較差
  二、固定的表結構
  三、高併發讀寫需求
  四、海量數據的高效率讀寫

非關係型數據庫

  非關係型數據庫的特性

  一、使用鍵值對存儲數據;
  二、分佈式
  三、通常不支持ACID特性;
  四、非關係型數據庫嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合。

  非關係型數據庫的優勢

  一、無需通過sql層的解析,讀寫性能很高
  二、基於鍵值對,數據沒有耦合性,容易擴展
  三、存儲數據的格式:nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,文檔形式、圖片形式等等,而關係型數據庫則只支持基礎類型。

非關係型數據庫的缺點

  一、不提供sql支持,學習和使用成本較高;
  二、無事務處理,附加功能bi和報表等支持也很差;

31. SQL結構化查詢語言(Structured Query Language)有哪些內容

1.關鍵詞
SELECT,UPDATE,DELETE,INSERECT,WHERE
2.RDBMS(Relational Database Management System)關係型數據庫管理系統
好比MS SQL Server,IBM DB2,Oracle,MySQL,Microsoft Access
3.RDBMS中的數據存儲在被稱爲表(tables)的數據庫對象中。  (解析理解   表(tables)被稱爲數據庫對象?)
表是相關數據項的集合,它由列和行組成

4.數據庫表

一個數據庫一般包含一個或者多個表,每一個表由一個名字標識(例如「客戶」或「訂單」),表包含帶有數據的記錄。

5.能夠吧SQL分爲2部分,DML(數據操做語言)、DDL(數據定義語言)

6.查詢和更新指令構成了SQL的DML部分,

SELECT-從數據庫表中獲取數據

UPDATE-更新數據庫表中的數據

DELETE-從數據庫表中刪除數據

INSERT INTO-向數據庫表中插入數據

7.SQL數據定義語言(DDL)部分使咱們有能力建立或者刪除表格。咱們也能夠定義索引(鍵),規定表之間的連接,以及施加表間的約束

SQL中最重要的DDL語句

-CREATE DATABASE 建立新數據庫

-ALTER DATABASE 修改數據庫

-CREATE TABLE 建立新表

-ALTER TABLE 變動(改變)數據庫表

-DROP TABLE 刪除表

-CREATE INDEX 建立索引(搜索鍵)

-DROP INDEX(刪除索引)
---------------------
版權聲明:本文爲CSDN博主「匠人科」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/zhangke_zhangke/article/details/76563189

32. 單行函數有哪些

單行函數介紹

SQL函數即數據庫的內置函數,能夠運用在SQL語句中實現特定的功能。SQL單行函數對於每一行數據進行計算後獲得一行輸出結果。SQL單行函數根據數據類型分爲字符函數、數字函數、日期函數、轉換函數,另外還有一些別的函數。——來自百度

單行數

1、字符函數

 

大小寫轉換函數

大小寫轉換函數包括:
1. UPPER() , 將查詢的字符串小寫轉換爲大寫 ;
2.  LOWER() , 將查詢的字符串大寫轉換爲小寫 ;
3. INITCAP() , 將查詢的字符串首字母大寫 ;


將表中的id和t_string查詢出來,並將string大寫

 


select id , upper(string)
from T_CHAR ;12

查詢結果:

 1

 

將表中的id和t_string查詢出來,並將string小寫

 


select id , lower(string)
from T_CHAR ;12

查詢結果:

12

將表中的id和t_string查詢出來,並將string首字母大寫

 


select id , initcap(string)
from T_CHAR ;12

查詢結果:

13


字符控制函數

SQL中經常使用的字符控制函數有:
1. CONCAT(),字符串鏈接函數
2. SUBSTR(),字符串截取函數
3. LEANTH(),求字符串長度函數
4.  LPAD(),左填充函數
5.  RPAD(),右填充函數
6.  TRIM(),字符移除函數
7.  REPLACE(),字符替換函數


CONCAT():將T_CHAR表string 和 string2鏈接起來

 


select id , concat(t_string , t_string2)
from T_CHAR12

查詢結果:

14

SUBSTR():截取string 中的前2個字符和string2中的前4個字符 。

 


select id , substr(t_string , 1 , 2 ) ,substr(t_string2 , 1 , 4 )
from T_CHAR12

查詢結果:

15

LEANTH():求string和string2的字符串長度

 


select id , t_string , length(t_string) ,t_string2 ,length(t_string2)
from T_CHAR12

運行結果:

16

LPAD() ,RPAD(), 將string用‘*’填充,string2用‘#’填充,總長爲10

 


select id , rpad(t_string,10,'*') ,lpad(t_string2,10,'#')
from T_CHAR12

查詢結果:

17

TRIM(),將string中的首位字母 ‘a’ 刪除 ,string2中的首尾字母 ‘o’ 刪除。

 


select id , trim('d' from t_string) ,trim('w' from t_string2 )
from T_CHAR ;12

查詢結果:

18

REPLACE() ,將string中的全部 ‘a’ 替換成‘*’ , string2中的全部‘o’替換成‘#’ 。

 


select id , replace(t_string , 'a' , '*') ,replace(t_string2 ,'o' ,'#' )
from T_CHAR ;12

查詢結果:

19


2、數字函數

SQL中用於數字計算的數字函數有:
1. ROUND() ,四捨五入函數;
2. TRUNC() ,截取函數
3.  MOD() ,求餘函數


ROUND() ,將T_CHAR表中的 t_number保留兩位小數第三位四捨五入。

 


select id , round(t_number , 2)
from T_CHAR ;12

查詢結果:

21

TRUNC() ,截取T_CHAR中的 t_number 保留小數點後四位,其他捨去。

 


select id , trunc(t_number , 4)
from T_CHAR ;12

查詢結果:

22

MOD() ,將T_CHAR中的 t_number 取模10 。

 


select id , mod(t_number , 10)
from T_CHAR ;12

查詢結果:

23


3、日期函數

 

對日期進行粗略計算

SQL中能夠對日期進行粗略計算:
1. 能夠將日期加上或者減去n天
2. 能夠用兩個日期相減獲得相差天數


將T_CHAR中的 t_date加上一天,減去兩天。

 


select t_date , t_date + 1 , t_date - 2
from T_CHAR ;12

查詢結果:

31

計算t_date到系統時間的天數 。

 


select t_date , sysdate , sysdate - t_date
from T_CHAR ;12

查詢結果:

32


對日期進行精確計算

SQL中提供了精確計算日期的函數:
1. MONTHS_BETWEEN() 計算兩個日期相差的天數;
2. ADD_MONTHS() 往一個日期中加n月;
3. NEXT_DAY() 當前系統時間的下一星期n的時間
4. LAST_DAY() 日期中月的最後一天
5. ROUND() 對日期的四捨五入
6. TRUNC() 對日期的截取


計算T_CHAR中的 t_date和系統時間相差的天數 , 並將t_date加2個月

 


select t_date , months_between(sysdate , t_date) , add_months(t_date , 2)
from T_CHAR ;12

查詢結果:

33

計算T_CHAR中 t_date 下一個星期三的日期,並計算系統時間的t_date最後一天的日期

 


select t_date , next_day(t_date , '星期三' ) , last_day(t_date)
from T_CHAR ;12

查詢結果:

34

將T_CHAR中 t_date按月四捨五入,將t_date按日截取

 


select t_date , round(t_date,'month') , trunc(t_date , 'day')
from T_CHAR ;12

查詢結果:

35


4、轉換函數

SQL中能夠進行兩種數據類型的轉換,即隱式轉換和顯示轉換。

 

隱式數據類型轉換

ORACLE數據庫中會將 char或varchar2 與 date 和 number 之間進行相互轉換。如前例中日期date能夠和number進行加減運算,也能夠將輸入的varchar2類型存入date型的數據庫中,稱之爲隱形轉換。

 

顯式數據類型轉換

ORACLE數據庫中也能夠經過方法 to_char() , to_date() , to_number(),完成數據類型之間的轉換。
- 查詢T_CHAR表中日期爲’2016年7月21日’ 的數據(日期轉字符串)。

 

select *
from T_CHAR
where to_char(t_date , 'yyyy-mm-dd') = '2016-07-21' ;123

查詢結果:

36

查詢T_CHAR表中日期爲’2015年11月19日’ 的數據(字符串轉日期)。

 


select *
from T_CHAR
where to_date('2015年11月19日' , 'yyyy"年"mm"月"dd"日"') = t_date ;123

查詢結果:

37
注:日期格式說明表示year的:y 表示年的最後一位 yy 表示年的最後2位 yyy 表示年的最後3位 yyyy 用4位數表示年;
表示month的:mm 用2位數字表示月;mon 用簡寫形式 好比11月或者nov ;month 用全稱 好比11月或者november; 
表示day的:dd 表示當月第幾天;ddd表示當年第幾天;dy 當週第幾天 簡寫 好比星期五或者fri;day當週第幾天 全寫好比星期五或者friday;
表示hour的:hh 2位數表示小時 12進制; hh24 2位數表示小時 24小時;
表示minute的:mi 2位數表示分鐘;
表示second的:ss 2位數表示秒 60進制;
表示季度的:q 一位數 表示季度 (1-4);
另外還有ww 用來表示當年第幾周 w用來表示當月第幾周;
24小時制下的時間範圍:00:00:00-23:59:59 ;
12小時制下的時間範圍:1:00:00-12:59:59


將T_CHAR中 t_number 轉換爲格式‘999,999.999’(數字轉字符串)

 


select id , to_char(t_number , '999,999.999')
from T_CHAR  ;12

查詢結果: 38


注:數字格式說明,用數字‘9’站位數字前有空位不補位,用數字‘0’站位前有空位時補‘0’; ‘$’放在最前表示美圓,大寫字母‘L’表示當地貨幣


將字符串’¥47.453’ 轉換爲數字(字符串轉數字)

 


select to_number('¥47.453','L999,999.999')
from dual ;12

查詢結果:

39


5、通用函數

ORACLE中提供了適合全部數據類型的函數,包括空值。


NVL(A,B) ,可以將一個空值轉換成已知的值,若A爲空顯示A,非空顯示B;
NVL2(A,B,C) , 若A非空顯示B 爲空顯示C ;
NULLIF(A,B), A,B相等時返回null,不等時返回A ;
COALESCE(A,B,C…) ,A爲空返回B,B爲空返回C,以此類推。


修改數據庫中數據以便演示通用函數:

 

查詢T_CHAR中全部數據,要求若t_date爲空則顯示‘日期爲空’,若t_string2爲空顯示‘字符串爲空’,若t_number爲空則顯示‘數字爲空’ (NVL)。


select id , t_string , nvl(to_char(t_date , 'yyyy/mm/dd') ,'日期爲空') , nvl(t_string2 ,'字符串爲空') , nvl(to_char(t_number , '9999999'),'數字爲空')
from T_CHAR ;12

查詢結果:

40

查詢T_CHAR中全部數據,要求若t_date爲空則顯示‘日期爲空’不然顯示‘有日期’,若t_string2爲空顯示‘字符串爲空’不然顯示‘有字符串’,若t_number爲空則顯示‘數字爲空’ 不然顯示‘有數字’(NVL2相似於if-else,或c語言中的三目運算符?:)。


select id , t_string , nvl2(to_char(t_date , 'yyyy/mm/dd'),'有日期' ,'日期爲空') , nvl2(t_string2 ,'有字符串' ,'字符串爲空') , nvl2(to_char(t_number , '9999999'),'有數字','數字爲空')
from T_CHAR ;12

查詢結果:

 53

單行函數介紹

SQL函數即數據庫的內置函數,能夠運用在SQL語句中實現特定的功能。SQL單行函數對於每一行數據進行計算後獲得一行輸出結果。SQL單行函數根據數據類型分爲字符函數、數字函數、日期函數、轉換函數,另外還有一些別的函數。——來自百度

查詢T_CHAR中t_string , t_string2的長度,並比較若長度相等顯示‘null’ 不然顯示t_string長度 ;


select id , t_string , t_string2 , nullif(length(t_string),length(t_string2))
from T_CHAR ;12

查詢結果:
------------54---------
版權聲明:本文爲CSDN博主「葉清逸」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/u013634252/article/details/80570432

33. 分組函數有哪些

 

34. 多表查詢有哪幾種方式

分組函數做用於一組數據,並對一組數據返回一個值。

分組函數做用於一組數據,並對一組數據返回一個值。
1.關鍵字AVG(平均值)、SUM(合計) ,在查詢數值型的數據時能夠使用AVG 和 SUM 函數。示例代碼以下:

select avg(salary),sum(salary) from employees where department_id=30;

在這裏插入圖片描述
須要注意一個問題,AVG函數只是計算不爲空的數據,能夠使用NVL函數解決該問題,NVL函數使分組函數沒法忽略空值。

SELECT AVG(NVL(commission_pct, 0)) FROM employees;

2.關鍵字MAX(最大值)、MIN(最小值),能夠對任意數據類型的數據使用MIN和MAX 函數select

min(salary),max(salary) from employees where department_id=80;

在這裏插入圖片描述
3. COUNT(計數)函數,COUNT(*) 返回表中記錄總數,適用於任意數據類型,COUNT(expr) 返回expr不爲空的記錄總數。如如下兩個例子:

SELECT COUNT(manager_id) FROM employees;

在這裏插入圖片描述

select count(*) from employees;

在這裏插入圖片描述
4.distinct關鍵字,例如COUNT(DISTINCT expr)返回expr非空且不重複的記錄總數

select count(distinct manager_id) from employees;

在這裏插入圖片描述
5.group by字句:在SELECT 列表中全部未包含在組函數中的列都應該包含在 GROUP BY 子句中, 包含在 GROUP BY 子句中的列沒必要包含在SELECT 列表中。另外須要注意的是,不能
在WHERE 子句中使用組函數,能夠在 HAVING 子句中使用組函數。

SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id, job_id ;

在這裏插入圖片描述
5.過濾分組:having字句

SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id, job_id having AVG(salary)>7500;

在這裏插入圖片描述
6.嵌套組函數,例如查詢各個職位平均工資的最大值

SELECT MAX(AVG(salary)) FROM employees GROUP BY job_id;

在這裏插入圖片描述

分組函數做用於一組數據,並對一組數據返回一個值。
1.關鍵字AVG(平均值)、SUM(合計) ,在查詢數值型的數據時能夠使用AVG 和 SUM 函數。示例代碼以下:

select avg(salary),sum(salary) from employees where department_id=30;

在這裏插入圖片描述
須要注意一個問題,AVG函數只是計算不爲空的數據,能夠使用NVL函數解決該問題,NVL函數使分組函數沒法忽略空值。

SELECT AVG(NVL(commission_pct, 0)) FROM employees;

2.關鍵字MAX(最大值)、MIN(最小值),能夠對任意數據類型的數據使用MIN和MAX 函數select

min(salary),max(salary) from employees where department_id=80;

在這裏插入圖片描述
3. COUNT(計數)函數,COUNT(*) 返回表中記錄總數,適用於任意數據類型,COUNT(expr) 返回expr不爲空的記錄總數。如如下兩個例子:

SELECT COUNT(manager_id) FROM employees;

在這裏插入圖片描述

select count(*) from employees;

在這裏插入圖片描述
4.distinct關鍵字,例如COUNT(DISTINCT expr)返回expr非空且不重複的記錄總數

select count(distinct manager_id) from employees;

在這裏插入圖片描述
5.group by字句:在SELECT 列表中全部未包含在組函數中的列都應該包含在 GROUP BY 子句中, 包含在 GROUP BY 子句中的列沒必要包含在SELECT 列表中。另外須要注意的是,不能
在WHERE 子句中使用組函數,能夠在 HAVING 子句中使用組函數。

SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id, job_id ;

在這裏插入圖片描述
5.過濾分組:having字句

SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id, job_id having AVG(salary)>7500;

在這裏插入圖片描述
6.嵌套組函數,例如查詢各個職位平均工資的最大值

SELECT MAX(AVG(salary)) FROM employees GROUP BY job_id;

在這裏插入圖片描述

35. 子查詢中空值和多值怎麼處理?

空值

方法一:使用coalesce函數
百度百科
定義: COALESCE是一個函數, (expression_1, expression_2, …,expression_n)依次參考各參數表達式,遇到非null值即中止並返回該值。若是全部的表達式都是空值,最終將返回一個空值。使用COALESCE在於大部分包含空值的表達式最終將返回空值。

// 場景一:你想要獲取最大值,而後+1返回(即返回的值已經默認爲空了),程序接收了原本不應爲空的值去運算,就會出錯。
SELECT MAX(my_money)+1 FROM tb_test;

// 改進方法:使用 coalesce函數   COALESCE(值1, 值2,......, 值n) ,只要遇到非null值就返回。
// 這樣子就能夠設置一個值,讓你第一個不成功後,返回指定的值,以下面,返回的是1.
SELECT COALESCE(MAX(my_money)+1, 1) FROM tb_test;

方法二:使用case when then else end

參考的簡書網址

Case函數只返回第一個符合條件的值,剩下的Case部分將會被自動忽略。
Case when 至關於一個自定義的數據透視表,group by 是行名,case when 負責列名。

// 場景一:你想要獲取最大值,而後+1返回(即返回的值已經默認爲空了),程序接收了原本不應爲空的值去運算,就會出錯。
SELECT MAX(my_money)+1 FROM tb_test;

// 改進方法:使用 case when then函數。
// 這樣子就能夠設置一個值,讓你第一個不成功後,返回指定的值,以下面,返回的是1.
SELECT
     (CASE
         WHEN ( MAX(my_money) IS NOT NULL)
         THEN  MAX(my_money)+1
         ELSE 1
         END)
FROM tb_test;


---------------------
版權聲明:本文爲CSDN博主「pengjunzhen」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/Pengxiaozhen1111/article/details/86231776

多值

 

36. Oracle的主要數據類型

一 字符串類型

    字符串數據類型還能夠依據存儲空間分爲固定長度類型(CHAR/NCHAR) 和可變長度類型(VARCHAR2/NVARCHAR2)兩種.

    所謂固定長度:是指雖然輸入的字段值小於該字段的限制長度,可是實際存儲數據時,會先自動向右補足空格後,纔將字段值的內容存儲到數據塊中。這種方式雖然比較浪費空間,可是存儲效率較可變長度類型要好。同時還能減小數據行遷移狀況發生。

所謂可變長度:是指當輸入的字段值小於該字段的限制長度時,直接將字段值的內容存儲到數據塊中,而不會補上空白,這樣能夠節省數據塊空間。

1.1:CHAR類型 CHAR(size [BYTE | CHAR])

CHAR類型,定長字符串,會用空格填充來達到其最大長度。非NULL的CHAR(12)老是包含12字節信息。CHAR字段最多能夠存儲2,000字節的信息。若是建立表時,不指定CHAR長度,則默認爲1。另外你能夠指定它存儲字節或字符,例如 CHAR(12 BYTYE) CHAR(12 CHAR).通常來講默認是存儲字節,你能夠查看數據庫參數

NLS_LENGTH_SEMANTICS的值。

SQL Code

  1. SQL> show parameter nls_length_semantics;
  2. NAME                   TYPE           VALUE
  3. ------------------   ----------- -----------------
  4. nls_length_semantics   string          BYTE
  5. eg:
  6. CREATE TABLE TEST
  7. (
  8. NAME_OLD CHAR(10),
  9. NAME_NEW CHAR(10 CHAR)
  10. )
  11. INSERT INTO TEST
  12. ( NAME_OLD, NAME_NEW)
  13. SELECT 'ABCDEFGHIJ' , '你清除字節與字符' FROM DUAL;
  14. COMMIT;
  15. INSERT INTO TEST
  16. ( NAME_OLD, NAME_NEW)
  17. SELECT '你清除字節與字符' , 'ABCDEFGHIJ' FROM DUAL;
  18. ORA-12899: 列 "SYS"."TEST"."NAME_OLD" 的值太大 (實際值: 24, 最大值: 10)

注意:數據庫的NLS_CHARACTERSET 爲AL32UTF8,即一個漢字佔用三到四個字節。若是NLS_CHARACTERSET爲ZHS16GBK,則一個字符佔用兩個字節。

若是串的長度小於或等於250(0x01~0xFA), Oracle 會使用1 個字節來表示長度。對於全部長度超過250 的串,都會在一個標誌字節0xFE 後跟有兩個字節來表示長度。所以,若是有一個包含「Hello World」的VARCHAR2(80),則在塊中可能如圖12.-1 所示

clip_image002

1.2: NCHAR類型

這是一個包含UNICODE格式數據的定長字符串。NCHAR字段最多能夠存儲2,000字節的信息。它的最大長度取決於國家字符集。另外查詢時,若是字段是NCHAR類型,則須要以下書寫

SELECT translated_description FROM product_descriptions

WHERE translated_name = N'LCD Monitor 11/PM';

1.3 VARCHAR類型

不要使用VARCHAR數據類型。使用VARCHAR2數據類型。雖然VARCHAR數據類型目前是VARCHAR2的同義詞,VARCHAR數據類型將計劃被從新定義爲一個單獨的數據類型用於可變長度的字符串相比,具備不一樣的比較語義。

1.4: VARCHAR2類型

變長字符串,與CHAR類型不一樣,它不會使用空格填充至最大長度。VARCHAR2最多能夠存儲4,000字節的信息。

1.5: NVARCHAR2類型

這是一個包含UNICODE格式數據的變長字符串。 NVARCHAR2最多能夠存儲4,000字節的信息。

二. 數字類型

2.1 NUMBER類型

NUMBER(P,S)是最多見的數字類型,能夠存放數據範圍爲10^130~10^126(不包含此值),須要1~22字節(BYTE)不等的存儲空間。

P 是Precison的英文縮寫,即精度縮寫,表示有效數字的位數,最多不能超過38個有效數字

S是Scale的英文縮寫,能夠使用的範圍爲-84~127。Scale爲正數時,表示從小數點到最低有效數字的位數,它爲負數時,表示從最大有效數字到小數點的位數

下面是官方文檔的示例

Actual Data Specified As Specified As
Specified As    
     
     
     
     
     
     
     
     
     
     
     
     
     

 

123.89

NUMBER

123.89

123.89

NUMBER(3)

124

123.89

NUMBER(6,2)

123.89

123.89

NUMBER(6,1)

123.9

123.89

NUMBER(3)

124

123.89

NUMBER(4,2)

exceeds precision

123.89

NUMBER(6,-2)

100

.01234

NUMBER(4,5)

.01234

.00012

NUMBER(4,5)

.00012

.000127

NUMBER(4,5)

.00013

.0000012

NUMBER(2,7)

.0000012

.00000123

NUMBER(2,7)

.0000012

1.2e-4

NUMBER(2,5)

0.00012

1.2e-5

NUMBER(2,5)

0.00001

2.2 INTEGER類型

INTEGER是NUMBER的子類型,它等同於NUMBER(38,0),用來存儲整數。若插入、更新的數值有小數,則會被四捨五入。

例如:

CREATE TABLE TEST

(

ID INTEGER

)

查看錶TEST的DDL(如何查看建立表的DDL語句)定義以下所示

CREATE TABLE "SYS"."TEST"

( "ID" NUMBER(*,0)

) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "SYSTEM" ;

INSERT INTO TEST

SELECT 12.34 FROM DUAL;

INSERT INTO TEST

SELECT 12.56 FROM DUAL;

SQL> SELECT * FROM TEST;

ID

----------

12

13

2.3 浮點數

浮點數能夠有一個十進制數點任何地方從第一個到最後一個數字,或者能夠在全部有沒有小數點。指數可能(可選) 用於如下數量增長的範圍 (例如, 1.777e-20)。刻度值不適用於浮點數字,由於能夠顯示在小數點後的位數的數量不受限制。

二進制浮點數不一樣數量的值由 Oracle 數據庫內部存儲的方式。使用小數精度數存儲值。徹底相同號碼存儲範圍和數量由支持的精度內的全部文本。正是由於使用小數精度(數字 0 到 9) 表示文本存儲文本。使用二進制精度 (數字 0 和 1) 存儲二進制浮點數。這種存儲方案不能表明全部確切地使用小數精度的值。頻繁地,將值從十進制轉換爲二進制的精度時出現的錯誤時撤消值回從二進制轉換爲十進制精度。在字面 0.1 是一個這樣的例子。

Oracle 數據庫提供了專爲浮點數的兩種數值數據類型:

BINARY_FLOAT

BINARY_FLOAT 是 32 位、 單精度浮點數字數據類型。能夠支持至少6位精度,每一個 BINARY_FLOAT 的值須要 5 個字節,包括長度字節。

BINARY_DOUBLE

BINARY_DOUBLE 是爲 64 位,雙精度浮點數字數據類型。每一個 BINARY_DOUBLE 的值須要 9 個字節,包括長度字節。

在數字的列中,浮點數有小數精度。在 BINARY_FLOAT 或 BINARY_DOUBLE 的列中,浮點數有二進制的精度。二進制浮點數支持的特殊值無窮大和 NaN (不是數字)。

您能夠指定列在表 2-4 範圍內的浮點數。"數字文本"中定義了用於指定浮點數的格式。

Table 2-3 Floating Point Number Limits

Value

Binary-Float

Binary-Double

Maximum positive finite value

3.40282E+38F

1.79769313486231E+308

Minimum positive finite value

1.17549E-38F

2.22507485850720E-308

2.5 FLOAT類型

FLOAT類型也是NUMBER的子類型。

Float(n),數 n 指示位的精度,能夠存儲的值的數目。N 值的範圍能夠從 1 到 126。若要從二進制轉換爲十進制的精度,請將 n 乘以 0.30103。要從十進制轉換爲二進制的精度,請用 3.32193 乘小數精度。126 位二進制精度的最大值是大約至關於 38 位小數精度。

三. 日期類型

日期類型用於存儲日期數據,可是並非使用通常的格式(2012-08-08)直接存儲到數據庫的。

3.1 DATE類型

DATE是最經常使用的數據類型,日期數據類型存儲日期和時間信息。雖然能夠用字符或數字類型表示日期和時間信息,可是日期數據類型具備特殊關聯的屬性。爲每一個日期值,Oracle 存儲如下信息: 世紀、 年、 月、 日期、 小時、 分鐘和秒。通常佔用7個字節的存儲空間。

3.2 TIMESTAMP類型

這是一個7字節或12字節的定寬日期/時間數據類型。它與DATE數據類型不一樣,由於TIMESTAMP能夠包含小數秒,帶小數秒的TIMESTAMP在小數點右邊最多能夠保留9位

3.3 TIMESTAMP WITH TIME ZONE類型

這是TIMESTAMP類型的變種,它包含了時區偏移量的值

3.4 TIMESTAMP WITH LOCAL TIME ZONE類型

3.5 INTERVAL YEAR TO MOTH

3.6 INTERVAL DAY TO SECOND

四. LOB類型

內置的LOB數據類型包括BLOB、CLOB、NCLOB、BFILE(外部存儲)的大型化和非結構化數據,如文本、圖像、視屏、空間數據存儲。BLOB、CLOB、NCLOB類型

4.1 CLOB 數據類型

   它存儲單字節和多字節字符數據。支持固定寬度和可變寬度的字符集。CLOB對象能夠存儲最多 (4 gigabytes-1) * (database block size) 大小的字符

4.2 NCLOB 數據類型

   它存儲UNICODE類型的數據,支持固定寬度和可變寬度的字符集,NCLOB對象能夠存儲最多(4 gigabytes-1) * (database block size)大小的文本數據。

4.3 BLOB 數據類型

   它存儲非結構化的二進制數據大對象,它能夠被認爲是沒有字符集語義的比特流,通常是圖像、聲音、視頻等文件。BLOB對象最多存儲(4 gigabytes-1) * (database block size)的二進制數據。

4.4 BFILE 數據類型

二進制文件,存儲在數據庫外的系統文件,只讀的,數據庫會將該文件當二進制文件處理

五. RAW & LONG RAW類型

5.1 LONG類型

它存儲變長字符串,最多達2G的字符數據(2GB是指2千兆字節, 而不是2千兆字符),與VARCHAR2 或CHAR 類型同樣,存儲在LONG 類型中的文本要進行字符集轉換。ORACLE建議開發中使用CLOB替代LONG類型。支持LONG 列只是爲了保證向後兼容性。CLOB類型比LONG類型的限制要少得多。 LONG類型的限制以下:

1.一個表中只有一列能夠爲LONG型。(Why?有些不明白)

2.LONG列不能定義爲主鍵或惟一約束,

3.不能創建索引

4.LONG數據不能指定正則表達式。

5.函數或存儲過程不能接受LONG數據類型的參數。

6.LONG列不能出如今WHERE子句或完整性約束(除了可能會出現NULL和NOT NULL約束)

官方文檔描敘以下:

The use of LONG values is subject to these restrictions:

A table can contain only one LONG column.

You cannot create an object type with a LONG attribute.

LONG columns cannot appear in WHERE clauses or in integrity constraints (except that they can appear in NULL and NOT NULL constraints).

LONG columns cannot be indexed.

LONG data cannot be specified in regular expressions.

A stored function cannot return a LONG value.

You can declare a variable or argument of a PL/SQL program unit using the LONG datatype. However, you cannot then call the program unit from SQL.

Within a single SQL statement, all LONG columns, updated tables, and locked tables must be located on the same database.

LONG and LONG RAW columns cannot be used in distributed SQL statements and cannot be replicated.

If a table has both LONG and LOB columns, then you cannot bind more than 4000 bytes of data to both the LONG and LOB columns in the same SQL statement. However, you can bind more than 4000 bytes of data to either the LONG or the LOB column.

In addition, LONG columns cannot appear in these parts of SQL statements:

GROUP BY clauses, ORDER BY clauses, or CONNECT BY clauses or with the DISTINCT operator in SELECT statements

The UNIQUE operator of a SELECT statement

The column list of a CREATE CLUSTER statement

The CLUSTER clause of a CREATE MATERIALIZED VIEW statement

SQL built-in functions, expressions, or conditions

SELECT lists of queries containing GROUP BY clauses

SELECT lists of subqueries or queries combined by the UNION, INTERSECT, or MINUS set operators

SELECT lists of CREATE TABLE ... AS SELECT statements

ALTER TABLE ... MOVE statements

SELECT lists in subqueries in INSERT statements

5.2 LONG RAW 類型,能存儲2GB 的原始二進制數據(不用進行字符集轉換的數據)

5.3 RAW類型

用於存儲二進制或字符類型數據,變長二進制數據類型,這說明採用這種數據類型存儲的數據不會發生字符集轉換。這種類型最多能夠存儲2,000字節的信息

六. ROWID & UROWID類型

在數據庫中的每一行都有一個地址。然而,一些錶行的地址不是物理或永久的,或者不是ORACLE數據庫生成的。

例如,索引組織錶行地址存儲在索引的葉子,能夠移動。

例如,外部表的ROWID(如經過網關訪問DB2表)不是​​標準的ORACLE的rowid。

ORACLE使用通用的ROWID(UROWIDs)的存儲地址的索引組織表和外表。索引組織表有邏輯urowids的,和國外表的外urowids,。UROWID這兩種類型的存儲在ROWID僞(堆組織的表的物理行id)。

建立基於邏輯的rowid在表中的主鍵。邏輯的rowid不會改變,只要主鍵不改變。索引組織表的ROWID僞UROWID數據類型。你能夠訪問這個僞列,你會堆組織表的ROWID僞(即便用一個SELECT ...ROWID語句)。若是你想存儲的rowid索引組織表,那麼你就能夠定義一列的表型UROWID到列檢索值的ROWID僞。

37. 常見的約束有哪些

Mysql數據庫的約束類型有:主鍵約束(Primary Key),外鍵約束(Foreign Key),非空約束(Not Null),惟一性約束(Unique),默認約束(Default)。一.主鍵約束(Primary Key)    主鍵約束要求主鍵列的數據惟一,而且不能爲空。主鍵分爲兩種類型:單字段主鍵和多字段聯合主鍵。1.單字段主鍵在定義列的同時指定主鍵,語法規則:字段名 數據類型 Primary Key [默認值]


--------------------

在定義完成全部列以後指定主鍵,語法規則:[Constraint<約束名>] Primary Key [字段名]

-

通常在建表時咱們會選擇將主鍵放在全部列後。2.多字段聯合主鍵主鍵由多個字段聯合組成。語法規則:Primary Key[字段1,字段2,....,字段n]

二.外鍵約束(Foreign Key)      外鍵用來在兩個表的

通常在建表時咱們會選擇將主鍵放在全部列後。

2.多字段聯合主鍵

主鍵由多個字段聯合組成。語法規則:Primary Key[字段1,字段2,....,字段n]

二.外鍵約束(Foreign Key)

      外鍵用來在兩個表的數據之間創建鏈接,它能夠是一列或者多列。一個表能夠有一個或者多個外鍵。一個表的外鍵能夠爲空,若不爲空,則每個外鍵值必須等於另外一個表中主鍵的某個值。

      外鍵的做用:保證數據應用的完整性。

      主表(父表):對於兩個具備關聯關係的表而言,相關聯字段中的主鍵所在的那個表便是主表。

      從表(子表):對於兩個具備關聯關係的表而言,相關聯字段中的外鍵所在的那個表便是從表。

     建立外表的語法規則:[Constraint<外鍵名>]Foreign Key 字段名1[,字段名2,....] References<主表名> 主鍵列1 [,主鍵列2,....]

建立一個表test_1

定義數據表test_2,讓它的主鍵deptId做爲外鍵關聯到的test_1的主鍵id,

在表test_2上添加了名稱爲test_deptId的外鍵約束,外鍵名稱爲deptId,其依賴於表test_2的主鍵id.

三.使用非空約束(Not Null)

     非空約束指字段的值不能爲空。

     非空約束 語法規則:字段名 數據類型 not null

四.惟一性約束(Unique)

   惟一性約束要求該列惟一,容許爲空,可是隻能出現一個空值。惟一約束能夠保證一列或者幾列不出現重複值。

   非空約束的語法規則

   1.在定義完列以後直接指定惟一約束

    字段名 數據類型 unique

   2.在定義完全部列以後指定惟一約束

     [Constraint<約束名>] Unique(<字段名>)

聲明:Unique在表中能夠有一個或者多個字段聲明,而Primary Key,只能有一個。

五.默認約束(Default)(最簡單)

    默認約束指定某列的默認值。

    語法規則: 字段名 數據類型 Dfault 默認值

 

38. 什麼是序列

序列(SEQUENCE)是序列號生成器,能夠爲表中的行自動生成序列號,產生一組等間隔的數值(類型爲數字)。
其主要的用途是生成表的主鍵值,能夠在插入語句中引用,也能夠經過查詢檢查當前值,或使序列增至下一個值。
建立序列須要CREATE SEQUENCE系統權限。
序列的建立語法以下: CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE/ MINVALUE n|NOMAXVALUE}] [{CYCLE|NOCYCLE}] [{CACHE n|NOCACHE}];   INCREMENT BY 用於定義序列的步長,若是省略,則默認爲1,若是出現負值,則表明序列的值是按照此步長遞減的。
START WITH 定義序列的初始值(即產生的第一個值),默認爲1。 
MAXVALUE 定義序列生成器能產生的最大值。選項NOMAXVALUE是默認選項,表明沒有最大值定義,這時對於遞增序列,系統可以產生的最大值是10的27次方;對於遞減序列,最大值是-1。
 MINVALUE定義序列生成器能產生的最小值 ...

39. 事務控制的四大特性

事務是由一步或者幾步數據庫操做序列組成的邏輯執行單元,這系列操做要麼所有執行,要麼所有放棄執行。

通俗的說的話,事務就是一件事情,要麼成功執行到底,要麼回到起點,什麼都不作。

事物的特性(ACID)

原子性(Atomicity):正如原子時天然界最小顆粒,具備不可再分的特徵同樣。意思就是說,咱的事務是一個邏輯單元,不能再拆分了,好比總體的執行。

一致性(Consistency):事務執行的結果,必須使數據庫從一個一致性狀態,變到另外一個一致性狀態。好比說銀行之間的轉帳,從A帳戶向B帳戶轉入1000元。系統先減小A帳戶1000元,而後再爲B帳戶增長1000元。若是所有執行成功的話,則數據庫就處於一致性狀態。若是僅僅A帳戶金額修改,B帳戶沒有增長的話,那麼數據庫就處於不一致的狀態。所以,一致性必須經過原子性來保證。

隔離型(Isolation):各個事務執行互不干擾,任意一個事務的內部操做對其餘併發的事務都是隔離的。也就是說,併發執行的事務之間不能看到對方的中間狀態。併發事務之間是不能互相影響的。

持久性(Durability):事務一旦提交,對數據所作的改變都要記錄到存儲器中,一般就是保存進物理數據庫。

40. 數據庫設計範式如何應用在數據庫設計中

什麼是數據庫設計範式?

       咱們設計數據庫的目的是什麼?固然是爲了咱們使用起來方便,管理起來方便等等。這樣,咱們就須要一套科學的、規則的規範來知足它。

       範式的英文名稱是 Normal Form,它是英國人 E.F.Codd(關係數據庫的老祖宗)在上個世紀70年代提出關係數據庫模型後總結出來的,範式是關係數據庫理論的基礎,也是咱們在設計數據庫結構過程當中所要遵循的規則和指導方法。目前有跡可尋的共有8種範式,依次是:1NF,2NF,3NF,BCNF,4NF,5NF,DKNF,6NF。一般所用到的只是前三個範式,即:第一範式(1NF),第二範式(2NF),第三範式(3NF)。

數據庫設計範式的好處和不足

       好處:數據庫的設計範式是數據庫設計所須要知足的規範,剛剛也說過,它是爲了知足咱們使用和管理的須要,因而可知,它是對原先數據的優化,使咱們處理數據更爲便利。

       不足:數據每每種類繁多,並且每種數據之間又互相關聯,所以,在設計數據庫時,所須要知足的範式越多,那表的層次及結構也就越複雜,最終形成數據的處理困難。這樣,還不如不知足這些範式呢。因此在使用範式的時候也要細細斟酌,是否必定要使用該範式,必須根據實際狀況作出選擇。通常狀況下,咱們使用前三個範式已經夠用了,再也不使用更多範式,就能完成對數據的優化,達到最優效果。

1、第一範式(1NF)

規範定義:第一範式是指數據庫表中的每一列都是不可分割的基本數據項;同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。

有兩個點:實體的屬性的不可分割性(原子性)、實體的屬性的不重複性 / 不能有多個值。

解釋一下實體和屬性:就比如一個客戶(實體),他有姓名(屬性),年齡(屬性),電話(屬性),地址(屬性)等屬性。說通俗點就是表中的一行數據。

1.實體的屬性的不可分割性(原子性)

       這個說的就是實體的屬性不可再分,就比如一我的的電話號碼分爲三種:手機號碼、家庭電話以及辦公電話。這樣,咱們在設計表時,就不能這樣設計:

P8U{~2BT}0TSYL6VQ_MVYSS


                而應該這樣設計:

TNY~(2TUN9KNQS7}THJU$8X


         2.實體的屬性的不重複性 / 不能有多個值(其實就是一個屬性欄裏不能出現多個值,畢竟同一個屬性欄中的值的屬性也必然是同樣的)

       即不能出現多個或者是重複的實體的屬性。注意,這裏是屬性的不重複或單一性,什麼叫屬性不重複?打個比方,如手機號碼、家庭電話以及辦公電話三者都屬於電話號碼這一屬性,而當咱們在設計表時,在電話號碼這一屬性中就可能會出現這我的的三個號碼,剛也說了,這三個號碼都屬於電話號碼這一屬性,所以屬於相同屬性,這樣就違反了實體的屬性的不重複性這一特性。又由於三個號碼出如今了同一個屬性中,所以也就同時違反了實體的屬性不能有多個值這一特性。

例如:

{UTQN@QUNVGHX]TDNPZ}(07[4]

 


     
                顯然,咱們能夠看到,Tel這一欄存放的是客戶的聯繫電話,可是對於每一個客戶而言,他們都具備三個電話(手機號碼、家庭電話以及辦公電話),這樣,咱們在設計時就不能將這三個相同的屬性放在同一個屬性列表當中,所以,上面這張表違反了數據庫設計的第一範式。具體解決方案以下:

9G4}0PYP@DE}K6JK~HBO20S


                1NF是關係模式應具有的最起碼的條件,若是數據庫設計不能知足第一範式,就不能被稱爲關係型數據庫。也就是說,只要是關係型數據庫,就必定要知足第一範式。

2、第二範式(2NF)

是在第一範式( 1NF) 的基礎上創建起來的,即知足第二範式( 2NF)必須先知足第一範式( 1NF)。

規範定義:若是關係模型R爲第一範式,而且數據庫表中不存在非關鍵字段對任一候選關鍵字段的部分函數依賴,即符合第二範式。R中的每個非主屬性徹底函數依賴於R的某個候選鍵,則稱R爲第二範式(若是A是關係模式R的候選鍵的一個屬性,則稱A是R的主屬性,不然稱A是R的非主屬性)。

       主屬性:存在於全部候選鍵中的屬性,稱之爲主屬性。

       候選鍵(候選關鍵字段):就是能夠區別一個個實體的最少屬性組合,是每一個實體的惟一標識。一個表可能有多個候選鍵,從這些候選鍵中選擇一個做爲主鍵。

       部分函數依賴:一個屬性與另外一個屬性不徹底相關。

       徹底函數依賴:一個屬性與另外一個屬性徹底相關。(下面會詳細解釋)

       好比,一個學生信息表,其中每個學生都擁有Id,Name,Age,Sex,Add等屬性,咱們假設Id存放的是學生的身份證號碼,這樣Id就能夠做爲每一個學生的惟一標識,那麼這個Id就能夠被稱爲候選鍵。又由於它做爲每一個學生的惟一標識,那麼咱們能夠理解爲它與其餘屬性徹底相關,這就是徹底函數依賴。

       這時,咱們假設Id和Name做爲學生的惟一標識,也就是候選鍵,這樣作顯然是不行的。由於即便去掉Name,咱們也一樣能夠肯定一個學生,也就是說,做爲候選鍵的屬性組合,必須都有本身的做用。並且,假設又出現了一個字段(屬性)銀行卡號,那麼,這個銀行卡號僅與Id有關,而不與Name相關,這樣,就出現了非關鍵字段對候選關鍵字段的部分函數依賴,那麼這個屬性組合是不符合要求的,應當從新選擇。

舉個例子:


             化工@T]1$@)%6XW(7NNCJI[%CU4
             99
                該表中一個學生能夠選多門課,一門課有多個學生,學生姓名可能出現重名。所以學號和課程號能夠惟一肯定一條記錄,所以用學號和課程號作主鍵。表中姓名、專業經過學號就能惟一肯定,可是課程名卻只與課程號有關,這樣就造成了部分函數依賴,違背了第二範式。

       違背第二範式將產生數據信息冗餘和數據更新異常的問題。

       1.數據信息冗餘:出現了重複的課程號-課程名。

       2.數據更新異常:假如如今有一門「計算機導論」要加入表中,可是因爲沒有學生考這一門課,那麼這麼課程就不能加入到表中(只有課程號和課程名而沒有其餘信息)。

       解決辦法:將其分爲三種關係模式:學生表、課程表和成績表

學生表:

~}}PO[2_HJEBTO2PS@AH[NV

3OU9WPTID97MY[V4~PKRMQW

MUPT)]S74@XNKHVHH@`QM_G

 


         3、第三範式(3NF)

規範定義:在知足第二範式的基礎上,在實體中不存在非主鍵屬性傳遞函數依賴於主鍵屬性。

       傳遞函數依賴:A依賴於B,B依賴於C,就能夠說A依賴C。

第三範式具備以下特徵:

1. 每一列(屬性)只有一個值。(1NF)

2. 每一行都能區分。(2NF)

3. 每個表都不包含其餘表已經包含的非主關鍵字信息。通俗的說:就是表中每一列都要與主鍵直接相關,而不是間接相關。

       就好比上面的例子中,在成績表中能夠出現學號,可是不能出現與學號相關的其餘信息,就是這個意思。
---------------------
版權聲明:本文爲CSDN博主「史博輝的開發日記」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/baidu_38760069/article/details/81162496

相關文章
相關標籤/搜索