Oracle 9i學習日誌(15)-- 表的管理

幾種存儲用戶數據的方法:Regular table(table)、partitioned table、Index-organized table、clustered tables。
Regular tables通常稱爲表或堆表,管理員很難控制表中行的存儲位置。插入行時,只要表中有合適的空間就將行放置在哪。
Clustered table:將一些相關的表通過一個cluster key關聯在一起,在物理上儲存在一塊。這些表物理上可能共享一列,但邏輯上是分開的。
Oracle內置數據類型: 
標量數據類型:
字符數據:字符數據可以作爲長度固定或長度可變的字符串存儲在數據庫中。長度固定 的字符數據類型(如CHAR 和NCHAR)存儲時帶有填補空格。NCHAR 是“全球化支持” 包含的一種數據類型,既可以存儲寬度固定字符集,也可以存儲寬度可變字符集。其最大大小取決於存儲一個字符所需要的字節數,上限爲每行2,000 個字節。缺省值爲1 個字符或1 個字節,具體取決於字符集。
長度可變的字符數據類型僅使用存儲實際列值所需要的字節數,並且每行的大小可以不同,最大可達4,000 字節。VARCHAR2 和NVARCHAR2 就是長度可變的字符數據類型的例子。
Varchar與varchar2的區別: 
數字數據類型:Oracle 數據庫中的數字始終以長度可變的數據存儲。最多可以存儲38 個有效數位。數字數據類型需要:
• 指數用1 個字節
• 尾數中的每兩個有效數位用1 個字節
• 負數用1 個字節(如果有效數位少於38 個字節)
DATE 數據類型:Oracle 服務器將日期存儲在包含七個字節的固定長度字段中。Oracle DATE 始終包括時間。
TIMESTAMP 數據類型:此數據類型存儲日期和時間,包括零點幾秒,最高可達9 位小數。
TIMESTAMP WITH TIME ZONE 和TIMESTAMP WITH LOCAL TIME ZONE 可以使用時區設定時間,如夏時制。TIMESTAMP 和TIMESTAMP WITH LOCAL TIME ZONE 可用於主鍵,而TIMESTAMP WITH TIME ZONE 則不能。
RAW 數據類型:可以使用此數據類型存儲小型二進制數據。在網絡中的計算機之間傳輸RAW 數據時,或者使用Oracle 實用程序將RAW 數據從一個數據庫移到另一個數據庫時,Oracle 服務器不執行字符集轉換。存儲實際列值所需要的字節數大小隨每行大小而異,最多爲2,000 字節。
LONG、LONG RAW 和大型對象(LOB) 數據類型:
Oracle 爲存儲LOB 提供六種數據類型:
• CLOB 和LONG 用於存儲大型的、寬度固定的字符數據
• NCLOB 用於存儲大型的、寬度固定國家字符集數據
• BLOB 和LONG RAW 用於存儲非結構化數據
• BFILE 用於存儲操作系統文件中的非結構化數據
LONG 和LONG RAW 數據類型以前用於非結構化數據,如二進制圖像、文檔或地理信息,
目前主要用於向後兼容。這兩種數據類型已由LOB 數據類型代替。LOB 數據類型與LONG和LONG RAW 不同,不能互換。LOB 不支持LONG 應用程序編程接口(API),反之亦然。最好與舊的數據類型(LONG 和LONG RAW)相比較來討論LOB 功能。在下文中,LONG指LONG 和LONG RAW 數據類型,而LOB 指所有LOB 數據類型。除非其大小小於VARCHAR2 數據類型的最大大小(4,000 字節),否則,LOB 在表中存儲一個定位器,而將數據存儲在另一位置;LONG 則將所有數據存爲一行。此外,LOB 允許將數據存儲在單獨的段和表空間中,或者存儲在主機文件中。LOB 支持對象類型屬性(NCLOB 除外)和複製;而LONG 不支持。LONG 主要存儲爲一連串的行片段,每一塊中有一個行片段指向存儲在另一塊中的下一行片段。因此,需要按順序訪問這些行片段。相反,LOB 通過類似文件的接口支持以片段方式隨機訪問數據。
ROWID 和UROWID 數據類型:
ROWID 是一種可以和表中其它列一起查詢的數據類型。它具有以下特徵:
• ROWID 是數據庫中每行的唯一標識符。
• ROWID 並不顯式地作爲一個列值存儲。
• 雖然ROWID 並不直接給出一行的物理地址,但它可以用來定位行。
• ROWID 爲訪問表中的行提供了最快的方法。
• ROWID 存儲在索引中來指定具有一組給定的鍵值的行。
在Oracle8.1 版中,Oracle 服務器提供一種稱爲通用ROWID 或UROWID 的數據類型。它支持外表(非Oracle 表)的ROWID,並且可存儲各種類型的ROWID。例如:要存儲按索引組織的表(IOT) 中存儲的行的ROWID,必須使用UROWID 數據類型。要使用UROWID,參數COMPATIBLE 的值必須設置爲Oracle8.1 或更高。
集合數據類型:
有兩種集合數據類型可用來爲表中的一個給定行存儲重複的數據。在Oracle8i 以前,定義和使用集合需要“對象” (Objects) 選項。下面簡要論述這些類型。
變化數組(VARRAY):變化數組對於存儲包含少量組成元素的列表(如客戶的電話號碼)非常有用。
VARRAY 具有以下特徵:
• 數組即一組有序的數據組成元素。
• 一個給定數組的所有組成元素的數據類型相同。
• 每個組成元素都有索引,即與數組中組成元素的位置相對應的編號。
• 數組中組成元素的數目決定了數組的大小。
• Oracle 服務器允許數組的大小可以變化,這就是它們被稱爲VARRAY(意爲變化數組)的原因,但在聲明數組類型時必須指定最大大小。
嵌套表:嵌套表提供一種將一個表定義爲另一個表內一列的方法。嵌套表可用來存儲可能
包含大量記錄的集合(比如一個訂單中的若干條目)。
嵌套表一般具有以下特徵:
• 嵌套表是一組無次序的記錄或行。
• 嵌套表中的各行結構相同。
• 嵌套表中的行與父表分別存儲,並且父表中的對應行有一個指針。
• 嵌套表的存儲特點可由數據庫管理員來定義。
• 嵌套表沒有預先確定的最大大小。
關係數據類型(REF):
關係類型在數據庫內用作指針。使用這些類型需要“對象” (Objects) 選項。這裏給出一個例子:訂購的每一項都可以指向或引用PRODUCTS 表中的一行,而不必存儲產品代碼。
Oracle 用戶定義的數據類型:
Oracle 服務器允許用戶定義抽象的數據類型並在應用程序內使用這些數據類型。
RoweID格式:
Rowid是每一個表都有的一列,在select *查詢時隱藏了。
SQL> select rowid, id, name from test;
 
ROWID                      ID NAME
------------------ ---------- --------------------
AAAHw5AANAAAAAKAAA          0 hello
AAAHw5AANAAAAAKAAB          1 world
AAAHw5AANAAAAAKAAC          3 bbb
AAAHw5AANAAAAAKAAD          2 aaa
AAAHw5AANAAAAAKAAE          3 bbb
Rowie總共佔10bytes存儲空間,採用base64編碼後顯示出來的是18個字符,包括以下組件:
•Data object number:指示每個數據對象,如:表或索引,當這些對象創建時唯一的標示每個對象。
•Relative file number:唯一的確定表空間裏的每個數據文件。
•Block number:指示某一行所在的塊的位置。
•Row number:標識每行,在塊頭中有一個行目錄slot與之對應。
其中object number 佔32bits顯示出6個字符, Relative file number佔10bits顯示出3個字符, Block number 佔22bits顯示出6個字符,Row number佔16bits顯示出3個字符。
行結構:
行是以可變長數據記錄存儲的,通常存儲行是按定義列時的順序存儲的,並且最後一列如果是null則不存儲。對於null列如果不是最後一列則須分配1byte的空間作爲column length。
Row header:記錄行內的列數,鏈接信息和鎖狀態。
Row data:對於每一列第一個byte存儲列長度(如果列長度超過250bytes則用三個bytes存儲長度),緊跟着是列值。行與行之間沒有空閒空間。在表頭上有一個row目錄,其中(的一個slot)指出了每一行的開始。
創建表與改變表:
創建表舉例:
SQL> CREATE TABLE hr.departments(
2 department_id NUMBER(4),
3 department_name VARCHAR2(30),
4 manager_id NUMBER(6),
5 location_id NUMBER(4))
6 STORAGE(INITIAL 200K NEXT 200K
7 PCTINCREASE 0 MINEXTENTS 1 MAXEXTENTS 5)
8 TABLESPACE data;
修改表參數舉例:
ALTER TABLE hr.employees
PCTFREE 30
PCTUSED 50
STORAGE(NEXT 500K
MINEXTENTS 2
MAXEXTENTS 100);
Initial:初始化大小200k。
Next:下一次分配空間200k。
注意:
以上兩個值要跟tablespace的相關參數要對應,如:創建tablespace時指定了extent management local uniform size 128k,則這時創建表時指定的分配空間原則會失效。
Pctincrease:下次分配空間比上次分配的大小增長百分比,例如:pctincrease 10,則第三次分配空間爲220k,第四次爲242k… …
其他參數:
注意:
表的INITIAL 值不能修改。
指定的NEXT 的值將舍入爲塊大小的一個倍數,該值大於或等於指定的值。
說明:
創建表空間原則:
-將各個表分別置於不同表空間。
-使用locally-managed表空間避免碎片(local管理方式會自動將碎片整理)。
-使用小的標準extent大小以減少碎片。
臨時表:
臨時表用來保存僅在事務處理或會話期間存在的會話專用數據。
DML locks are not acquired on the data.
可以在臨時表上創建索引,視圖和觸發器。
創建臨時表:
CREATE GLOBAL TEMPORARY TABLE hr.employees_temp [on commit delete|preserve rows] AS SELECT * FROM hr.employees;
• ON COMMIT DELETE ROWS:事務級別
• ON COMMIT PRESERVE ROWS:會話級別
實驗:
SQL> select * from test;
 
        ID NAME
---------- --------------------
         0 hello
         1 world
         3 bbb
         2 aaa
         3 bbb
 
SQL> create global temporary table sess_temp on commit preserve rows
 2 as select * from test;
 
表已創建。
#如果只是想拷貝表結構而不要數據,則加上 where 1=0.
SQL> select * from sess_temp;
 
        ID NAME
---------- --------------------
         0 hello
         1 world
         3 bbb
         2 aaa
         3 bbb
 
SQL> create global temporary table tran_temp on commit delete rows
 2 as select * from test;
 
表已創建。
 
SQL> select * from tran_temp;
 
未選定行
 
SQL> insert into tran_temp select * from test;
 
已創建5行。
 
SQL> insert into sess_temp select * from test;
 
已創建5行。
 
SQL> select count(*) from sess_temp;
 
 COUNT(*)
----------
        10
 
SQL> select count(*) from tran_temp;
 
 COUNT(*)
----------
         5
 
SQL> commit;
 
提交完成。
 
SQL> select count(*) from tran_temp;
 
 COUNT(*)
----------
         0
 
SQL> select count(*) from sess_temp;
 
 COUNT(*)
----------
        10
 
SQL> quit
重新登錄
SQL> select count(*) from tran_temp;
 
 COUNT(*)
----------
         0
設置pctfree和pctused
行的遷移和鏈接
遷移:
鏈接:
當沒有任何一個block能容納下行時,行被分爲幾小段,每一段稱爲row pieces。Row piece會帶着一個檢索和組合其他piece的指針。
遷移和鏈接會增加I/O操作,降低性能。所以應該儘量避免。可以將更新較頻繁或原來初始值是null以後會更新值的表存儲的segment的pctfree增大。爲了減少行鏈接的發生,應增大塊大小或將表拆分成小表。
手動分配存儲空間:
ALTER TABLE [schema.]table
ALLOCATE EXTENT(SIZE 500K
DATAFILE ‘/DISK3/DATA01.DBF’);
一般用在這兩種情況:
• 控制一個表的區在文件之間的分配
• 在大量加載數據前避免表的動態擴展
如果沒指定size這個參數,則使用next_extent(從dba_tables視圖中可以查到此參數)指定大小。Datafile必須是屬於表所在的表空間。這條命令不影響next_extent這個值。
重組織非分區表
ALTER TABLE hr.employees MOVE TABLESPACE data1;
用於將表移動倒不同的表空間或重新組織extent。這樣可以不必使用導出導入工具,另外,允許重新設置存儲參數。還可以消除行遷移。還有一種方法是創建和舊錶一樣的新表,然後刪除舊錶。Create table table.new as select * from table.old
移動表後必須重建索引,否則會發生錯誤。
Trunncate
TRUNCATE TABLE hr.employees;
TRUNCATE TABLE [schema.] table [{DROP | REUSE} STORAGE]
刪除表中所有行,並且釋放已用空間,但同時索引也被truncate。
執行這條語句不會產生undo,因爲truncate是DDL命令,這條語句是隱式提交的。
如果其他表有應用這個表的外鍵,則這個表不能被truncate。
命令執行時這個表的刪除觸發器不會被觸發。
Drop
DROP TABLE [schema.] table [CASCADE CONSTRAINTS]
刪除一個表後,該表所使用的區將得以釋放。如果這些區是相鄰的,則可以在以後某個時間自動或手動將它們合併。
如果該表是外鍵關係中的父表,就必須使用CASCADE CONSTRAINTS 選項
Drop 列:
可以使用Oracle 服務器從表的行中刪除列。刪除列可清除未使用但可能佔用大量空間的列,而不必導出或導入數據及重新創建索引和約束。刪除一列可能要用相當長的時間,因爲該列的所有數據都將從表中刪除。
在Oracle8i 以前的發行版中,無法刪除表中的列。
刪除列時使用檢查點:
ALTER TABLE hr.employees DROP COLUMN comments CASCADE CONSTRAINTS CHECKPOINT 1000;
刪除列可能需要很長時間,並且且需要大量的還原空間。從大型表中刪除列時,可以指 定檢查點來儘量減少還原空間的使用。在上例中,每1,000 行出現一個檢查點。在操作運行完成前,該表一直被標記爲INVALID。如果操作過程中例程失敗,則該表在啓動後仍將處於INVALID 狀態,因此該操作必須完成。使用下面的語句可恢復中斷的刪除操作:
SQL> ALTER TABLE hr.employees DROP COLUMNS CONTINUE;
如果表處於VALID 狀態,則使用此語句將生成錯誤。
增加一列:SQL> alter table t add num integer;
改變一列的字段類型:SQL> alter table t modify name varchar2(10);
重命名列:
ALTER TABLE hr.employees RENAME COLUMN hire_date TO start_date;
Oracle 9i Database Release 2後的版本中提供了爲關係表重命名列的功能,但不能重命名帶index的表。如果要重命名這種表必須先刪除索引。列被重命名後,功能性索引和check約束依然有效,但在表上的視圖,觸發器,domain indexes,函數,procedures packages將失效。
Renaming is allowed for tables with materialized views and tables involved in replication. If errors in the materialized views occur subsequently, you must modify the materialized views to work out the issues. The syntax is:
SQL> ALTER TABLE [schema.]table_name
2 RENAME COLUMN old_column_name
3 TO new_column_name;
使用UNUSED 選項
• 將列標記爲未使用:
ALTER TABLE hr.employees SET UNUSED COLUMN comments CASCADE CONSTRAINTS;
• 刪除未使用的列:
ALTER TABLE hr.employees DROP UNUSED COLUMNS CHECKPOINT 1000;
• 繼續執行刪除列操作:
ALTER TABLE hr.employees DROP COLUMNS CONTINUE CHECKPOINT 1000;
除將列從表中刪除以外,還可以先將列標記爲“未使用”,以後再刪除。因爲沒有刪除 數據,所以此操作不回收磁盤空間,因而具有速度比較快的優點。被標爲“未使用” 的列可在以後系統活動較少時從表中刪除。未使用的列就像不屬於表一樣。查詢時看不到未使用列中的數據。此外,在執行DESCRIBE 命令時,也不會顯示這些列的名稱和數據類型。用戶可以添加與未使用的列同名的新列。如果想刪除同一表中的兩列,則可先將列設置爲“未使用” 然後再刪除。在刪除兩列時,表中的所有行都會更新兩次;但如果將這些列設置爲“未使用” 然後再刪除,則所有的行僅更新一次。
確定包含未使用列的表要確定包含未使用列的表,可以查詢視圖DBA_UNUSED_COL_TABS。該查詢可獲取包含未使用列的表的名稱及表中標記爲未使用列的數目。下面的查詢顯示HR 擁有的表EMPLOYEES 含有一個未使用的列:
SQL > SELECT * FROM dba_unused_col_tabs;
OWNER TABLE_NAME COUNT
----- -------------- ------
HR EMPLOYEES 1
要確定已完成一部分DROP COLUMN 操作的表,可查詢DBA_PARTIAL_DROP_TABS視圖。
SQL > SELECT * FROM dba_partial_drop_tabs;
OWNER TABLE_NAME COUNT
----- -------------- ------
no rows selected
刪除列的限制
不能執行下列操作:
• 從對象類型表中刪除列
• 從嵌套表中刪除列
• 刪除一個表中的所有列
• 刪除分區鍵列
• 從SYS 擁有的表中刪除列
• 從按索引組織的表中刪除主鍵列
• 如果有未使用但未刪除的LONG 或LONG RAW 列,將無法向表中添加LONG 或LONG RAW 列。(即使表的說明顯示沒有LONG 或LONG RAW 列也是如此。)
實驗:
SQL> desc mm
 名稱                                      是否爲空? 類型
 ----------------------------------------- -------- ----------------------
 
 NUM                                                NUMBER(38)
 NAME                                               CHAR(10)
 STORE                                              CHAR(20)
 
SQL> alter table mm set unused column store cascade constraints;
 
表已更改。
 
SQL> desc mm
 名稱                                      是否爲空? 類型
 ----------------------------------------- -------- ----------------------
 
 NUM                                                NUMBER(38)
 NAME                                               CHAR(10)
 
SQL> select * from user_unused_col_tabs;
 
TABLE_NAME                                                        COUNT
------------------------------------------------------------ ----------
MM                                                                    1
 
SQL> alter table mm drop unused columns checkpoint 1000;
 
表已更改。
 
SQL> select * from user_unused_col_tabs;
 
未選定行
 
SQL> desc mm
 名稱                                      是否爲空? 類型
 ----------------------------------------- -------- ----------------------
 
 NUM                                                NUMBER(38)
 NAME                                               CHAR(10)
獲取信息:
DBA_TABLES
DBA_OBJECTS
 
1 Create the following tables as user SYSTEM for an order entry system that you are implementing now. The tables and the columns are shown below.
Note: When using OEM be sure to set DATE_OF_DELY to NULL.
In addition, you have been informed that in the table ORDERS, rows will be inserted without a value for DATE_OF_DELY, and it will be updated when the order is fulfilled. Use tablespace USERS. You can use the default storage settings.
2 Run the lab11_02.sql script to insert rows into the tables.
3 Find which files and blocks contain the rows for the ORDERS table.
Hint: Query the DBA_EXTENTS data dictionary view.
解析:
SQL> select segment_name,file_id,blocks,block_id from dba_extents
 2 where segment_name='ORDERS' and owner='SYSTEM';
 
SEGMENT_NAME            FILE_ID     BLOCKS   BLOCK_ID
-------------------- ---------- ---------- ----------
ORDERS                        1          8      47537
 
SQL> SELECT FILE_NAME,TABLESPACE_NAME FROM DBA_DATA_FILES
 2 WHERE FILE_ID=1;
 
FILE_NAME                                                 TABLESPACE_NAME
----------------------------------------- -------------------------------------
/u01/oradata/lty/system01.dbf                    SYSTEM
 
4 Check the number of extents used by the ORDERS table.
5 Allocate an extent manually, with default size, for the ORDERS table and confirm that the extent has been added as specified.
解析:
SQL> alter table orders allocate extent(datafile '/u01/oradata/lty/system01.dbf');
 
Table altered.
 
SQL> select segment_name,file_id,blocks,block_id from dba_extents
 2   where segment_name='ORDERS' and owner='SYSTEM';
 
SEGMENT_NAME            FILE_ID     BLOCKS   BLOCK_ID
-------------------- ---------- ---------- ----------
ORDERS                        1          8      47537
ORDERS                        1          8      47545
 
6 Create another table, ORDERS2 as a copy of the ORDERS table in the USERS tablespace, with MINEXTENTS equal to 10. Verify that the table has been created with the specified number of extents.
7 Truncate the ORDERS table without releasing space and check the number of extents to verify that extents have not been deallocated.
8 Truncate the ORDERS2 table, releasing space. How many extents does the table have now?
解析:
SQL> truncate table orders reuse storage;
Table truncated.
SQL> select segment_name,file_id,blocks,block_id from dba_extents
 2 where segment_name='ORDERS' and owner='SYSTEM';
 
SEGMENT_NAME            FILE_ID     BLOCKS   BLOCK_ID
-------------------- ---------- ---------- ----------
ORDERS                        1          8      47537
ORDERS                        1          8      47545
 
SQL> truncate table orders ;
 
Table truncated.
 
SQL> select segment_name,file_id,blocks,block_id from dba_extents
 2 where segment_name='ORDERS' and owner='SYSTEM';
 
SEGMENT_NAME            FILE_ID     BLOCKS   BLOCK_ID
-------------------- ---------- ---------- ----------
ORDERS                        1          8      47537
 
9 Run the lab11_09.sql script to insert some rows into the ORDERS2 table.
10 View the columns for the ORDERS2 table. Then mark the DATE_OF_DELY column as UNUSED. View the columns for the ORDERS2 table again. What happens?
解析:
SQL> alter table orders2 set unused column date_of_dely;  
 
Table altered.
 
SQL> desc orders2;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ORD_ID                                             NUMBER(3)
 ORD_DATE                                           DATE
 CUST_CODE                                          VARCHAR2(3)
 
SQL> select * from dba_unused_col_tabs;
 
OWNER                TABLE_NAME                          COUNT
-------------------- ------------------------------ ----------
SYSTEM               ORDERS2                                 1
 
SQL> alter table orders2 drop unused columns checkpoint 1000;
 
Table altered.
 
SQL> select * from dba_unused_col_tabs;
 
no rows selected
 
11 Drop the unused column DATE_OF_DELY.
12 Drop the ORDERS2 table.
本文出自 “冰冷的太陽” 博客,請務必保留此出處http://luotaoyang.blog.51cto.com/545649/291181
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章