1. 程式人生 > >視圖、序列、索引、約束

視圖、序列、索引、約束

objects ont 標識 索引 得到 play 分組 back 情況

1. 視圖

? 視圖定義

視圖(VIEW)也被稱作虛標,即虛擬的表,是一組數據的邏輯表示,其本質是對應於一條SELECT語句,結果集被賦予一個名字,即視圖名字。

視圖本身並不包含任何數據,它只包含映射到基表的一個查詢語句,當基表數據發生變化,視圖數據也隨之變化。

創建視圖語法:

CREATE [OR REPLACE] VIEW view_name [(alias[,alias…])] AS subquery;

視圖創建後,可以像操作表一樣操作視圖,主要是查詢操作。

根據視圖所對應的子查詢種類分為:

l SELECT語句是基於單表建立的,且不包含任何函數運算、表達式或分組函數,叫做簡單視圖,此時視圖是基表的子集

l SELECT語句同樣是基於單表,但包含了單行函數、表達式、分組函數或GROUP BY 子句,叫做復雜視圖

l SELECT語句是基於多個表的,叫做連接視圖。

? 視圖作用

如果需要經常執行某項復雜查詢,可以基於這個復雜查詢建立視圖,此後查詢此視圖即可,簡化復雜查詢。

視圖本質上就是一條SELECT語句,所以當訪問視圖時,只能訪問所對應的SELECT語句中設計到的列,對基表中的其它列起到安全和保密的作用,可以限制數據訪問。

? 授權創建視圖

創建視圖的DDL語句是CREATE VIEW,用於必須有CREATE VIEW系統權限才能創建視圖。

案例:演示權限不足情況下創建視圖報錯如下

技術分享

管理員通過DCL語句授予用戶創建視圖的權限,如下:

GRANT CREATE VIEW TO username;

案例:授予SCOTT創建視圖權限

技術分享

? 創建簡單視圖

案例:使用SCOTT用戶創建emp的視圖

CREATE VIEW v_emp

AS

SELECT empno,ename,sal,deptno

FROM emp

WHERE deptno=10;

技術分享

查看視圖:

DESC v_emp;

技術分享

? 查詢視圖

案例:查詢視圖

SELECT * FROM v_emp;

技術分享

? INSERT

視圖本身並不包含數據,只是基表數據的邏輯映射。所以當對視圖執行DML操作時,實際上是對基表的DML操作。對視圖執行DML操作基本原則如下:

l 簡單視圖能夠執行DML操作,下列情況除外:在基表中定義了非空列,但簡單視圖對應的SELECT語句並沒有包含這個非空列,導致這個非空列對視圖不可見,這時無法對視圖執行INSERT操作

l 如果視圖定義中包含了函數、表達式、分組語句、DISTINCT關鍵字或ROWNUM偽列,不允許執行DML操作

l DML操作不能違反基表的約束條件

案例:對簡單視圖進行INSERT操作

INSERT INTO v_emp VALUES (1000,‘QQQ‘,5000,10);

查看視圖:

SELECT * FROM v_emp;

技術分享

查看基表:可以發現對基表產生了影響

SELECT * FROM emp;

技術分享

? CHECK OPTION約束

語法:

CREATE [OR REPLACE] VIEW view_name[(alias[, alias…])]

AS subquery

[WITH CHECK OPTION];

WITH CHECK OPTION表示通過視圖所做的修改,必須在視圖的可見範圍內:

l INSERT,新增的記錄在視圖仍可查看

l UPDATE,修改後的結果必須能通過視圖查看到

l DELETE,只能刪除現有視圖裏能看到的記錄

案例:創建帶有CHECK OPTION約束的視圖

CREATE OR REPLACE VIEW v_emp

AS

SELECT empno id,ename name,sal salary,deptno

FROM emp

WHERE deptno=10

WITH CHECK OPTION;

? READ ONLY約束

對簡單視圖進行DML操作是合法的,但是不安全。如果沒有在視圖上執行DML操作的必要,在建立時可以聲明只讀來避免對基表數據的非法修改。

語法:

CREATE [OR REPLACE] VIEW view_name[(alias[, alias…])]

AS subquery

[WITH READ ONLY];

案例:創建帶有READ ONLY約束的視圖

CREATE OR REPLACE VIEW vread_emp

AS

SELECT empno,ename,sal,deptno FROM emp

WHERE deptno=10

WITH READ ONLY;

對該表進行修改測試:

DELETE FROM vread_emp WHERE ename=‘CLARK‘;

技術分享

? 數據字典

和視圖相關的數據字典如下:

l USER_OBJECTS

l USER_VIEWS

l USER_UPDATABLE_COLUMNS

案例:USER_OBJECTS

SELECT object_name FROM user_objects WHERE object_type=‘VIEW‘;

技術分享

案例:USER_VIEWS

SELECT text FROM user_views WHERE view_name=‘V_EMP‘; --視圖名字要大寫

技術分享

案例:USER_UPDATABLE_COLUMNS

SELECT column_name,insertable,updatable,deletable

FROM user_updatable_columns

WHERE table_name=‘V_EMP‘;

技術分享

? 創建復雜視圖

創建復雜視圖指在子查詢中包含了表達式、單行函數或分組函數的視圖。此時必須為子查詢中的表達式或函數定義別名。

如果不創建別名會有以下錯誤提示:

技術分享

案例:創建一個視圖把emp表的數據按部門分組,獲得每個部門的平均薪水、薪水總和、最高薪水和最低薪水

CREATE VIEW vsalary_emp

AS

SELECT d.dname,AVG(e.sal) avg_sal,SUM(e.sal) sum_sal,MAX(e.sal) max_sal,MIN(sal) min_sal

FROM emp e JOIN dept d

ON e.deptno=d.deptno

GROUP BY d.dname;

SELECT * FROM vsalary_emp;

技術分享

註意:復雜視圖不允許DML操作,否則會報錯。

當不再需要視圖的定義,可以使用DROP VIEW語句刪除視圖。

案例:刪除復雜VIEW

DROP VIEW vsalary_emp;

2. 序列

? 序列的定義

序列(SEQUENCE)是一種用來生成唯一數字的數據庫對象。序列的值由Oracle程序按遞增或遞減順序自動生成,通常用來自動產生表的主鍵值,是一種高效率獲得唯一鍵值的途徑。

序列是獨立的數據庫對象,和表是獨立的對象,序列並不依附於表。

通常情況下,一個序列為一個表提供主鍵值,但一個序列也可以為多個表提供主鍵值。

? 創建序列

語法:

CREATE SEQUENCE [schema.] sequence_name

[START WITH i] [INCREMENT BY j]

[MAXVLUE m | NOMAXVALUE]

[MINVALUE n | NOMINVALUE]

[CYCLE | NOCYCLE] [CACHE p | NOCACHE]

參數含義如下:

l sequence_name是序列名,將創建在schema方案下

l 序列的第一個序列值是i,步進是j

l 如果j是整數,表示遞增,j是負數,表示遞減

l 序列可生成的最大值是m,最小值是n

l 如果沒有設置任何可選參數,序列第一個值是1,步進是1

l CYCLE表示在遞增至最大值或遞減至最小值之後是否繼續生成序列號,默認是NOCYCLE

l CACHE用來指定先預取p個數據在緩存中,以提高序列值的生成效率,默認是20

案例:創建一個序列起始數據是100,步進是10

CREATE SEQUENCE emp_seq

START WITH 100

INCREMENT BY 10;

當創建序列後,必須先執行一次NEXTVAL,才能使用CURRVAL。

先不執行NEXTVAL,直接執行CURRVAL查看效果:

SELECT emp_seq.CURRVAL FROM dual;

技術分享

獲取第一個值並使用序列值為EMP插入新的數據:

INSERT INTO emp(empno,ename) VALUES (emp_seq.NEXTVAL,‘SEQ1‘);

查詢新數據會發現插入的empno是100:

SELECT * FROM emp WHERE ename=‘SEQ1‘;

技術分享

運行一次NEXTVAL得到序列號加10,即110:

SELECT emp_seq.NEXTVAL FROM dual;

技術分享

查看當前序列號:

SELECT emp_seq.CURRVAL FROM dual;

技術分享

? 刪除序列

語法:

DROP SEQUENCE sequence_name;

案例:刪除序列emp_seq

DROP SEQUENCE emp_seq;

3. 索引

? 索引原理

索引是一種允許直接訪問數據表中某一數據行的樹形結構,為了提高查詢效率而引入,是獨立於表的對象,可以存放在與表不同的表空間(TABLESPACE)中。索引記錄中存有索引關鍵字和指向表中數據的指針(地址)。對索引進行I/O操作比對表進行操作要少很多。

索引一旦被建立就將被Oracle系統自動維護,查詢語句中不用指定使用哪個索引,是一種提高查詢效率的機制。

ROWID:偽列,唯一標識一條數據記錄,可理解為行地址。

? 創建索引

語法:

CREATE [UNIQUE] INDEX index_name ON table(column[,column…])

l index_name:表示索引名稱

l table:表示表名

l column:表示列名,可以簡歷單列索引和符合索引

l UNIQUE:表示唯一索引

案例:在emp表的ename列上建立索引

CREATE INDEX idx_emp_ename ON emp(ename);

技術分享

? 創建復合索引

復合索引也叫多列索引,是基於多個列的索引。

如果經常在ORDER BY子句中使用job和sal作為排序依據,可以建立復合索引,如下案例

案例:建立復合索引

CREATE INDEX idx_job_sal ON emp(job,sal);

當做下面查詢時,會自動應用索引idx_job_sal

SELECT empno,ename,sal,job FROM emp ORDER BY job,sal;

? 創建基於函數的索引

如果需要在emp表的ename列上執行大小寫無關搜索,可以在此列上建立一個基於UPPER的函數的索引,如下案例:

CREATE INDEX emp_ename_upper_idx ON emp(UPPER(ename));

做以下查詢,會自動應用剛剛建立的索引:

SELECT * FROM emp WHERE UPPER(ename)=‘SMITH‘;

? 修改和刪除索引

如果經常在索引列上執行DML操作,需要定期重建所有,提高所有的空間利用率。

重建索引語法:

ALTER INDEX index_name REBUILD;

案例:重建索引idx_emp_ename

ALTER INDEX idx_emp_ename REBUILD;

技術分享

當一個表上有不合理的索引,會導致操作性能下降,需要刪除。

刪除索引語法:

DROP INDEX index_name;

案例:刪除idx_emp_ename

DROP INDEX idx_emp_ename;

技術分享

? 合理使用索引提升查詢效率

l 為經常出現在WHERE子句中的列創建索引

l 為經常出現在ORDER BY、DISTINCT後面的字段建立索引,如果建立的是復合索引,索引的字段順序要和這些關鍵字後面的字段順序一致

l 為經常作為表的連接條件的列上創建索引

l 不要在經常做DML操作的表上建立索引

l 不要在小表上建立索引

l 限制表上的索引數據,索引並不是越多越好

l 刪除很少被使用、不合理的索引

4. 約束

? 約束的作用

l 約束(CONSTRAINT),即約束條件,也稱作完整性約束條件

l 約束是在數據表上強制執行的一些數據校驗規則,當執行DML操作時,數據必須符合這些規則,如果不符合則無法執行

l 約束條件可以保證表中數據的完整性,保證數據間的商業邏輯

? 約束的類型

l 非空約束(Not Null),簡稱NN

l 唯一性約束(Unique),簡稱UK

l 主鍵約束(Primary Key),簡稱PK

l 外鍵約束(Foreign Key),簡稱FK

l 檢查約束(Check),簡稱CK

4.1 非空約束

? 建表時添加非空約束

非空約束用於確保字段值不為空,默認情況下,任何列都允許有空值,但業務邏輯可能會要求某些列不能取空值,當某個字段被設置了非空約束條件,這個字段中必須存在有效值。即:

u 當執行INSERT操作時,必須提供這個列的數據

u 當執行UPDATE操作時,不能給這個列的值設置為NULL

案例:建表時設置非空約束

CREATE TABLE test_emp(

id NUMBER(8) NOT NULL,

name VARCHAR2(30) NOT NULL,

salary NUMBER(8,2)

);

技術分享

? 修改表時添加非空約束

可以在建表之後,通過修改表的定義,添加非空約束

案例:修改test_emp表salary列設置非空約束

ALTER TABLE test_emp MODIFY (salary NUMBER(8,2) NOT NULL);

技術分享

? 取消非空約束

取消某列的非空約束,可以采用重建表或修改表的方式。

案例:修改salary列取消非空約束

ALTER TABLE test_emp MODIFY (salary NUMBER(8,2) NULL);

技術分享

4.2 唯一性約束

? 唯一性約束

唯一性(Unique)約束條件用於保證字段或者字段的組合不出現重復值。當給表的某個列定義了唯一性約束條件,該列的值不允許重復,但允許是NULL值。唯一性約束條件可以在建表的時候建立,也可以在建表以後再建立。

? 添加唯一性約束

案例:建表時添加唯一性約束

CREATE TABLE emp2(

eid NUMBER(6) UNIQUE,

name VARCHAR2(30),

email VARCHAR2(50),

salary NUMBER(7,2),

hiredate DATE,

CONSTRAINT emp2_email_uk UNIQUE(email)

);

案例:建表後增加唯一性約束條件

ALTER TABLE test_emp2 ADD CONSTRAINT test_emp2_name UNIQUE(name);

如果在其它表上建立唯一性約束,則唯一性條件約束的名稱不能重復,不然會出現如下錯誤提示:

如:執行ALTER TABLE test_emp3 ADD CONSTRAINT test_emp2_name UNIQUE(name);

技術分享

註意:如果一個已存在的表,有一列已經有重復字段,再想給這個表的這一列添加唯一性約束就會報錯,報錯內容為:有重復關鍵字。

4.3 主鍵約束

? 主鍵的意義

主鍵(Primary Key)約束條件從功能上看相當於非空(NOT NULL)且唯一(UNIQUE)的組合。主鍵字段可以是單字段或多字段組合,即:在主鍵約束下的單字段或者多字段組合上不允許有空值,也不允許有重復值。主鍵可以用來在表中唯一的確定一行數據,一個表上只允許建立一個主鍵,而其他約束條件則沒有明確的個數限制。

? 主鍵選取的原則

l 主鍵應是對系統無意義的數據

l 永遠也不要更新主鍵,讓主鍵除了唯一標識一行之外再無其他作用

l 主鍵不應包含動態變化的數據,如時間戳

l 主鍵應自動生成,不要人為幹預,以免使它帶有除了唯一標識一行以外的意義

l 主鍵盡量建立在單列上

? 添加主鍵約束

案例:建表時添加主鍵約束

CREATE TABLE test_emp3(

id NUMBER(8) PRIMARY KEY,

name VARCHAR2(30),

salary NUMBER(8,2)

);

案例:建表後添加主鍵約束

ALTER TABLE test_emp4 ADD CONSTRAINT test_emp3_pk PRIMARY KEY (id);

4.4 外鍵約束

? 外鍵約束的意義

外鍵約束條件定義在兩個表的字段或一個表的兩個字段上,用於保證相關兩個字段的關系。如:

dept表:主表或父表

emp表:從表或子表

外鍵裏面的值,必須是NULL或者主鍵裏有的值。

主鍵裏想刪除一個值,必須是外鍵裏面沒有參照的(不存在的)。

? 添加外鍵約束

先建表,在建表後建立外鍵約束條件。

案例:

技術分享

錯誤原因:因為dept1表沒有添加主鍵,刪除兩個表,重新配置外鍵約束,如下:

CREATE TABLE dept1(

deptno NUMBER(8) PRIMARY KEY,

loc VARCHAR2(30)

);

CREATE TABLE emp1(

id NUMBER(8),

name VARCHAR2(30),

deptno NUMBER(8)

);

ALTER TABLE emp1

ADD CONSTRAINT emp1_deptno_fk

FOREIGN KEY (deptno) REFERENCES dept1(deptno);

技術分享

? 外鍵約束對一致性的維護

l 從表上定義的外鍵的列值,必須從主表被參照的列值中選取,或者為NULL

l 當主表參照列的值被從表參照時,主表的該記錄不允許被刪除

案例:增加數據

INSERT INTO dept1 VALUES(10,‘NJ‘); --dept主表中添加deptno為10

INSERT INTO emp1 VALUES(1,‘smith‘,20); --emp從表中添加數據,deptno為20

報錯:違反完整約束條件

技術分享

INSERT INTO emp1 VALUES(1,‘smith‘,10); --修改成10,添加成功

INSERT INTO emp1 VALUES(1,‘smith‘,NULL); --或者修改成NULL,添加成功

案例:刪除數據

DELETE FROM dept1 where deptno=10; --10這個值被從表參照,無法刪除

報錯:

技術分享

DELETE FROM emp1 WHERE deptno=10; --必須先刪除從表中的參照值

DELETE FROM dept1 where deptno=10; --才可以刪除主表數據成功

? 外鍵約束對性能的降低

如果在一個頻繁DML操作的表上建立外鍵,每次DML操作都將導致數據庫自動對外鍵所關聯的對應表做檢查,產生開銷,如果已在程序中控制邏輯,這些判斷將增加額外負擔,可以省去。外鍵確定了主從表的先後生成關系,有時會影響業務邏輯。

? 關聯不一定需要外鍵約束

l 保證數據完整性可由程序或觸發器控制

l 簡化開發,維護數據時不用考慮外鍵約束

l 大量數據DML操作時不需考慮外鍵耗費時間

4.5 檢查約束

? 什麽是檢查約束

檢查(Check)約束條件用來強制在字段的每個值都要滿足Check中定義的條件,當定義了Check約束的列新增或修改數據時,數據必須符合Check約束中定義的條件。

? 添加檢查約束

ALTER TABLE emp1

ADD CONSTRAINT emp_id_ck

CHECK(id<10);

添加數據測試

INSERT INTO emp1 VALUES(11,‘jack‘,NULL); --報錯,違反檢查約束條件

技術分享

添加正確數據:

INSERT INTO emp1 VALUES(8,‘jack‘,NULL);

INSERT INTO emp1 VALUES(NULL,‘tom‘,NULL); --可以添加NULL值

註意:如果添加檢查約束的列已有數據並且與添加的CHECK條件不一致,則檢查約束添加會報錯。

視圖、序列、索引、約束