11G Concept 第二章翻譯 table and table cluster(表和table cluster,這個名詞不翻譯)

前面第一章是簡單介紹了一下Oracle 數據庫

而第二章到第六章則是正文內容,屬於正文的第一塊

Part I Oracle Relational dataStructures(Oracle關係數據結構)

本Part 描述了Oracle數據庫的基礎數據結構,包括 數據完整性規則,以及一些存着metadata的結構(metadata指元數據,具體意思自己百度吧)

第二章Tables and Table Clusters(表及TableClusters)

本章簡單介紹了各種schemaObjects。以及詳細討論各種表。

表是schema objects中最常使用到的。

 

Introduction to SchemaObjects 介紹Schema中的各種對象

一個數據庫schema 是個邏輯的容器,容器裏放着一大堆data structures(數據結構),這些數據結構就叫做schemaobjects.

例如:表,索引

schemaobjects的創建和操作都是通過SQL來完成。

每個數據庫用戶都有密碼,以及各種各樣的數據庫權限.每個用戶都有屬於自己的schema,且schema的名字和用戶名一樣。

例如:舉個例子 hr用戶有hr Schema,這個Schema包含着schemaobjects,比如一個叫employee的表。在生產數據庫中,大多數情況下一個賬戶代表的是一個應用,而不是真的一個人。

在schema中,每個類型的的schemaobject對象都有自己唯一的名稱。例如hr.employees指代在hr Schema中的employees表

下圖描述了一個叫hr的schema以及它擁有者(也就是指hr用戶)還有在schema中的schema objects


Schema Object Types (SchemaObject的各種類型)

在關係型數據庫中,最重要的schemaobject就是表。

表用行的形式存儲數據

OracleSQL 還可以創建和操作其他類型的schema object,包括:

·Indexes(各種索引)

  索引是個schema object。它幫助用戶能夠直接的,快速的去訪問相關行。Oracle database 支持幾種index 類型。還有一種叫表叫索引組織表,這種表的記錄都是按照索引的結構存儲的(也就是已經排好序的)。

·Partitions(各種分區)

  分區就是大表或者大索引的一部分.每個分區有它自己的名字還可以有它自己的存儲特性

·Views(視圖)

  視圖是定製的數據顯示,從一個或者多表,或者其他視圖中。你這可以把它理解爲複雜的查詢語句不過這些語句是存儲起來的。視圖並不真正的擁有數據。

·Sequences(序列)

  序列是一個用戶創建,多個用戶都能共享使用的。它用來形成整數,基本上,序列都被用在生成主鍵列值.

·Dimensions(維)

  一個維定義了一個 parent-chidrelationship beween  paris of column sets(兩組列)(感覺怎麼翻都很拖沓,乾脆不翻這句)

  維通常用在可分類的數據 比如 客戶信息,產品信息, 以及時間

·Synonyms(同義詞)

  同義詞就是其他人對象的別名。由於同義詞只是一個別名,它只需要在數據字典中定義一下就可以,不需要存儲空間

·PL/SQL subprogramsand packages(過程和包)

  PL/SQL是OracleSQL的程序化擴展,PL/SQLsubprogram 指的就是一個PL/SQL塊,可以被調用。PL/SQL package 就是將一個subprogram 和它用到的變量啊,cursor啊放到一起,方便別人調用。

 

還有一些其他類型的對象,它們也是通過SQL創建和操作的,但是它們不屬於schema,所以它們不是schema objects ,它們包括:users(用戶),roles(角色),contexts,以及directory objects(目錄對象,用在expdp/impdp)

 

Schema object Storage(Schemaobject的存儲方式)

一部分schema objects存儲數據到 名叫segments(段)的邏輯存儲結構。例如,一個沒有分區的普通表(也叫堆表)/索引都有屬於自己的segment。一一對應。

而其他的比如view或者sequence,都僅僅只有元數據(存放在數據字典),

這一節只介紹擁有segment的schemaobjects

 

Oracle 數據庫將schemaobject邏輯的存在tablespace(表空間), 而schema和tablespaces是沒有任何關係的,不要放在一起理解。表空間可以存放不同schema的schema objects,而且每個schema的schema objects可以放在不同的表空間。一個表空間由多個數據文件物理組成,而一個segment中的數據,可以物理的存放在多個數據文件上。

 

下圖顯示了segment,tablespace 和數據文件的關係。一個segment橫跨屬於一個表空間的兩個數據文件。一個segment不能橫跨多個表空間。


Schema ObjectDependencies(Schema Object之間的依賴關係)

一些schema objects 會引用別的schemaobjects,例如:一個視圖其實就是一個查詢,這個查詢依賴於一些表或者視圖。又例如:一個PL/SQL subprogram 引用了其他的subprogram

如果,對象A的定義中引用了對象B,則A是dependentobject(相對於B來說),而B是一個referenced object(相對於A來說).

Oracle數據庫提供了一個自動機制來確保dependent object引用的數據永遠是ferenced objects中當前的。當referenced object結構發生改變時,則可能會影響它的dependent object,dependent object可能會被標記爲失效.

例如:如果一個用戶刪了一個表,基於這個表的視圖,全部都會失效。

 

失效的dependent object 想重新生效,必須將依賴關係修復後重新編譯。

運行失效的存儲過程,重新編譯操作會自動進行。

下面的例子是說明schemaobjects怎樣創建dependencies,這個腳本創建了test_table表,以及一個存儲過程來查詢這個表:

CREATETABLE test_table(col1 INTEGER, col2 INTEGER);

CREATEOR REPLACE PROCEDURE test_proc

AS

BEGIN

  FOR x IN (select col1,col2 FROM test_table)

  LOOP

--processdata

  END LOOP;

END;

/

查一下test_proc的狀態:

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME  STATUS

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

TEST_PROC     VALID

 

test_table表增加一列col3,這時候存儲過程依然是valid,因爲它和col3沒有任何依賴關係

SQL>ALTER TABLE test_table ADD col3 NUMBER;

 

Tablealtered.

 

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME  STATUS

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

TEST_PROC     VALID

 

可是,修改了col1列的數據類型,而test_proc存儲過程是依賴於這列的,這將使得test_proc存儲過程失效:

SQL>ALTERTABLE test_table MODIFY col1 VARCHAR2(20);

 

Tablealtered.

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME           STATUS

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

TEST_PROC              NVALID

 

運行或者重新編譯一下這個存儲過程,使它恢復valid,必須像下面顯示的:

SQLEXECUTE test_proc

 

PL/SQLprocedure successfully completed.

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME        STATUS

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

TEST_PROC            VALID

 

SYS and SYSTEM Schemas

所有的Oracle數據庫都有一些默認的管理帳號,這些賬號原則上只供DBA使用。DBA這些帳號來執行一些像開關數據庫,管理存儲和內存,創建數據庫,創建用戶等等的管理任務。

管理賬戶SYS,這個用戶在創建數據庫的時候會自動創建.這個賬戶擁有最高的權限。

而與它關聯的SYS schema則存摺數據字典的基表和視圖.這些基表和視圖對於Oracle數據庫來說非常重要.

存在SYS中的這些基表和視圖,只能由數據庫自己操作,用戶絕對不可以擅自操作.

 

SYSTEM賬戶同樣在數據庫創建的時候自動創建.而SYSTEM schema裏面存了一些另外的表和視圖,這些東西同樣也是用來顯示一些管理信息,還有一些內部表和視圖也存在進去,Oracle數據庫一些可選的組建可能會用到。

永遠不要用SYSTEM schema來存一些與管理員無關的表(比如說業務表).

 

Sample Schemas(例子 schema)

Oracledatabase還可能有例子schema,這個實例schema能讓你根據oracle上的實例來實驗一些普通的數據庫任務.

hrschema 就是一個例子schema,它包括了 employees,departments,locations histories等等表,以及相應的一些信息。

下圖就是hr schema中的完整關係圖,Concepts中的大多數實驗都根據這個schema編寫的。


 

Overview of Tables(表的概述)

一個表描述的就是一個entity的一些非常明顯的特徵信息。舉個例子:

一個僱員就可以是一個entity。

Oracle數據庫的表分成以下幾種

·Relational tables(關係表)

  關係表有一些列,是最常見的表

·Object tables

  這種表可以說是一種模版,普通表(relationaltables)創建的時候可以直接根據已經創建好的Object tables來創建。例如:create table 普通表 of  (Object table); 不用指定列什麼的了。

 

一個的Relational table(關係表),可以根據結構分成以下幾種:

·Heap-organizedtable(堆表),存儲的行沒有順序,堆,就是把行隨便堆在那就完事。

  CREATE TABLE命令默認創建的就是這種表。

·Index-organizedtable(索引組織表,IOT)這種表將行按照主鍵的順序進行排列。

  對於一些應用,IOT能增強性能以及更有效的利用磁盤空間。

·External table(外部表),這種表是一種只讀表,這種表只有metadata存在數據庫中,但是真正的數據並不存在數據庫中。(也就是數據庫中只存表的結構,數據實際在外面)

 

表分兩種,普通表和臨時表。普通表的定義和數據會一直保存,除非你刪除它。而臨時表則不同,它數據是臨時的,有兩種級別事務級,session(會話級))

臨時表用在一些只需要臨時生成的數據,臨時使用,不用保存。

本小節分爲以下幾個主題:

·Columns and Rows(列,行)

·Example:CREATE TABLEand ALTER TABLE statements(舉例create table alter table)

·Oracle Data Types(列的數據類型)

·IntergrityConstraints(完整性約束)

·Object Tables (Object Table就是上面說的模版表)

·Temporary Tables( 臨時表)

·External Tables(外部表)

·Table Storage(表的存儲方式,也就是強調一下segment)

·Table Compression(表壓縮)

 

Columns and Rows

定義一個表,需要指定一個表名,以及一大堆列。一個列都表示一個屬性(特徵),例如:

employees表中employee_id列就是指 僱員(employee)的ID屬性。

一般,當你建表的時候,你需要給每個列 一個列名,一個數據類型,一個寬度。例如:

employee_id列的數據類型就是NUMBER(6),6就是寬度。說明這列只能插入數字,且最多6位。有些類型的寬度是預先設定好的,比如DATE。

表可以有virtual column(虛列),virtualcolumn不需要耗費磁盤空間。數據庫在用戶需要用到的時候會將虛列派生出來,例如:比如income虛列可以對salary ,commission_pct列起作用

表創建完成後,可以使用SQL插入,查詢,刪除和更新rows(行)。row(行)就是一條記錄,這條記錄由一堆相關列的值組成.例如:

employees中的一行,用來描述一個指定empoyee的詳細信息

 

Example:CREATE TABLE andALTER  TABLE statements

(createtable 和alter table的例子)

 

OracleSQL中創建表的命令是 CREATE TABLE.

CREATE TABLE employees

    (employee_id    NUMBER(6)

    ,first_name     VARCHAR2(20)

    ,last_name      VARCHAR2(25)

        CONSTRAINT    emp_last_name_nn  NOT NULL

    , email          VARCHAR2(25)

       CONSTRAINT     emp_email_nn  NOT NULL

    ,phone_number   VARCHAR2(20)

    ,hire_date      DATE

       CONSTRAINT    emp_hire_date_nn  NOT NULL

    , job_id         VARCHAR2(10)

       CONSTRAINT     emp_job_nn  NOT NULL

    , salary         NUMBER(8,2)

    ,commission_pct NUMBER(2,2)

    ,manager_id     NUMBER(6)

    ,department_id  NUMBER(4)

    ,CONSTRAINT     emp_salary_min

                    CHECK (salary > 0)

    ,CONSTRAINT     emp_email_uk

                    UNIQUE (email)

    ) ;

這個例子顯示了hr 例子schema中 employees表的創建語句。

這條語句指定一些列,如employee_id,­first_name等,爲每列指定了數據類型如NUMBER,DATE等

 

下面來一個修改表結構的列子,通過ALTERTABLE

ALTER TABLE employees

ADD ( CONSTRAINT    emp_emp_id_pk

                      PRIMARY KEY (employee_id)

    ,CONSTRAINT     emp_dept_fk

                      FOREIGN KEY (department_id)

                        REFERENCES departments

    ,CONSTRAINT     emp_job_fk

                      FOREIGN KEY (job_id)

                        REFERENCES jobs (job_id)

    ,CONSTRAINT     emp_manager_fk

                      FOREIGN KEY (manager_id)

                        REFERENCES employees

    ) ;

上面例子用ALTER TABLE語句給employees表增加了一個完整性約束,完整性約束強制保證了生意規則,預防了無效的信息進入到表。

 

下面再顯示個SELECT 返回的結果,

EMPLOYEE_IDFIRST_NAME  LAST_NAME   SALARY  COMMISSION_PCT  DEPARTMENT_ID

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

        100 Steven      King            24000                           90

        101 Neena       Kochhar         17000                           90

        102 Lex         De Haan         17000                           90

        103 Alexander   Hunold           9000                           60

        107 Diana       Lorentz          4200                           60

        149 Eleni       Zlotkey         10500             .2            80

        174 Ellen       Abel            11000             .3            80

        178 Kimberely   Grant            7000            .15

上面的這個例子顯示了表,列,行的一些重要特種:

·行描述了一個僱員的屬性:name(名字),salary(工資),department(所屬部門)等。例如,第一行顯示了一個僱員,名叫Steven King的信息。

·列描述了僱員的屬性,在這個例子中,employee_id列是主鍵,主鍵的意思是列中每個值必須都是唯一的,要保證任何兩個僱員的僱員ID都必須是不同的。

·非關鍵列則可以包含相同的值,比如這裏,ID爲101和102的salary列,值都是17000.

·foreign key(外鍵)列引用一個本表或者其他表的主鍵列,或者唯一性值列。在這個例子中,department_id就引用了departments表的department_id列。

·filed(字段),是行和列的交叉點,它只能有一個值,例如104僱員的department_id。這就是一個字段,在這裏,它的值是60。

·列可以沒有值,在Oracle裏,沒有值 稱爲NULL值。僱員100的commission_pct列的值就是NULL,而僱員149相同列值爲.2。

  一個列允許有NULL值,除非是主鍵,或者這列有NOTNULL完整性約束。

 

Oracle Data Types(Oracle 數據類型 )

每列都有數據類型,數據類型就是 特定的存儲格式,約束,以及可插入值的允許範圍。

存儲格式其實就是一組 對於值的固定的屬性集,這些屬性使Oracle數據庫處理一種數據類型的方法,和處理另外一種是不相同的。

例如:你可以對NUMBER數據類型做乘法,但是對RAW屬類型卻不行。

當你創建一個表,你必須指定每列的數據類型,之後插入列的每個值都會被認爲是相應的數據類型。

Oracle數據庫提供一些數據類型。最常用到的數據類型都屬於下面這些分類:

·Character Data Types(字符型)

·Numeric Data Types(數字型)

·Datatime Data Types(日期時間型)

·Rowid Data Types(Rowid型,行的物理存放位置)

·Format Model andData Types(將數值或者時間當成字符型存起來,需要按照一定的格式)

還有其他一些重要的數據類型包括 raw,largeobjects(LOBs),collections。

PL/SQL的常量和變量也都有數據類型。包括BOOLEAN(布爾),reference types(引用),composite types(records,也就是行),以及一些用戶自定義的類型。

 

Character Data Types(字符型)

字符型儲存 字符型數據,字符型的數字也算字符型。最常用的字符型是VARCHAR2,它是儲存字符最高效的選擇。

其中的值 與字符集有關(比如從別的庫搞出來的數據,在這裏搞進去,但是兩個庫字符集不匹配,那就變亂碼了)

數據庫字符集是在數據庫創建的時候就建立好的!舉幾個字符集的例子:Unicode UTF-8,7-bit ASCII,EBCDIC。

 

VARCHAR2 and CHAR Data Types

VARCHAR2數據類型存儲可變長的字符文本(literals),專業屬於literal(文本)和constant value(常量)是同義詞都是指固定不變的數據值。

例如'LILA','St.GeorgeIsland' ,以及'101' 這些全部都是字符文本,而5001是數字文本.

字符文本被涵蓋在兩個單引號裏,這樣數據庫才能知道它們沒有特殊意義。

 

當你你創建的表中有VARCHAR2列,你指定了最大的字符長度。比如Name列 VARCHAR(25),它的意思是任務存儲進這個列的名字可以最大不超過25個字節。

對於每行來說,Oracle存儲的每個在name列的值都是可變長的。除非數據已經到了最大長度。

舉個例子,在一個單字節的字符集中,如果輸入了10個字符進name列,則行保存進數據塊中時值保存10個字符(10 byts) 而不是25。使用VARCHAR2會減少磁盤的消耗。

 

對比起VARCHAR2,CHAR存儲的是 不可變長的字符串。比如輸入了25,你只插入了10,但是還是會按照25保存。其他15用空格填充

 

NCHAR and NVARCHAR2 Data Types

NCHAR 和NVARCHAR2數據類型存的是Unicode字符數據。Unicode是universal encode(通用編碼)字符集,用這個字符集可以存儲任何語言。

NCHAR 特性和CHAR對應,只不過使用的是national(國家)字符集,而NVARCHAR2與VARCHAR2對應。

當你創建數據庫的時候,你也會指定一個nationalcharacter set。國家字符集。這個字符集就是爲 NCHAR ,NVARCHAR2準備的,這字符集要麼是AL16UTF16,要麼是UTF8。這兩個字符集都是使用了Unicode encoding

NCHARNVARCHAR設置長度的時候,只能設置單位是char的。不能設置單位是bytes的

 

Numeric Data Types(數值類型)

oracle數據庫的數值類型是按照可變長模式存儲的。

每個值都是按照科學計數法存儲的,會有一個字節用來存儲指數。

數據庫最多用20個bytes來存儲尾數(小數點後面的),尾數是floating-point(浮點數)的一部分,包含了它顯著的位數。

Oracle數據庫不儲存開頭的0 和結尾的0

 

NUMBER DATA type(數字型)

數字型存儲了固定和浮點類型的數字。數據庫可以存儲幾乎任何大小的數字.在不同的操作系統上運行的Oracle數據庫,數值型的格式是一致的.

如果你必須要存儲數值類型,則NUMBER是最常用,也是最推薦的。

 

NUMBER的格式是NUMBER(p,s),p和s分別指得下列意思:

·Precision(p)(精度)

  precision指的是總共多少位,如果p沒有指定,則這個字段存儲的值和應用提供的完全一樣,沒有任何四捨五入

·Scale(s)(刻度,其實就是指小數位數)

  如果s指定,則等於0.例如

  number(8,2)則總共有8位,其中2位是小數。

Floating-Point Numbers(浮點數)

Oracle數據庫提供了兩種浮點 數據類型:BINARY_FLOAT和BINARY_DOUBLE。

這兩種類型能支持NUMBER類型所支持的所有功能。不過,NUMBER使用的是10進制精度,而BINARY_FLOAT和BINARY_DOUBLE使用的是2進制精度,這種精度使得計算更快,並且通常能減少存儲需求。

BINARY_FLOAT和BINARY_DOUBLE是大概的數值類型,它們存儲了近似的十進制。而不是精確的表示,舉個例子:值0.1是沒辦法通過BINARY_DOUBLE和BINARY_FLOAT精確表示的。

它們經常被用到科學運算。它們的行爲和JAVA中的FLOAT和DOUBLE很相似。

 

Datetime Data Types(時間數據類型)

數據時間的類型有DATE和TIMESTAMP.

Oracle數據庫提供對 時區(time zone)的全面支持

 

DATE data Type(日期型)

DATE類型裏面存了日期 和時間,日期時間 可以用字符或者數字類型來表示,而DATE則是對其進行了特殊的關聯。推薦使用date類型來存放日期時間。

 

在數據庫內部,date存放的格式是數字,date會存成定長的7個字節。分別代表 世紀,年,月,日,小時,分鐘,秒。

DATE類型全面支持算術運算。比如+1就是增加一天加0.5就增加半天。

數據庫顯示時間是根據指定的 formatmodel (格式模版). format model是日期時間按照字符型的樣子來進行表示(但它實際是按照數字存放的)

標準默認的時間格式的DD-MON-RR,顯示出來爲02-JAN-09

RR 和YY很想,都是將年的最後兩位顯示出來,但是它們返回的後兩位,代表的年份可能不是一個世紀的。比如說,在1909年的話,數據庫顯示 01-JAN-09,,如果日期格式用RR,則09代表2009,而如果格式使用YY,則代表1909,你可以改變默認的日期顯示格式在INSTANCE級別和SESSION級別。

Oracle 數據庫存儲時間 格式是HH:MI:SS,如果沒有插入時間部分,則默認顯示是00:00:00 A.M .如果日期部分沒有插入,則默認是當前月的第一天。

 

TIMESTAMP Data Type(時間戳數據類型)

TIMESTAMP數據類型是DATE類型的擴展,除了DATE能夠存儲的信息,它還另外加了秒以下的單位。TIMESTAMP類型對於存儲精確的時間是非常有效的,比如應用必須能夠跟蹤事件一個時間的順序(比如一秒可能出現了很多事件)

TIMESTAMPWITH TIME ZONE和TIMESTAMP WITH LOCAL TIME ZONE是TIMESTAMP其中的兩個類型,都是能夠感應時區的(也就是和時區可以關聯起來).當用戶查詢出這兩種類型的值,則值會根據用戶的時區自動進行調整。

這兩種類型對於跨時區的系統是很有用的

 

Rowid Data Types(Rowid 數據類型)

存在數據庫中的每行,都有自己的一個唯一地址.Oracle數據庫使用ROWID數據類型來存儲這個地址(rowid).

Rowid有以下幾種類型:

·Physical rowids(物理rowid) 這類是被普通表,tablecluster,以及分區所使用。

·Logical rowids(邏輯 rowid) 這類是被index-organizedtables,IOT使用的。

·Foreign rowids(外部 rowid) 這類用來表示外部的表,比如通過網關訪問的DB2的表,它們不是標準的Oracle 數據庫 rowid。

 

Use of Rowids(Rowid的使用)

Oracle數據庫,索引就是基於ROWID的。B-tree索引, 這個是索引最常用的類型,索引是將鍵值按照順序排列,並且分開 放入到一些範圍裏(可用郵編來理解)

每個鍵值都與一個rowid關聯,它指向了相關的行地址,使應用可以通過索引快速訪問。

終端用戶和應用開發同樣可以在一些重要的功能上 使用rowid

·Rowid是訪問指定行最快的方式

·Rowid 在一個給定的表中,是絕對的唯一標識

你可以創建一個表,列用ROWID數據類型 。例如:你可以定義一個有rowid類型列的 意外表,用來存一些違犯了完整性約束 行的rowid。

列用rowid類型,表現和其他表的列是一樣的:列可以被更新等。

 

ROWID Pseudocolumn (ROWID 虛列)

Oracle數據庫中的每個表都有 虛列,名叫ROWID. 一個序列的表現像是表的列,但是它並不真實儲存在表中。你可以select 序列,但是你不能insert update 或者delete它們的值。一個虛列類似一個沒有參數的功能函數。一個沒有參數的函數通常會返回一個相同的值,但是虛列通常對於每行都會返回一個不同的值。

下面是一個例子:查詢empolyee_id等於100的rowid

SQL>SELECTROWID FROM employees WHERE employee_id=100;

ROWID

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

AAAPecAAFAAAABSAAA

 

Format Models and Data Types (格式化模型和數據類型)

formatmodel是字符文字描述存儲在一個字符類型中的datetime或數值類型。

formatmodel並不真正改變值在數據庫中的表現。

 

當你將一個字符值轉換成日期或者數字的時候,formatmodel決定了數據庫該怎樣翻譯。

SQL中你可以使用formatmodel作爲TO_CHAR和TO_DATE函數的參數。用來格式化從數據庫中讀出的值,或者將值格式化後存入數據庫。

 

下面的語句查詢了 部門80的僱員們的工資,並且將查出來的工資使用to_char格式化成字符串形式,format model爲 '$99,990.99'

SQL>SELECT last_name employee,TO_CHAR(salary,'$99,990.99')

     FROM employees

     WHERE department_id=80 ANDlast_name='Russell';

EMPLOYEE   TO_CHAR(SAL

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

Russell       $14,000.00

 

而下面的例子則是 更新 hire_date 。通過使用TO_DATE,將字符串'1998 0520'格式化成了時間格式

SQL>UPDATE employees

     SET hire_date = TO_DATE('1998 05 20','YYYYMM DD')

     WHERE last_name = 'Hunold';

 

Integrity Constraints(完整性約束)

表中一列或多列中對於插入值的限制規則,就是完整性約束.這些規則防止不合法的數據條目插入到表.同事完整性約束也可以防止表中數據刪除,當一些依賴性存在時(外鍵)

 

當約束enabled時,則數據庫會檢查數據.如果數據不符合要求,是不會讓它進入的.

當約束disabled時,數據不符合要求,但是也是可以進入的

 

在之前的例子例子中  CREATE  TABLE 語句指定了 NOT NULL 約束在一些列,比如last_name,email,hire_date等。

createtable中的constranit子句標明瞭段名,以及約束條件.

這個NOT NULL約束保證了指定列中不能有null值,也就是不能爲空。

 

約束除了在創建表的時候可以弄,也可以在表創建完以後建立

約束也可以根據需要臨時disabled(禁用)掉。

 

Object Tables(根據object type創建的表,就叫objecttable)

Oracleobject type。

object type定義一個邏輯架構,但是卻不創建segment(段)

舉例說明

CREATETYPE department_type AS OBJECT

   (d_name VARCHAR2(100),

   d_address VARCHAR2(200));

/

當department_type這個objecttable創建好後,可以根據它來創建object table

例如:

CREATETABLE department_obj OF department_type;

這樣一個object table就創建好了,不需要指定列。列和之前object table的完全一樣。

這時候可以直接插入數據了。

insertinto department_obj

     values('hr','10 Main st, Some town, CA');

和普通表一樣,不過object table的每行都有一個邏輯的object identifier(OID),它在一個object table是唯一的。object table的OID列是隱藏列。

 

Temporary Tables(臨時表)

臨時表中數據 保存的週期 只有 transaction(事務)週期和session(會話)週期兩種

臨時表是不共享的。也就是說,每個session看到的一個相同的臨時表,但是數據卻是完全不同的(臨時表中數據是私有的)

臨時表對於應用中比如某些結果集要臨時存一下。這時候是非常有效的。

舉個例子:

選課軟件使的大學生可以創建自己本學期的可選課程計劃。每個計劃 都可以用臨時表中的一行來表示,在整個session(會話)期間,這個計劃的數據都是私有的。當學生確定了一個上課計劃,在應用會把這行 移到一張 永久表(非臨時就叫永久).在這個session關閉時,這些在臨時表中的計劃數據,將會自動的刪除掉。

 

Temporary Table Creation

CREATEGLOBAL TEMPORARY TABLE語句創建臨時表。ON COMMIT 子句指定表的數據是事務級別(默認)還是session級別。

和其他數據庫並不一樣,當你在Oracle數據庫創建臨時表時,你創建了一個靜態的定義。臨時表是一個永久的對象描述,但是爲空(不分配segment)  直到你的session插入數據到這個表。你創建臨時表是提供給數據庫本身,但並不提供給每個PL/SQL 存儲過程。

 

英文臨時表是靜態的定義,你可以用CREATEINDEX去對它創建索引。創建在臨時表上的索引也是臨時的。你也可以創建視圖和 觸發器 在臨時表上。

 

SegmentAllocation in Temporary Tables(臨時表關於段的分配)

和永久表一樣,臨時表在數據字典中是有定義的。但是臨時段卻是在數據第一次插入到臨時表的時候才分配,在沒有插入數據前,臨時表是不分配段的。當session或者事務結束時(兩個級別)則臨時段會 取消分配。也就是 臨時段用完就又收回了。

 

External Tables(外部表)

外部表的實際數據都在外面。你可以使用SQL,PL/SQL,以及JAVA來查詢外部數據

外部數據對於查詢 平臺文件非常有效,舉個例子吧:一個基於sql的應用可能會從 txt文件中訪問需要的記錄,這些記錄類似如下:

100,Steven,King

101,Neena,Kochhar

102,Lex,DeHaan

你可以創建一個外部表,將文件拷貝到外部表定義好的位置,然後使用sql 從txt文件中查詢條目。

外部表對於ETL(extraction,transformation,loading)任務,這種任務普遍在數據倉庫環境中。舉個例子:外部表使得 數據庫加載過程和轉換過程 合併了。將需要的數據才載入到庫,以便於數據庫進一步處理。

 

External Table Creation(外部表的創建)

對數據庫內部而言,創建一個外部表 其實就是在數據字段中添加一些元數據。和普通表不一樣,一個外部表,並不存儲數據,也不存儲數據描述是怎樣存儲在外部的。外部表的元數據表了

CREATETABLE ... ORGANIZATION EXTERNAL 有兩個部分,

第一個部分,external tabledefinition 描述了段的類型,這個definition(定義)像一個視圖,它使SQL可以查詢外部數據的時候,不將其再入到庫。

第二個部分表示了外部數據是怎樣和每個列掛鉤的。

外部表是 只讀表。除非創建表用CREATETABLE AS SELECT 以及使用ORACLE_DATAPUMP訪問驅動器。

外部表的限制有1、不支持索引列,2、不支持虛擬列,3、不支持列對象。

 

External Table Access Drivers(外部表訪問驅動器)

accessdriver 是一個API(應用程序接口),它解釋了 database 的外部數據。這個訪問驅動器運行在數據庫內部,它被用來讀外部表中的數據。這個訪問驅動器以及外部表層是相關聯的,用來執行將查詢轉換匹配到外部表中的數據。

下圖解釋了外部數據是怎樣被訪問到的。


Oracle提供兩種訪問驅動.ORACLE_LOADER(默認)和ORACLE_DATAPUMP.

ORACLE_LOADER通過SQL*Loader來只讀的訪問外部表.你用ORACLE_LOADER驅動時不能更新,或者創建,或者追加內容到外部表。

ORACLE_DATAPUMP驅動使你可以unload(卸下)外部數據,

這個操作包括從數據庫中讀取數據,並且插入數據到一個外部表,創建一個或多個外部文件。

 在外部文件創建後,則數據庫不能在更新或者追加數據進去。

這個驅動器同樣可以使你load(加載)外部數據,包括從外部表中讀取,並且加載到數據庫中。

 

Table Storage(表的存儲)

Oracle 數據庫使用 datasegment(段)用來保存表的數據。也被叫做 User Segment.一個segment包含由data blocks(數據塊們)組成的extents(區)

 

表對應的段,默認是在用戶自己的默認表空間中,如果create table的時候指定了則,則存儲指定表空間(你要有權限往裏寫)

 

Table Organization(表的組織結構)

默認情況下,表的組織結構是 heap(堆),它的意思是數據庫存放行的時候,怎麼存快就怎麼存,而不是按照一個用戶特別指定的順序。(堆表就是隨便堆在那)。因此,heap(堆)組織表是中的行是無序存放的. 用戶添加行,數據庫則將行存放在段中的第一個可用位置.

當行被查詢時,並不保證是它當時插入的順序.

hr.departments表就是一個堆表,它的列表述的內容有 department ID,name,manager ID,以及location ID。當行插入的時候,數據庫存放他們時,哪裏有空就存在哪。

一個在表segment的數據庫。可能存放着一堆無序的行,如下面這個樣子


在一個表中,所有行的 列的順序都是一樣的,數據庫通常存放列的方向是這個表創建時候指定的方向。但是,這裏說的是通常,但並不是絕對。舉個例子:如果一個表有一個列的類型是LONG,則Oracle數據庫永遠把這列的值存在最後。同樣如果你添加一個新列進一個表,則這個新列成爲最後一個列。

表可以包含virtual column(虛列),它不像普通的列,它並不消耗磁盤空間。當用戶根據指定的表達式或者函數要計算一個返回集,並且裏面有用到虛列,則數據庫會將虛列派生出來(也就是當時纔開始產生,返回完又沒了)

你可以對它進行索引(注意 虛列和pseudocolumn是有區別的),收集它們的統計信息,以及創建完整性約束,因此,virtual 列其實和普通列非常相似

 

Row Storage(行的存儲)

數據庫存儲行到數據塊中,每個rowpiece只能存最多255列。

Oracle 數據庫會儘可能的把每行數據存爲一個row piece(行片),然後,如果一行的數據一個塊放不下,或者如果一個行發生了更新,導致原本的塊放不下了,則數據庫這時將使用多個row pieces(行片)

tablecluster中的行和普通表中的一樣,此外,table cluster中的行包含的信息中引用了它們使用的cluster key

 

Rowids of Row Pieces(行片的rowid)

rowid是一個佔用了每行10個byte的物理地址。像"RowidData Types"中解釋的一樣,在堆表(普通表)中的每行都有唯一的rowid,它和row piece的物理地址一一對應。

在table cluster中,在不同表的行,它們在相同的數據塊。它們可以有一樣的rowid

 

Oracle 數據庫內部使用rowid來構造索引。舉個例子:在B-tree索引中的每個key都和一個rowid關,它指向了相關行的地址,使索引可以快速訪問數據。

物理rowid是最快訪問到行的方式。使數據庫檢索行在一個I/O就可以搞定。

 

Storage of Null Values(關於NULL值的存儲)

null就是段中沒有值。null表示 丟失,未知 或者不可用數據。

null是會被存儲的,如果它在一堆有值的列的中間。在這種情況下,它們需要用1byte來存儲段的長度(0)

如果行中最後追着一堆NULL,則這些null並不存儲。舉個例子,如果一個表中最後三列是null。在這些columns是不需要存儲的。

 

Basic and OLTP Table Compression

基於字典的表壓縮 ,這種壓縮給普通表提供了很好的壓縮比例.Oracle數據庫支持以下幾種基於字典的表壓縮。

·Basic tablecompression(基本表壓縮)

  這種壓縮類型爲 大塊的加載操作 準備。數據庫不能壓縮使用傳統DML修改的數據,你必須使用directpath load(直接路徑載入),ALTER TABLE ...MOVE操作,或者online table redefinition(在線表重定義)用來實現 基礎表壓縮。

 

·OLTP tablecompression(OLTP表壓縮)

  這種壓縮方式專門爲了OLTP準備,可以在數據還被SQL操作的時候進行壓縮。

對於基本和OLTP 方式的表壓縮,數據庫存儲壓縮後的行 格式是 row-major。一個行的所有段都存儲在一起,後面跟隨的是下一行的所有段,依此類推

而相同的值將被替換爲一個標記表中的一個指針,這個表存在塊的頭部。因此,將塊解壓縮而需要的相關信息已經在塊自身存儲了。

壓縮後的數據塊看起來和正常數據塊很像。絕大多數能夠用在標準數據塊上的數據庫特性和應用,也同樣可以用在壓縮後的數據塊。

 

你可以在表空間,表,分區,子分區級別上申明壓縮。

如果指定在表空間級別,則所有在這個表空間創建的表 默認就是壓縮的。

可以使用下列命令引用 OLTP壓縮到orders表:

ALTERTABLE orders COMPRESS FOR OLTP;

下面這個例子是CREATE TABLE 中對於一個分區指定了OLTP壓縮,而其他分區則是基礎壓縮:

CREATETABLE sales(

       prod_id NUMBER NOT NULL,

       cust_id NUMBER NOT NULL, ...)

 PCTFREE 5 NOLOGGING NOCOMPRESS

 PARTITION BY RANGE (time_id)

  (partition sales_2008 values lessthan(to_date(...)) COMPRESS BASIC,

   partition sales_2009 values lessthan(MAXVALUE) COMPRESS FOR OLTP);

 

Hybird Columnar Compression(混合列壓縮)

在混合列壓縮中,數據庫將一組行的相同列值存在一起.

數據塊不將數據存儲爲row-major格式,使用了一個行和列組合起來的一種方法.       

把段的數據存在一起,根據相同的數據類型和相似的特點,通過極大的增強存儲的使用來實現壓縮的目的。壓縮後的數據可以被任何SQL操作。雖然壓縮級別其實比直接路徑加載更高。數據庫操作對於壓縮對象是透明的,所以無需修改應用程序。

 

Types of Hybrid Columnar Compression(混合列壓縮的類型)

如果你底層的存儲支持混合列壓縮,則你可以指定下列壓縮類型,根據你的需要:

·WareHouseCompression(倉庫壓縮)

  這種壓縮類型是對於存儲空間的優化,它爲了數據倉庫類型準備

·Online archivalcompression(在線歸檔壓縮)

  這種壓縮方式是最高的壓縮級別,它專門爲了歷史數據,不會發生變化的數據準備。

爲了完成Warehouse oronline archival 壓縮。你必須使用直接路徑加載。ALTER TABLE ...MOVE操作,或者表在線重定義。

混合列壓縮是用來優化數據倉庫和Exadata存儲的決策支持系統。在Exadata中查詢使用了混合列壓縮的表,性能最好,Exadata存儲服務器是利用強大的處理能力,內存,以及Infiniband網絡組成的。

  其他oracle存儲系統也支持混合列壓縮,而且提供和Exadata相同的空間使用,但是它不提供相同的查詢性能。在這些存儲系統中,混合列壓縮用不經常訪問的,老的歸檔數據是合理的。

 

CompressionUnits(壓縮單元)

混合列壓縮使用了一種邏輯結構叫compressionunit(壓縮單元),它用來存儲一組行。當你將數據加載到表中時,則數據庫將一組行存儲成列模式,每列的值都存儲和壓縮在一起。

在數據庫把一堆行的列數據都壓縮後,數據庫以後將從compression unit中獲取數據。

舉個例子:

你對daily_sales表執行了混合列壓縮.在每天結束時,你得把銷售的物品和數量填充進來.

有物品ID和date 形成組合主鍵,下表顯示daily_sales中的一個子集


假設上表的行都存在一個壓縮單元中。混合列壓縮將把每個段的值存儲在一起,而且使用多重算法去壓縮每列。數據庫選擇算法是基於多種因素影響,包括段的數據類型,段中值的基數以及用戶選擇的壓縮級別。

 

像下圖顯示,每個壓縮單元可以跨過多個塊。而特定列的值可能跨過,也可能沒跨過多塊。


混合列壓縮會產生row鎖(Rowlocks(tx))。當一個update發生在一個未壓縮塊中的行,只有這行被鎖。與之不同的是,如果一個update發生在一個壓縮單元中的行,則整個壓縮單元中的所有行都會被lock。更新使用了混合列壓縮rows的rowids的改變。

  注意:

  當表使用了混合列壓縮,Oracle DML操作時會鎖住 壓縮單元(一大堆數據塊),這樣會降低併發

 

 

Overview of Table Clusters (TableCluster的概述)

Tablecluster 是一組表,這組表共享一些共有的列,並把相關的數據存儲到相同的塊.當表是clustered(集羣化的),一個數據塊可以包含多個表的行。

舉個例子.一個塊可以存放employees和departments表中的行,而不是隻能存儲一個表中的行。

clusterkey 是指集羣化的表中的公共列。舉個例子,employees和departments表分享department_id列.

你要在創建table cluster(表集羣)和每個附加在tablecluster上的表時,要指定cluster key

clusterkey value 是指cluster key 列中的值。

所有包含cluster key value(比如department_id=20),都是物理存儲在一起的。每個cluster key value在一個table cluster中只存儲一次。無論有多少不同表都用了這個列。

打個比方,假設人事經理有兩個書架:一個放着僱員信息文件的盒子,另一個放着裝有部門文件的盒子.用戶經常需要找一些特定部門的僱員信息。爲了讓檢索更簡單,這個經理把所有的盒子都放到一個書架。她把盒子根據部門ID分開,因此所有在部門20的僱員信息,以及部門20本身自己的信息都放入了一個盒子。而部門100的僱員信息和部門100自身的信息放入一個不同的盒子,以此類推

 

當表經常被查詢(不經常修改),而且表頻繁用join方式查詢,這時候可以考慮用tablecluster而把表集羣化起來(共享某些列)。因爲table cluster可以存儲不同表的相關列在一個數據塊,

恰當的使用table cluster有下列優勢(對比非集羣化的表):

·集羣化後的表(附加在tablecluster上的表)join的時候,磁盤I/O會減少。

·集羣化後的表 join的時候,訪問時間會有改善

·存儲的使用會減少。因爲clusterkey value 只存一次。N多表都可以用。

下列情況,使用cluster tables不合適:

·表經常被更新

·表經常需要 全表掃描

·表會被 truncate命令操作。

 

Indexes Clusters 概述

Indexedcluster是table cluster使用的索引。cluster index是在cluster key上的B*tree索引。一個cluster index必須在cluster key中沒有數據的時候創建。

 

假設你創建了table cluster :employees_departments_cluster,cluster key是department_id,像下面語句顯示,因爲HASHKEYS子句沒指定,則這個cluster是一個indexedcluster。之後你創建了一個名叫idx_emp_dept_cluster的索引在這個cluster key上。

CREATECLUSTER employees_departments_cluster

  (department_id NUMBER(4))

SIZE512;

CREATEINDEX idx_emp_dept_cluster ON CLUSTER employees_departments_cluster;

然後你創建employees和departments表到這個cluster中。指定department_id列爲clusterkey.如下(省略號標記的位置是設置列的位置)

CREATETABLE employees(...)

         CLUSTERemployees_departments_cluster(department_id);

CREATETABLE departments(...)

         CLUSTERemployees_departments_cluster(department_id);

最後,你插入行到employees和departments。employees和departments表上,department_id相同的數據,會被物理的存儲在一個塊裏。存儲的格式是heap。訪問它們通過index。

下圖顯示了employees_departments_clusterTABLE CLUSTER。它包含了employees和departments表。數據庫將department20的僱員信息行存儲在一起,department110的僱員信息行存儲在一起,以此類推。

如果表沒有集羣化(notclustered,也就是普通表)數據庫不保證相關的行會存儲在一起。

 


B-treecluster index根據包含cluster key value的塊的DBA(數據庫塊地址)進行關聯。

舉個例子:一個索引條目顯示的數據塊地址,這個數據塊地址包含了department20的僱員信息。

20,AADAAAA9d

clusterindex是分開管理的。就像非clusterd表(普通表),它可以存入到一個與table cluster所在表空間不同的表空間

 

Overview of Hash Clusers 哈希cluster概述

hashcluster很像indexed cluster,除了將index key 替換爲 hash function. 沒有單獨的cluster index..

在hash cluster中,數據本身就是index(索引)

在有索引的表 或者 indexedcluster,Oracle數據庫通過存在索引中的key value來定位行.

爲了找到存在表中的行,數據庫最小都需要兩個I/O

·一個(或更多)I/O用來找到索引中的keyvalue

·另外一個I/O用來讀or寫 表中或table cluster 中的行

 

在hash cluster中讀取或寫入一行,Oracle數據庫 對 行的cluster key value 執行 hashfunction ,返回的hash值會對應到cluster中的一個數據塊,這個塊就是語句要讀或着寫的。

 

增強數據的檢索能力,hash是一種選擇。

Hashclusters在下列情況是有益處的

·這個表DML頻繁

·hash key列經常在條件中用=號。例如 wheredepartment_id=20.像這種查詢,cluster key values是hash的,這個hash key value 直接指向磁盤中存儲這行的區域。

·你可以有根據的猜測 hash key的數量,以及每個 keyvalue存儲了多少數據

 

HASH Cluster Creation  創建HASHCluster

hashcluster 的cluster key。和indexed cluster的cluster可以很像。

是一個段或者多個段。被cluster中的表所共享使用的。

hash keyvalues就是插入到cluster key column中的值

例如:如果cluster key 是department_id。則hash keyvalues 可能就是10,20,30以此類推

 

Oracle數據庫使用hashfunction(函數),插入無數的 hash key values,分類它們然後插入到有數的buckets(桶)中。每個bucket都有一個唯一的數字ID,叫 hash value。

每個hash value 都是一張地圖,上面記錄了hashkey value對應行儲存的塊的地址。

 

使用CREATE CLUSTER語句創建hash cluster,附加一個hash key。hash values的數 取決於hash key。下面例子中,可能存在的部門數量爲100個,所以 HASHKEYS 設置成100.

CREATECLUSTER employees_departments_cluster

(department_idNUMBER(4))

SIZE8192 HASHKEYS 100;

在創建employees_departments_cluster後,你可以創建employees和departments表到這個cluster中。你可以將數據加載進去。創建表的過程和 indexed cluster一模一樣。

 

Hash Cluster Queries(hashcluster的查詢)

數據庫自己決定怎樣把用戶插入的keyvalue HASH掉(哈希),而不是某個用戶來決定。

舉例:假設用戶頻繁的執行像下面這樣的查詢。輸入不同的department ID到p_id

SELECT *

FROMemployees

WHEREdepartment_id =:p_id;

 

SELECT *

FROMemployees

WHERE department_id=:p_id;

 

SELECT *

FROMemployees e,departments d

WHEREe.department_id = d.department_id

ANDd.department_id = :p_id;

如果用戶查詢在department_id等於20的僱員,則數據庫會hash這個值(20)到bucket 77.

如果用戶查詢在department_id等於10的僱員,則數據庫會hash這個值(10)到bucket 15.

數據庫根據要查詢的部門IP 使用內部產生hashvalue去定位包含empolyee行的塊。

下圖描述了一個hash cluster 段 是一堆水平的塊,像顯示的那樣 ,查詢可以一個I/O就檢索到數據



hashclusters的限制是,如果cluster key沒有進行索引,就無法進行 index range scan。假設它沒有單獨對hash cluster創建一個索引。而一個查詢要查部門20到100,就必須進行全表掃描,而不能進行index range scan。因爲hash算法沒辦法hash 20 到100之前的所有值(20-100之間有無數個值)。

 

Hash Cluster Variations (Hash Cluster 的變種)

單表hash cluster是最優化的hash cluster,它在同一時間只支持一個表存在。這時候hash key和row存在一一映射關係。

一個單表hash cluster 可以有效的用於用戶通過主鍵快速查詢這個單表。

舉個例子:用戶經常通過empolyees表中的empolyees_id主鍵來查找數據。

 

有序的hash cluster存儲的行將根據hash key排序好,這樣數據庫就可以按照排序的順序返回每個值對應的行。

數據庫將在內部執行最優的排序.對於應用來說,它們總是消耗資源在數據庫的排序上.這個技術可能意味着更快的查詢數據.

舉個例子:

一個應用可能總是根據orders表的order_date列進行排序.

 

Hash Cluster Storage(Hash cluster的存儲)

 Oracle數據庫分配hashcluster的空間,不同於indexed cluster


上面例子中,HASHKEYS指定了可能會存在的部門,而SIZE指定了每個部門的各自數據大小。

數據庫基於下面的值計算出存儲空間的大小:

HASHKEYS* SIZE /database_block_size

因此,如果上面例子中塊大小是4K,那麼數據庫給hashcluster最少分配200個塊.

Oracle 數據庫並不限制你可以插入的hashkey values的數量。

舉個例子:儘管 HASHKEYS是100..但是你可以是可以插入200個不同的部門到departments表.不過,如果hash values的值超過了HASHKEYS,則檢索速度會受到影響.

圖解說明一下檢索的的問題,在下圖中假設塊100存滿了department20的行。一個用戶插入一個department_id是43的新部門。部門的數量超過了HASHKEYS的值。那麼數據庫將把部門43 hash爲77,而77和部門20hash的值一樣。

將不同的值hash成相同的值,有個術語叫哈希衝突。

當用戶插入部門43的相關行,則數據庫不能存儲這些行到塊100(已經放滿了部門20的數據)。數據庫將發生overflow,連接一個新塊到塊100,這個新塊叫塊200,並將數據插入到這個塊。這時候塊100和200將存儲兩個部門中的值。像下圖顯示的,一次查詢,無論查詢20還是43,現在都需要兩個I/O纔可以返回數據。塊100和塊200進行了關聯。你可以通過重新創建一個新的cluster,增加HASHKEYS值來解決這個問題。



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

勤學如春起之苗,不見其增日有所長。輟學如磨刀之石,不見其損日有所虧

 

Email:    orahank.dai@gmail.com

QQ:       88285879



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章