Oracle數(shù)據(jù)庫數(shù)據(jù)對象分析
Oracle數(shù)據(jù)庫數(shù)據(jù)對象中最基本的是表和視圖,其他還有約束、序列、函數(shù)、存儲過程、包、觸發(fā)器等。對數(shù)據(jù)庫的操作可以基本歸結(jié)為對數(shù)據(jù)對象的操作,理解和掌握Oracle數(shù)據(jù)庫對象是學(xué)習(xí)Oracle的捷徑。
表和視圖
Oracle中表是數(shù)據(jù)存儲的基本結(jié)構(gòu)。ORACLE8引入了分區(qū)表和對象表,ORACLE8i引入了臨時(shí)表,使表的功能更強(qiáng)大。視圖是一個(gè)或多個(gè)表中數(shù)據(jù)的邏輯表達(dá)式。本文我們將討論怎樣創(chuàng)建和管理簡單的表和視圖。
管理表
表可以看作有行和列的電子數(shù)據(jù)表,表是關(guān)系數(shù)據(jù)庫中一種擁有數(shù)據(jù)的結(jié)構(gòu)。用CREATE TABLE語句建立表,在建立表的同時(shí),必須定義表名,列,以及列的數(shù)據(jù)類型和大小。例如:
CREATE TABLE products (
PROD_ID NUMBER(4),
PROD_NAME VAECHAR2(20),
STOCK_QTY NUMBER(5,3)
);
這樣我們就建立了一個(gè)名為products的表, 關(guān)鍵詞CREATE TABLE后緊跟的表名,然后定義了三列,同時(shí)規(guī)定了列的數(shù)據(jù)類型和大小。
在創(chuàng)建表的同時(shí)你可以規(guī)定表的完整性約束,也可以規(guī)定列的完整性約束,在列上普通的約束是NOT NULL,關(guān)于約束的討論我們在以后進(jìn)行。
在建立或更改表時(shí),可以給表一個(gè)缺省值。缺省值是在增加行時(shí),增加的數(shù)據(jù)行中某一項(xiàng)值為null時(shí),oracle即認(rèn)為該值為缺省值。
下列數(shù)據(jù)字典視圖提供表和表的列的信息:
. DBA_TABLES
. DBA_ALL_TABLES
. USER_TABLES
. USER_ALL_TABLES
. ALL_TABLES
. ALL_ALL_TABLES
. DBA_TAB_COLUMNS
. USER_TAB_COLUMNS
. ALL_TAB_COLUMNS
表的命名規(guī)則
表名標(biāo)識一個(gè)表,所以應(yīng)盡可能在表名中描述表,oracle中表名或列名最長可以達(dá)30個(gè)字符串。表名應(yīng)該以字母開始,可以在表名中包含數(shù)字、下劃線、#、$等。
從其它表中建立表
可以使用查詢從基于一個(gè)或多個(gè)表中建立表,表的列的數(shù)據(jù)類型和大小有查詢結(jié)果決定。建立這種形式的表的查詢可以選擇其他表中所有的列或者只選擇部分列。在CREATE TABLE語句中使用關(guān)鍵字AS,例如:
SQL> CREATE TABLE emp AS SELECT * FROM employee
SQL> CREATE TABLE Y AS SELECT * FROM X WHERE no=2
需要注意的是如果查詢涉及LONG數(shù)據(jù)類型,那么CREATE TABLE....AS SELECT....將不會(huì)工作。
更改表定義
在建立表后,有時(shí)候我們可能需要修改表,比如更改列的定義,更改缺省值,增加新列,刪除列等等。ORACLE使用ALTER TABLE語句來更改表的定義
1、增加列
語法:ALTER TABLE [schema.] table_name ADD column_definition
例:
ALTER TABLE orders ADD order_date DATE;
對于已經(jīng)存在的數(shù)據(jù)行,新列的值將是NULL.
2、更改列
語法: ALTER TABLE [schema.] table_name MODIFY column_name new_attributes;
例:
ALTER TABLE orders MODITY (quantity number(10,3),status varchar2(15));
這個(gè)例子中我們修改了表orders,將STATUS列的長度增加到15,將QUANTITY列減小到10,3;
修改列的規(guī)則如下:
. 可以增加字符串?dāng)?shù)據(jù)類型的列的長度,數(shù)字?jǐn)?shù)據(jù)類型列的精度。
. 減少列的長度時(shí),該列應(yīng)該不包含任何值,所有數(shù)據(jù)行都為NULL.
. 改變數(shù)據(jù)類型時(shí),該列的值必須是NULL.
. 對于十進(jìn)制數(shù)字,可以增加或減少但不能降低他的精度。
3、刪除數(shù)據(jù)列
優(yōu)化ORACLE數(shù)據(jù)庫,唯一的方法是刪除列,重新建立數(shù)據(jù)庫。在ORACLE8i中有很多方法刪除列,你可以刪除未用數(shù)據(jù)列或者可以標(biāo)示該列為未用數(shù)據(jù)列然后刪除。
語法:ALTER TABLE [schema.] table_name DROP {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
要注意的是在刪除列時(shí)關(guān)于該列的索引和完整性約束也同時(shí)刪除。注意關(guān)鍵字CASCADE CONSTRAINS,如果刪除的列是多列約束的一部分,那么這個(gè)約束條件相對于其他列也同時(shí)刪除。
如果用戶擔(dān)心在大型數(shù)據(jù)庫中刪除列要花太多時(shí)間,可以先將他們標(biāo)記為未用數(shù)據(jù)列,標(biāo)記未用數(shù)據(jù)列的語法如下:
ALTER TABLE [schema.] table_name SET UNUSED {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
這個(gè)語句將一個(gè)或多個(gè)數(shù)據(jù)列標(biāo)記為未用數(shù)據(jù)列,但并不刪除數(shù)據(jù)列中的數(shù)據(jù),也不釋放占用的磁盤空間。但是,未用數(shù)據(jù)列在視圖和數(shù)據(jù)字典中并不顯示,并且該數(shù)據(jù)列的名稱將被刪除,新的數(shù)據(jù)列可以使用這個(gè)名稱。基于該數(shù)據(jù)列的索引、約束,統(tǒng)計(jì)等都將被刪除。
刪除未用數(shù)據(jù)列的語句是:
ALTER TABLE [schema.] table_name DROP {UNUSED COLUM | COLUMN CONTINUE}
刪除表和更改表名
刪除表非常簡單,但它是一個(gè)不可逆轉(zhuǎn)的行為。
語法: DROP TABLE [schema.] table_name [CASCADE CONSTRAINTS]
刪除表后,表上的索引、觸發(fā)器、權(quán)限、完整性約束也同時(shí)刪除。ORACLE不能刪除視圖,或其他程序單元,但oracle將標(biāo)示他們無效。如果刪除的表涉及引用主鍵或唯一關(guān)鍵字的完整性約束時(shí),那么DROP TABLE語句就必須包含CASCADE CONSTRAINTS子串。
更改表名
RENAME命令用于給表和其他數(shù)據(jù)庫對象改名。ORACLE系統(tǒng)自動(dòng)將基于舊表的完整性約束、索引、權(quán)限轉(zhuǎn)移到新表中。ORACLE同時(shí)使所有基于舊表的數(shù)據(jù)庫對象,比如視圖、程序、函數(shù)等,為不合法。
語法:RENAME old_name TO new_name;
例:
SQL> RENAME orders TO purchase_orders;
截短表
TRUNCATE命令與DROP命令相似, 但他不是刪除整個(gè)數(shù)據(jù)表,所以索引、完整性約束、觸發(fā)器、權(quán)限等都不會(huì)被刪除。缺省情況下將釋放部分表和視圖空間,如果用戶不希望釋放表空間,TRUNCATE語句中要包含REUSE STORAGE子串。TRUNCATE命令語法如下:
TRUNCATE {TABLE|CLUSTER} [schema.] name {DROP|REUSE STORAGE}
例:
SQL> TRUNCATE TABLE t1;
管理視圖
視圖是一個(gè)或多個(gè)表中的數(shù)據(jù)的簡化描述,用戶可以將視圖看成一個(gè)存儲查詢(stored query)或一個(gè)虛擬表(virtual table).查詢僅僅存儲在oracle數(shù)據(jù)字典中,實(shí)際的數(shù)據(jù)沒有存放在任何其它地方,所以建立視圖不用消耗其他的空間。視圖也可以隱藏復(fù)雜查詢,比如多表查詢,但用戶只能看見視圖。視圖可以有與他所基于表的列名不同的列名。用戶可以建立限制其他用戶訪問的視圖。
建立視圖
CREATE VIEW命令創(chuàng)建視圖,定義視圖的查詢可以建立在一個(gè)或多個(gè)表,或其他視圖上。查詢不能有FOR UPDATE子串,在早期的ORACLE8i版本中不支持ORDER BY子串,現(xiàn)在的版本中CREATE VIEW可以擁有ORDER BY子串。
例:
SQL> CREATE VIEW TOP_EMP AS
SELECT empno EMPLOYEE_ID,ename EMPLOYEE_NAME,salary
FROM emp
WHERE salary > 2000
用戶可以在創(chuàng)建視圖的同時(shí)更改列名,方法是在視圖名后立即加上要命名的列名。重新定義視圖需要包含OR REPLACE子串。
SQL> CREATE VIEW TOP_EMP(EMPLOYEE_ID,EMPLOYEE_NAME,SALARY) AS
SELECT empno ,ename ,salary FROM emp WHERE salary >2000
如果在創(chuàng)建的視圖包含錯(cuò)誤在正常情況下,視圖將不會(huì)被創(chuàng)建。但如果你需要?jiǎng)?chuàng)建一個(gè)帶錯(cuò)誤的視圖必須在CREATE VIEW語句中帶上FORCE選項(xiàng)。如:
CREATE FORCE VIEW ORDER_STATUS AS
SELECT * FROM PURCHASE_ORDERS
WHERE STATUS="APPPOVE";
SQL>/
warning :View create with compilation errors
這樣將創(chuàng)建了一個(gè)名為ORDER_STATUS的視圖,但這樣的視圖的狀態(tài)是不合法的,如果以后狀態(tài)發(fā)生變化則可以重新編譯,其狀態(tài)也變成合法的。
從視圖中獲得數(shù)據(jù)
從視圖中獲得數(shù)據(jù)與從表中獲得數(shù)據(jù)基本一樣,用戶可以在連接和子查詢中使用視圖,也可以使用SQL函數(shù),以及所有SELECT語句的字串。
插入、更新、刪除數(shù)據(jù)
用戶在一定的限制條件下可以通過視圖更新、插入、刪除數(shù)據(jù)。如果視圖連接多個(gè)表,那么在一個(gè)時(shí)間里只能更新一個(gè)表。所有的能被更新的列可以在數(shù)據(jù)字典USER_UPDATETABLE_COLUMNS中查到。
用戶在CREATE VIEW中可以使用了WITH子串。WITH READ ONLY子串表示創(chuàng)建的視圖是一個(gè)只讀視圖,不能進(jìn)行更新、插入、刪除操作。WITH CHECK OPTION表示可以進(jìn)行插入和更新操作,但應(yīng)該滿足WHERE子串的條件。這個(gè)條件就是創(chuàng)建視圖WHERE子句的條件,比如在上面的例子中用戶創(chuàng)建了一個(gè)視圖TOP_EMP,在這個(gè)視圖中用戶不能插入salary小于2000的數(shù)據(jù)行。
刪除視圖
刪除視圖使用DROP VIEW命令。同時(shí)將視圖定義從數(shù)據(jù)字典中刪除,基于視圖的權(quán)限也同時(shí)被刪除,其他涉及到該視圖的函數(shù)、視圖、程序等都將被視為非法。
例:
DROP VIEW TOP_EMP;
過程和函數(shù)
過程和函數(shù)都以編譯后的形式存放在數(shù)據(jù)庫中,函數(shù)可以沒有參數(shù)也可以有多個(gè)參數(shù)并有一個(gè)返回值。過程有零個(gè)或多個(gè)參數(shù),沒有返回值。函數(shù)和過程都可以通過參數(shù)列表接收或返回零個(gè)或多個(gè)值,函數(shù)和過程的主要區(qū)別不在于返回值,而在于他們的調(diào)用方式。過程是作為一個(gè)獨(dú)立執(zhí)行語句調(diào)用的:
pay_involume(invoice_nbr,30,due_date);
函數(shù)以合法的表達(dá)式的方式調(diào)用:
order_volumn:=open_orders(SYSDATE,30);
創(chuàng)建過程的語法如下:
CREATE [ OR REPLACE] PROCEDURE [schema.]procedure_name
[parameter_lister]
{AS|IS}
declaration_section
BEGIN
executable_section
[EXCEPTION
exception_section]
END [procedure_name]
每個(gè)參數(shù)的語法如下:
paramter_name mode datatype [(:=|DEFAULT) value]
mode有三種形式:IN、OUT、INOUT。
IN表示在調(diào)用過程的時(shí)候,實(shí)際參數(shù)的取值被傳遞給該過程,形式參數(shù)被認(rèn)為是只讀的,當(dāng)過程結(jié)束時(shí),控制會(huì)返回控制環(huán)境,實(shí)際參數(shù)的值不會(huì)改變。
OUT在調(diào)用過程時(shí)實(shí)際參數(shù)的取值都將被忽略,在過程內(nèi)部形式參數(shù)只能是被賦值,而不能從中讀取數(shù)據(jù),在過程結(jié)束后形式參數(shù)的內(nèi)容將被賦予實(shí)際參數(shù)。
INOUT這種模式是IN和OUT的組合;在過程內(nèi)部實(shí)際參數(shù)的值會(huì)傳遞給形式參數(shù),形勢參數(shù)的值可讀也可寫,過程結(jié)束后,形勢參數(shù)的值將賦予實(shí)際參數(shù)。
創(chuàng)建函數(shù)的語法和過程的語法基本相同,唯一的區(qū)別在于函數(shù)有RETUREN子句
CREATE [ OR REPLACE] FINCTION [schema.]function_name
[parameter_list]
RETURN returning_datatype
{AS|IS}
declaration_section
BEGIN
executable_section
[EXCEPTION]
exception_section
END [procedure_name]
在執(zhí)行部分函數(shù)必須有喲個(gè)或多個(gè)return語句。
在創(chuàng)建函數(shù)中可以調(diào)用單行函數(shù)和組函數(shù),例如:
CREATE OR REPLACE FUNCTION my_sin(DegreesIn IN NUMBER)
RETURN NUMBER
IS
pi NUMBER=ACOS(-1);
RadiansPerDegree NUMBER;
BEGIN
RadiansPerDegree=pi/180;
RETURN(SIN(DegreesIn*RadiansPerDegree));
END;
包
包是一種將過程、函數(shù)和數(shù)據(jù)結(jié)構(gòu)捆綁在一起的容器;包由兩個(gè)部分組成:外部可視包規(guī)范,包括函數(shù)頭,過程頭,和外部可視數(shù)據(jù)結(jié)構(gòu);另一部分是包主體(package body),包主體包含了所有被捆綁的過程和函數(shù)的聲明、執(zhí)行、異常處理部分。
打包的PL/SQL程序和沒有打包的有很大的差異,包數(shù)據(jù)在用戶的整個(gè)會(huì)話期間都一直存在,當(dāng)用戶獲得包的執(zhí)行授權(quán)時(shí),就等于獲得包規(guī)范中的所有程序和數(shù)據(jù)結(jié)構(gòu)的權(quán)限。但不能只對包中的某一個(gè)函數(shù)或過程進(jìn)行授權(quán)。包可以重載過程和函數(shù),在包內(nèi)可以用同一個(gè)名字聲明多個(gè)程序,在運(yùn)行時(shí)根據(jù)參數(shù)的數(shù)目和數(shù)據(jù)類型調(diào)用正確的程序。
創(chuàng)建包必須首先創(chuàng)建包規(guī)范,創(chuàng)建包規(guī)范的語法如下:
CREATE [OR REPLACE] PACKAGE package_name
{AS|IS}
public_variable_declarations |
public_type_declarations |
public_exception_declarations |
public_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
創(chuàng)建包主體使用CREATE PACKAGE BODY語句:
CREATE [OR REPLACE] PACKAGE BODY package_name
{AS|IS}
private_variable_declarations |
private_type_declarations |
private_exception_declarations |
private_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
私有數(shù)據(jù)結(jié)構(gòu)是那些在包主體內(nèi)部,對被調(diào)用程序而言是不可見的。
觸發(fā)器(Triggers)
觸發(fā)器是一種自動(dòng)執(zhí)行響應(yīng)數(shù)據(jù)庫變化的程序。可以設(shè)置為在觸發(fā)器事件之前或之后觸發(fā)或執(zhí)行。能夠觸發(fā)觸發(fā)器事件的事件包括下面幾種:
DML事件
DDL事件
數(shù)據(jù)庫事件
創(chuàng)建觸發(fā)器的語法如下:
CREATE [OR REPLACE] TRIGGER trigger_name
{before|after|instead of} event
ON {table_or_view_name|DATABASE}
[FOR EACH ROW[WHEN condition>
trigger_body
只有DML觸發(fā)器(INSERT、UPDATE、DELETE)語句可以使用INSTEAD OF觸發(fā)器并且只有表的DML觸發(fā)器可以是BEFORE或AFTER觸發(fā)器。
象約束一樣觸發(fā)器可以被設(shè)置為禁用或啟用來關(guān)閉或打開他們的執(zhí)行體(EXECUTE),將觸發(fā)器設(shè)置為禁用或啟用使用ALTER TRIGGER語句:
ALTER TRIGGER trigger_name ENABLE;
ALTER TRIGGER trigger_name DISABLE;
要禁用或啟用表的所有觸發(fā)器,使用ALTER TABLE語句
ALTER TRIGGER table_name DISABLE ALL TRIGGER;
ALTER TRIGGER table_name ENABLE ALL TRIGGER;
刪除觸發(fā)器使用DROP TRIGGER
DROP TRIGGER trigger_name;
數(shù)據(jù)字典
Oracle數(shù)據(jù)字典包含了用戶數(shù)據(jù)庫的元數(shù)據(jù)。帶下劃線的表名稱中帶OBJ$、UET$、SOURCE$,這些表是在執(zhí)行CREATE DATABASE語句期間由sql.bsq腳本創(chuàng)建的,一般情況下用戶很少訪問這些表。腳本catalog.sql(通常位于$oracle_home/rdbms/admin)在CREATE DATABASE語句之后立即運(yùn)行,創(chuàng)建數(shù)據(jù)字典視圖。
數(shù)據(jù)字典視圖大致可以分為三類:
.前綴為USER_的數(shù)據(jù)字典視圖,包含了用戶擁有的對象的信息。
.前綴為ALL_的數(shù)據(jù)字典視圖,包含了用戶當(dāng)前可以訪問的全部對象和權(quán)限的信息。
.前綴為DBA_的數(shù)據(jù)字典視圖,包含了數(shù)據(jù)庫擁有的所有對象和權(quán)限的信息。
在絕大多數(shù)數(shù)據(jù)字典視圖中都有象DBA_TABLES,ALL_TABLES和USER_TABLES這樣的視圖家族。Oracle中有超過100個(gè)視圖家族,所以要全面介紹這些視圖家族是單調(diào)乏味的而且沒有多大的意義。在下表中列出了最重要和最常用的視圖家族,需要注意的是每個(gè)視圖家族都有一個(gè)DBA_,一個(gè)ALL_一個(gè)USER_視圖。
其他的字典視圖中主要的是V$視圖,之所以這樣叫是因?yàn)樗麄兌际且訴$或GV$開頭的。V$視圖是基于X$虛擬視圖的。V$視圖是SYS用戶所擁有的,在缺省狀況下,只有SYS用戶和擁有DBA系統(tǒng)權(quán)限的用戶可以看到所有的視圖,沒有DBA權(quán)限的用戶可以看到USER_和ALL_視圖,但不能看到DBA_視圖。與DBA_,ALL,和USER_視圖中面向數(shù)據(jù)庫信息相反,這些視圖可視的給出了面向?qū)嵗男畔ⅰ?
在大型系統(tǒng)上化幾周時(shí)間手工輸入每一條語句
手工輸入帶用戶名變量的語句,然后再輸入每一個(gè)用戶名,這需要花好幾個(gè)小時(shí)的時(shí)間
寫一條SQL語句,生成需要的ALTER USER語句,然后執(zhí)行他,這只需要幾分鐘時(shí)間
很明顯我們將選擇生成SQL的方法:
例:
SELECT "ALTER USER"||username||"TEMPORARY TABLESPACE temp;"
FROM DBA_USERS
WHERE username<>"SYS"
AND temporary_tablespace<>"TEMP";
這個(gè)查詢的結(jié)果將被脫機(jī)處理到一個(gè)文件中,然后在執(zhí)行:
ALTER USER SYSTEM TEMPORARY TABLESPACE temp;
ALTER USER OUTLN TEMPORARY TABLESPACE temp;
ALTER USER DBSNMP TEMPORARY TABLESPACE temp;
ALTER USER SCOTT TEMPORARY TABLESPACE temp;
ALTER USER DEMO TEMPORARY TABLESPACE temp;