數據庫基礎知識


一.1 數據庫

與Sybase不同,一個用戶就對應於一個數據庫。

create user CBMAIN

identified by "sunline"   

default tablespace CBMAIN_DATA     -- 表空間

temporary tablespace CBMAIN_TEMP;   -- 臨時表空間

一.2 表空間

表空間由一個或多個物理文件組成,一個表空間只能用於一個數據庫。

create temporary tablespace CBMAIN_TEMP datafile

'D:\Oradata\CBMAIN_TEMP01.dbf' size 200M,

'D:\Oradata\CBMAIN_TEMP02.dbf' size 200M

一.3 登錄身份

與Sybase不同,用戶登錄時需指定身份登錄。 分為Normal、sysdba、sysoper

三種不同身份。各自對數據庫擁有的權限不同,sysdba最高,normal 最低。如:

c:\> sqlpuls /nolog

sql>connect sys as sysdba

一.4 普通數據類型

Varchar2\Varchar:在建表語句中系統保留使用varchar,但建立的表結構實際為varchar2。PL\SQL中只允許使用varchar2。

Char:在建表語句中,字段內容長度固定可使用char,如狀態字段。其它情況下不建議使用Char來建表。

Boolean:不能用於建表,只用於PL\SQL;

Date\Timestamp:日期時間型,可用於建表,也可用於PL\SQL語句編寫。但在Ltts5.0表結構設計中不對其做廣泛應用,日期字段用char(8)來存儲。

Sys_refcursor:游標數據類型,采用此種類型定義的游標,在定義時無須編寫SELECT子句,打開時采用Open Cur_var For Select c1,c2 from tab1的方式。

一.5 結構

類似於C中的結構體,常在包、過程、函數中定義。如:

TYPE t_Result IS RECORD(

      Instam NUMBER(18, 2) default 0.00,

      Intxst NUMBER(18, 2) default 0.00,

      Intxam NUMBER(18, 2) default 0.00,

      Sqltxt VARCHAR2(2000),

      Instrt NUMBER(11, 7)

      );

行類型(rowtype)是個特殊的結構體,select * into xxxx時即可into到行類型變量,也可into到要素雷同的結構體。

常用於返回結果(Oracle out 型的參數必須傳入,便於擴展)。

一.6 

包具有部分OO特征:封裝性、多態性。

簡單的理解為一個容器,可以將若干個過程或者函數組合成一個更大的單位。

包體編寫過程體或函數體,包頭申明過程說明或函數說明。只有在包頭申明過的過程或函數才能被外部程序調用。

除過程和函數外,還可以申明包變量、常量、結構;其中包頭定義可以被外部直接訪問或修改(public)。包體部分定義的只能被包自身訪問(priavte)。

包的生命周期:起始於此包的第一次調用,結束於當前session的斷開。根據此特性,可用包頭或包體的變量、常量、結構存儲運算結果,甚至是系統級別的參數緩存。

不建議在包頭申明變量;通常方法是在包體申明變量同時配以一組方法訪問它。

通常在包頭定義某個結構,用來在過程傳遞或返回一組信息。

  • 常用系統包

UTL_FILE   ----------處理外部文件

DBMS_OUTPUT  ----調試PL/SQLDEBUG

DBMS_SQL   ----------執行動態SQL PL\SQL

dbms_job   ------管理JOB

dbms_system  -------跟蹤用戶,SESSION

dbms_transaction -------- 管理SQL事務

 

一.7 過程與函數

原則上,過程和包不允許獨立編寫,必須封裝在包中。

與sybase不同, out 型的參數必須傳入,不能缺省。

函數雖可定義out型變量,但不建議如此應用。當且僅當所實現只返回一個(含預估未來)基礎數據類型(字符、數字、布爾、日期)的時候才將此功能申明為函數。其它情況下都申明為方法。

在包頭有申明的過程在定義out型變量時,建議用一個結構體。目的是在未來擴展輸出參數時,無須修改已修改的代碼。

過程或函數定義基礎類型參數時,varchar2, number 等即可。沒必要使用用戶自定義類型如:sys_type.u_acctno%type 或者kna_accs.acctno%type;

對於out 或in out 參數定義時 nocopy 關鍵字的意義:

不加nocopy傳遞的是復制(by value),否則傳遞的是地址(by reference)。

傳遞地址對大型結構或大數據時可以提高效率。

在出現異常時,不加nocopy的情況下,外層程序讀到的仍然是原值。加nocopy的情況下,若有修改,外層程序讀到的是修改之后的值。因此使用nocopy 時,需要確保在被調用過程中處理所有的異常。

一.8 事務

Sybase需要用Begin tran來控制是否需要手動commit或rollback; Oralce無此語句,但有一開關Set autocommit OFF/ON;將commit或rollback的權力交給用戶。默認關閉,即由用戶來控制事務的提交或回滾;也就沒有事務積數器這一全局變量(@@transcount)。

  • DDL語句與事務

Alter … create …等都屬於DDL語句。

由於Oracle執行DDL語句時會自動調用Commit,因此禁止在業務程序里使用DDL語句。

  • 獨立事務

PRAGMA  AUTONOMOUS_TRANSACTION;

可在某個子過程或函數中單獨申明一段事務,有關其涉及到的業務邏輯處理,由自身commitrollback,不會影響到主程序已處理的事務。

注意:函數中若有事務語句,必須申明獨立事務。即:若無特殊情況,涉及事務處理都不寫成函數,都應寫成過程。

相關應用:生成流水號、記錄密碼錯誤等。

一.9 異常

  • 概念要點

Sybase由系統控制異常,Oracle則可主動捕捉異常。每當PL/SQL違背了ORACLE原則或超越了系統依賴的原則就會隱式的產生內部異常。

異常分為兩類:分為系統異常和用戶自定義異常。用戶定義異常則需要顯現的拋出。

拋出方式

異常類型

通過PL/SQL運行引擎

系統內部異常

使用RAISE語句

用戶定義異常

調用RAISE_APPLICATION_ERROR存儲過程

用戶定義異常

異常處理是用來處理正常執行過程中未預料的事件。如果PL/SQL程序塊一旦產生異常而又沒有指出如何處理時,程序會自動終止。

系統內部異常分為:預定義的內部異常和未定義內部異常。未定義內部異常只能在Other部分捕捉。

常見預定義異常

sqlerrm

sqlcode

描述

no_data_found

ora-01403

+100

Select into無符合條件的記錄

too_many_rows

ora-01422

-1422

Select into符合條件的記錄有多條

dup_val_on_index

ora-00001

-1

違反唯一約束

value_error

ora-06502

-6502

發生算數、轉換、截斷或大小約束錯誤

storage_error

ora-06500

-6500

內存溢出

zero_divide

ora-01476

-1476

除數為零

case_not_found

ora-06592

-6530

無匹配when子句也無默認else子句

cursor_already_open

ora-06511

-6511

試圖打開已經打開的游標

timeout_on_resource

ora-00051

-51

等待某一資源,超時

access_into_null

ora-06530

-6530

試圖給未初始化對象的屬性賦值

invalid_cursor

ora-01001

-1001

游標操作錯誤,如:關閉未打開

login_denied

ora-01017

-1017

登錄時用戶名或密碼非法

program_error

ora-06501

-6501

PL/SQL內部錯誤

rowtype_mismatch

ora-06504

-6504

賦值變量與游標返回變量不兼容

self_is_null

ora-30625

-30625

 

sys_invalid_rowid

ora-01410

-1410

字符串轉化成rowid失敗

subscript_beyond_count

ora-06533

-6533

 

subscript_outside_limit

ora-06532

-6532

 

collection_is_null

ora-06531

-6531

 

invalid_number

ora-01722

-1722

字符串轉化成數字失敗

not_logged_on

ora-01012

-1012

未連接數據庫前訪問數據

 

  • 異常傳播機制:

當異常發生時,若本語句塊未做異常處理,控制將轉到或傳播到外層語句塊的異常處理部分。直到外層捕捉到異常,則運行捕捉異常后語句塊;若外層塊沒有該異常的處理程序則傳播到調用環境,並立即終止。

 

  • SQL與異常規范:

總原則:

任何異常處理必須有Others分支

1.SELECT  INTO 語句

常見no_data_foundtoo_many_rows異常,也就是說要保證查詢結果有且只有一條數據才不會觸發入上異常。因此不能用 SQL%Rowcount來判斷行數。

若where 條件中包括物理上的唯一索引,則可以不對too_many_rows進行處理。

另:無group by 子句的,SELECT Count(*)、sum、max等聚合函數 INTO 能保證有且僅有一條數據,因此可以不對too_many_rows和 no_data_found進行處理。 

2.INSERT 語句:

若插入的表存在唯一索引或主鍵,則需要判斷 dup_val_on_index 異常;

空值異常在 Others 里處理 (ORA-01400);

能用 SQL%Rowcount 來判斷行數。

3.Update語句:

若被修改的列是唯一索引所在列,則需要判斷 dup_val_on_index 異常;

空值異常在 Others 里處理 (ORA-01400);

能用 SQL%Rowcount 來判斷行數。

4.DELETE 語句:

處理Other異常即可,無須其它異常處理

能用 SQL%Rowcount 來判斷行數。

  • 異常嵌套:

為了程序結構清晰,應避免異常處理語句中出現異常嵌套;也就是說,異常處理中不應該再編寫可能再次出現異常的語句如如:select、insert、delete、update等語句。可寫成子程序或跳出此語句塊后再處理。

一.10 臨時表

不同於Sybase,臨時表必須事先創建好。

臨時表獨立於每個session,也就是說,A連接不可能訪問到B連接臨時表中的數據。臨時表有兩種創建形式:

commit preserve rows,隨着事務提交保存。數據一直存儲,直到當前session斷開。因此,在此種情況下,去維護臨時表的表結構是行不通的。

commit delete rows,隨着事務提交時清空。若只是用於中間計算,可用此種形式。

小技巧:臨時表所有字段均為空,以便適用於不同場景。

一.11 哈希表

也稱關聯數組、索引表。是普通集合的擴展,可以用健值獲得數組中的值。

優點,鍵值唯一,訪問速度快。

  • 普通集合

Type t_array is table of varchar2(20)

L_array t_array := {‘John’, ‘Susan’};

Dbms_Output.Put_Line(l_Array(2)); -- 下標

  • 哈希表

Type t_array_hash is table of varchar2(20) index by varchar2(4);

L_array_hash t_array_hash;

L_array_hash(‘0001’) := ‘John’;

L_array_hash(‘0002’) := ‘Susan’;

Dbms_Output.Put_Line(l_Array_Hash('0001')); -- 鍵值

  • 單主鍵表轉為一維哈希表

如有下表(userid varchar2(5) is primary key, userna varchar2(20), brchno varchar2(6)

TYPE t_User_Rec IS RECORD( -- 先對主鍵外字段建立“記錄型”用戶自定義類型

userna VARCHAR2(20),

      brchno VARCHAR2(6)

);

-- 在結構上建立哈希表

TYPE t_User_tab IS TABLE OF t_User_Rec INDEX BY VARCHAR2(5);

l_User_Rec t_User_Rec; --申明記錄變量

l_User_tab t_User_tab; --申明表變量

l_Userna   varchar2(20); --普通變量

-- 哈希表插入記錄

l_User_Rec.userna = ‘李大照’; l_User_Rec.brchno = ‘010201’;

l_User_tab(‘用戶1’) := l_User_Rec; -- 記錄1

l_User_Rec.userna = ‘王虎’; l_User_Rec.brchno = ‘019801’;

l_User_tab(‘00002’) := l_User_Rec; -- 記錄2

-- 訪問記錄

l_Userna = l_User_tab(‘00002’).Userna;

  • 雙主鍵表轉為二維哈希表

如上表需增加維度行號(bankno varchar2(12) is primary key, userid varchar2(5) is primary key,…)

-- 需要增加的工作是對一維哈希表再建立一層哈希表

TYPE t_Bank_User_tab IS TABLE OF t_User_tab INDEX BY VARCHAR2(12);

l_User_Rec     t_User_Rec; --申明記錄變量

l_bank_user    t_Bank_User_tab --申明二維表變量

l_Userna       varchar2(20);   --普通變量

-- 哈希表插入記錄

l_User_Rec.userna = ‘李大照’; l_User_Rec.brchno = ‘010201’;

l_User_tab(‘武漢分行’)(‘用戶1’) := l_User_Rec; -- 記錄1

l_User_Rec.userna = ‘王虎’; l_User_Rec.brchno = ‘019801’;

l_User_tab(‘常洲分行’)(‘00002’) := l_User_Rec; -- 記錄2

-- 訪問記錄

l_Userna = l_User_tab(‘常洲分行’)(‘00002’).Userna;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM