外部表介紹html
ORACLE外部表用來存取數據庫之外的文本文件(Text File)或ORACLE專屬格式文件。所以,創建外部表時不會產生段、區、數據塊等存儲結構,只有與表相關的定義放在數據字典中。外部表,顧名思義,存儲在數據庫外面的表。當存取時才能從ORACLE專屬格式文件中取得數據,外部表僅供查詢,不能對外部表的內容進行修改(INSERT、UPDATE、DELETE操做)。不能對外部表創建索引。由於建立索引就意味着要存在對應的索引記錄。而外部表其實在沒有存儲在數據庫中。故在外部是沒法創建索引的。若是硬要創建的話,則系統會提示「操做在外部組織表上不受支持」的錯誤提示。數據庫
Notice: 外部表是ORACLE 9i後引入的。編程
外部表特徵安全
(1) 位於文件系統之中(必定要在數據庫服務器中,而不是其它網絡路徑),按必定格式分割,服務器
例如@#$等,文本文件或者其餘類型的文件能夠做爲外部表。網絡
(2) 對外部表的訪問能夠經過SQL語句來完成,而不須要先將外部表中的數據裝載進數據庫中。oracle
(3) 外部數據表都是隻讀的,所以在外部表不可以執行DML操做,也不能建立索引。app
(4) ANALYZE語句不支持採集外部表的統計數據,應該使用DMBS_STATS包來採集外部表的統計數據。測試
(5) 能夠查詢操做和鏈接。也能夠並行操做。this
(6) 數據在數據庫的外部組織,是操做系統文件。
(7) 操做系統文件在數據庫中的標誌是經過一個邏輯目錄來映射的。
外部表範例:
1:建立目錄對象並受權
從9i開始,ORACLE數據庫若須要存取文件系統,就必須使用目錄對象,以相對路徑方式存取文件,強化數據庫的安全性。創建目錄對象、授予權限。
SQL>CREATE OR REPLACE DIRECTORY DUMP_DIR AS '/oradata/exterltab';
給用戶授予指定目錄的操做權限
SQL>GRANT READ,WRITE ON DIRECTORY DUMP_DIR TO ETL;
2:建立外部表
我建立了一個平面文件做爲測試用例,以下所示,總共5條記錄,其中一條錯誤記錄
[oracle@DB-Server exterltab]$ more student.data
10001@#$kerry@#$male@#$28@#$1
10002@#$jimmy@#$male@#$22@#$1
10003@#$ken@#$male@#$21@#$1
10004@#$merry@#$femal@#$20@#$1
this is a bad file
CREATE TABLE EXTER_TEST
(
ID NUMBER(5) ,
NAME VARCHAR(12) ,
SEX VARCHAR(8) ,
AGE NUMBER(3) ,
GRADE NUMBER(1)
) ORGANIZATION EXTERNAL
(
type oracle_loader
default directory dump_dir
access parameters
(
records delimited by newline
fields terminated by '@#$'
)
location ('student.data')
);
外部表語法也是蠻複雜的,參數選項很是多,這裏不作過多解釋。有興趣天然能夠翻閱官方文檔。
SQL> select * from exter_test;
select * from exter_test
*
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEFETCH callout
ORA-30653: reject limit reached
ORA-06512: at "SYS.ORACLE_LOADER", line 52
出現下面錯誤,是由於student.data文件中有不符合規範的記錄,能夠刪除「this is a bad file」這一條記錄,可是這是爲了測試下面狀況,因此能夠經過執行 alter table exter_test reject limit unlimited;跳過一些限制。
SQL> alter table exter_test reject limit unlimited;
Table altered.
SQL> select * from exter_test;
ID NAME SEX AGE GRADE
---------- ------------ -------- ---------- ----------
10001 kerry male 28 1
10002 jimmy male 22 1
10003 ken male 21 1
10004 merry femal 20 1
SQL>
此時去查看/oradata/exterltab,你會發現自動生成了EXTER_TEST_8907.bad 和 EXTER_TEST_8907.log兩個文件,其中log記錄訪問外部表的記錄信息,bad文件記錄錯誤記錄的信息。大致以下所示
[oracle@DB-Server exterltab]$ ls
EXTER_TEST_8907.bad EXTER_TEST_8907.log student.data
[oracle@DB-Server exterltab]$
3:查看外部表的目錄
xxx_external_locations 能夠知道當前全部的目錄對象以及相關的外部表,還會查詢出這些外部表所對應的操做系統文件的名字。
select * from all_external_locations;
select * from user_external_locations;
select * from dba_external_locations;
SQL> show user
USER is "SYS"
SQL> col owner for a20
SQL> col table_name for a30
SQL> col location for a30
SQL> col directory_owner for a3;
SQL> col directory_name for a30;
SQL> select * from dba_external_locations;
OWNER TABLE_NAME LOCATION DIR DIRECTORY_NAME
--------- -------------------------- --------------- ---------------------------
SH SALES_TRANSACTIONS_EXT sale1v3.dat SYS DATA_FILE_DIR
ETL EXTER_TEST student.data SYS DUMP_DIR
4:查看外部表的詳細信息
select * from user_external_tables;
select * from all_external_tables;
select * from dba_external_tables;
SQL> desc dba_external_tables;
Name Null? Type
----------------------------------------- -------- ----------------------------
OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
TYPE_OWNER CHAR(3)
TYPE_NAME NOT NULL VARCHAR2(30)
DEFAULT_DIRECTORY_OWNER CHAR(3)
DEFAULT_DIRECTORY_NAME NOT NULL VARCHAR2(30)
REJECT_LIMIT VARCHAR2(40)
ACCESS_TYPE VARCHAR2(7)
ACCESS_PARAMETERS VARCHAR2(4000)
PROPERTY VARCHAR2(10)
5:刪除外部表
刪除外部表SQL語法跟普通表同樣,可是不一樣之處在於有可能還要刪除與之對應的目錄對象。當外部表不用時,須要及時刪除外部表或者與之對應的目錄對象。不過在刪除這些內容時會有一些限制。這些限制主要是管理上的限制,而不是技術上的限制。也就是說,Oracle數據庫系統沒有對其進行強制的限制。可是若是數據庫管理員不遵照這些限制的話,可能會出現一些問題。如要先刪除外部表,而後再刪除目錄對象。有時候一個目錄對象中可能會包含多個外部表。此時必需要確認全部的外部表都不用了,都已經刪除乾淨了,而後纔可以刪除目錄對象。在建立外部表時,操做系統會判斷一下,與之對應的目錄對象是否已經建立。可是在刪除對象時,系統不會去判斷跟這個目錄對象關聯的外部表是否已經所有刪除。若是目錄對象刪除了,可是還有外部表存在。此時查詢這個外部表的時候,系統就會提示「對象不存在」的錯誤信息。因此這個刪除目錄對象時,數據庫系統缺少一種檢查,此 時只有數據庫管理員在刪除目錄對象時,先手工確認一下這個目錄對象是否存在其餘的外部表。
外部表限制:
1. 只能對錶進行SELECT,不能進行DELETE、UPDATE、INSERT這些DML操做。
2. 由於外部表須要在ORACLE數據庫「服務端」建立目錄,OS文件必須放在這些目錄中。即這些文件只能放在數據庫服務端。若是數據文件不位於服務器,則沒法使用外部表
3. 外部表上不能建立索引。但能夠創建視圖
4. 外部表不支持LOB對象。若是要使用LOB類型,則不能使用外部表。
eg:刪除外部表的記錄
SQL> delete from exter_test where id=10001;
delete from exter_test where id=10001
*
ERROR at line 1:
ORA-30657: operation not supported on external organized table
eg: 在外部表上建立視圖
SQL> create or replace view vv
2 as
3 select * from etl.exter_test;
View created.
SQL> select * from vv;
ID NAME SEX AGE GRADE
---------- ------------ -------- ---------- ----------
10001 kerry male 28 1
10002 jimmy male 22 1
10003 ken male 21 1
10004 merry femal 20 1
SQL>
外部表優點:
若是要談外部表的優點,通常會和SQLLDR來對比,外部表不少語法跟SQLLDR控制文件確實有不少相似的地方,下面談談本身的理解和"Oracel 9i&10g編程藝術"裏面的一些對比
1. SQLLDR須要將數據裝載入庫後才能查詢相關記錄,若是隻是爲了查詢一些記錄,外部表確實比SQLLDR要有優點一些,很方便又不佔用數據庫存儲空間。尤爲是很大的數據,之前作移動綜合分析項目處理SGSN話單(幾百G的數據,若是所有裝載入庫,很是浪費空間和時間)時就有這樣的體會。外部表虛擬的導入過程極快
2:當平面文件改變時,外部表內的數據會跟着改變。這樣避免了插入、更新、刪除等操做,對於超大記錄的外部表至關有優點,我只須要使用Shell命令就能搞定數據庫須要很高代價才能完成的事情。
3:外部表可使用複雜的WHERE 條件有選擇地加載數據。儘管SQLLDR 有一個WHEN 子句用來選擇要加載的行,可是你只能使用AND 表達式和執行相等性比較的表達式,在WHEN 子句中不能使用區間(大於、小於),沒有OR 表達式,也沒有IS NULL 等。
4:可以合併(MERGE)數據。能夠取一個填滿數據的操做系統文件,並由它更新現有的數據庫記錄。
5:能執行高效的代碼查找。能夠將一個外部表聯結到另外一個數據庫表做爲加載過程的一部分。
6:使用INSERT 更容易地執行多表插入。從Oracle9i 開始,經過使用複雜的WHEN 條件,能夠用一個INSERT 語句插入一個或多個表。儘管SQLLDR 也能夠加載到多個表中,可是相應的語法至關複雜。
參考資料:
http://blog.itpub.net/22578826/viewspace-703470
http://www.cnblogs.com/lanzi/archive/2010/12/28/1918755.html