[Oracle]約束(constraint)


(一)約束的概念

在Oracle中,可以通過設置約束來防止無效數據進入表中。Oracle一共有5種約束:

  • 主鍵約束(primary key)
  • 外鍵約束(foreign key)
  • 唯一性約束(unique)
  • 非空約束(not null)
  • 檢查約束(check)

(1)主鍵約束

--主鍵約束可以定義在一列或多列上,值具有唯一性、非空性;

--在一個表上只能定義一個主鍵約束;

--Oracle會自定在主鍵約束的列上創建唯一性索引,可以指定唯一性索引的位置及存儲參數。

(2)外鍵約束

--外鍵約束列的取值來源於參照表(父表)的參照列的值,或者空值;

--定義外鍵約束的列只能參照父表的主鍵約束列和唯一性約束列;

--父表與子表必須在同一個數據庫中。

(3)唯一性約束

--可定義在一列或多列上,列的取值必須唯一;

--如果在某些列上定義了唯一性約束,而沒有定義非空約束,那么在這些列上可以出現多個空值;

--Oracle會自定在主鍵約束的列上創建唯一性索引,可以指定唯一性索引的位置及存儲參數。

(4)非空約束

--只能定義在列上;

--在同一個表中可定義多個非空約束。

(5)檢查約束

--檢查約束用來限制列的取值范圍,其表達式必須引用相應列,表達式的計算結果是一個布爾值;

--一個列可以定義多個檢查約束

(二)列級約束與表級約束

列級約束是對某一個特定列的約束,包含在列的定義中,直接跟在其它定義之后,不需要指出列名。其語法為:

column_definition [CONSTRAINT constraint_name] constraint_type ...

表級約束的定義與列的定義相互獨立,通常用於多列組合的約束,定義表級約束要指出約束的名稱。其語法為:

[CONSTRAINT constraint_name]
constraint_type(column1,[column2...]);

需要注意的是,除了非空約束只能定義列級約束外,其他的均可定義列級/表級約束。

(三)約束的狀態

根據在數據插入、更新時是否對數據進行約束檢查,約束狀態分為激活狀態(ENABLE)和禁用狀態(DISABLE);

根據是否對表中已有數據進行約束檢查,約束狀態分為驗證狀態(VALIDATE)和非驗證狀態(NOVALIDATE);

組合之后,一共有四種約束狀態:

約束狀態

定義

特點

激活驗證狀態
(ENABLE VALIDATE)
激活約束且約束檢查已有數據 對表中已有數據進行檢查,對后續插入、更新的數據也會進行檢查
激活非驗證狀態
(ENABLE NOVALIDATE)
激活約束但是不檢查表中已存在的數據 不檢查目前表中已經存在的數據,但會檢查后續插入、更新的數據
禁用驗證狀態
(DISABLE VALIDATE)
不激活約束但是會去檢查表中已經存在的數據 Oracle不允許進行任何DML(insert/update/delete)操作,因為操作無法得到約束的檢查。表處於只讀模式
禁用非驗證狀態
(DISABLE NOVALIDATE)
不激活驗證且不檢查表中已有的數據 不會對表中數據進行約束檢查,也不會對新插入的數據進行約束檢查

(四)創建約束

(1)創建列級約束

創建列級約束的語法為:

INITIALLYCONSTRAINT constraint_name                           --約束名
[                                                             --選擇5中約束類型
 [NOT] NULL             |
 [UNIQUE]               | 
 [PRIMARY KEY]          |
 [CHECK (condition)]    |
 [REFERENCES [schema.]object[(column)]  [ON DELETE CASCADE | SET NULL]] 
]
[                                                             --是否延遲約束檢查
 [NOT DEFERRABLE]       |
 [DEFERRABLE [INITIALLY IMMEDIATE | DEFERRED]]
]
[ENABLE | DISABLE]                                            --定義約束檢查的類型
[VALIDATE | NOVALIDATE ]  
[USING INDEX index_clause]                                    --約束上索引的定義(主鍵約束與唯一性約束)
[EXCEPTIONS INTO [schema.]table]                              --違反約束的數據的存儲方式

參數說明:

--cinstraint_name:約束名,如果沒有為約束命名,oracle將自動為約束命名,命名樣式為SYS_Cn,n是數據庫對象的唯一編號;

--ON DELETE CASCADE:定義級聯刪除的外鍵約束;

--ON DELETE SET NULL:定義置空刪除的晚間約束;

--NOT DEFERRABLE:約束不可延遲;

--DEFERRABLE:約束可以延遲;

--INITIALLY IMMEDIATE:可延遲約束的立即檢查;

--DEFERRED:可延遲約束的延遲檢查;

--USING INDEX index_clause:創建 唯一性索引的參數設置(存在與主鍵約束、唯一性約束);

--EXCEPTIONS INTO:將違反約束的記錄保存到表中。

(2)定義表級約束

列級約束是定義在列上的,如果需要在多個列上定義約束,則需采用表級約束,表級約束語法如下:

.INITIALLYCONSTRAINT constraint_name                           --約束名
[                                                             --選擇4種約束類型,非空約束只能定義在列上
 [UNIQUE(column1[,column2…])]               | 
 [PRIMARY KEY(column1[,column2…])]          |
 [CHECK (condition)]                         |
 [FOREIGN KEY (column1[,column2…])                                                           --外鍵約束需要指出要約束的列,與列級約束有較大區別
   REFERENCES [schema.]object[(column1[,column2…])] [ON DELETE CASCADE | SET NULL]]        
]
[                                                             --是否延遲約束檢查
 [NOT DEFERRABLE]                           |
 [DEFERRABLE [INITIALLY IMMEDIATE | DEFERRED]]
]
[ENABLE | DISABLE]                                            --定義約束檢查的類型
[VALIDATE | NOVALIDATE ]  
[USING INDEX index_clause]                                    --約束上索引的定義(主鍵約束與唯一性約束)
[EXCEPTIONS INTO [schema.]table]                              --違反約束的數據的存儲方式

(五)添加、修改、重命名、刪除約束

(1)添加約束

語法為:

ALTER TABLE table_name 
ADD [CONSTRAINT constraint_name] constraint_type(column1[,column2...])
[constraint_parameters];

例子1.添加約束

--創建表books
create table books
(
  id       number(6),
  title    varchar2(20),
  isbn     number(20),
  auther   varchar(10),   
  price    number(6,2),
  discribe varchar2(1000),
  pid      number
);
Table created

--創建表publish(用來輔助books創建外鍵約束)
create table publish
(
  pid     number                    primary key,
  name    varchar2(20)
);
Table created

--添加主鍵約束
SQL> alter table books add constraint books_pk primary key (id);
 
Table altered
 
--添加外鍵約束
--需要注意,參照的父表的列需要是主鍵約束列或唯一性約束列
--主要注意,外鍵約束的references帶‘s’
SQL> alter table books add constraint books_fk foreign key (pid) references publish(pid);
 
Table altered
 
--創建唯一性約束
SQL> alter table books add constraint books_unique unique (title);
 
Table altered
 
--創建檢查約束 
SQL> alter table books add constraint books_check check (price > 0);
 
Table altered
 
--需要特別注意,非空約束只能使用modify來創建/刪除 ,不能使用add方式
--1.創建非空約束
SQL> alter table books modify auther not null;
 
Table altered
--2.刪除非空約束
SQL> alter table books modify auther null;
 
Table altered

 

(2)修改約束

可以使用ALTER TABLE … MODIFY修改約束參數,語法為:

ALTER TABLE table_name 
MODIFY [CONSTRAINT constraint_name]  |
[PRIMARY KEY] | [UNIQUE(column1[,column2,...])]  --主鍵約束和唯一性約束可以通過約束類型來修改
[constraint_parameters]

例子2.修改約束

--修改檢查約束,將其置為不檢查表中已有數據
SQL> alter table books modify constraint books_check novalidate;
 
Table altered

--使主鍵約束不可用 
SQL> alter table books modify primary key disable;
 
Table altered

 

(3)重命名約束

可以使用ALTER TABLE … RENAME…來重命名約束,語法為:

ALTER TABLE table_name RENAME CONSTRAINT old_constrain_name TO new_constraint_name;

 

(4)刪除約束

可以使用ALTER TABLE … DROP …來刪除約束,語法為:

ALTER TABLE table_name 
DROP [CONSTRAINT constraint_name]    |
[PRIMARY KEY]   |    [UNIQUE (column1 [,column2,...])]
[CASCADE]  [KEEP | DROP INDEX]

對於刪除約束,需要注意:

1.可以通過約束名稱來刪除約束,對於主鍵約束和唯一性約束,也可以指定約束的類型來刪除約束;

2.如果要刪除的主鍵約束或唯一性約束已經被子表中的外鍵約束引用,需要加CASCADE關鍵字,刪除子表中的外鍵約束;

3.在刪除主鍵約束/唯一性約束時,如果要保留主鍵約束/唯一性約束創建時生成的唯一性索引,則需要使用KEEP關鍵字。

image

                                              圖、books與publish的關系

例子3.刪除主鍵約束

--根據上圖,我們發現books的外鍵引用了publish的主鍵,如果直接刪除,會報錯,只有加了cascade后才能刪除主鍵約束
--刪除主鍵約束后才去看books表,對應的外鍵約束也被刪除了
SQL> alter table publish drop primary key;
 
alter table publish drop primary key
 
ORA-02273: 此唯一/主鍵已被某些外鍵引用
 
SQL> alter table publish drop primary key cascade;
 
Table altered

 

(六)關於外鍵約束的數據刪除方式

假如兩個表之間存在外鍵約束的關系,在父表進行數據刪除時,子表的關聯數據如何處理?Oracle提供了3種方式。

(1)受限刪除【默認】,如果子表中有與父表關聯的記錄存在,則不能刪除數據;

例子4.受限刪除無法刪除已經關聯的數據

create table table_a      --父表
(
  id           number        primary key,
  name         varchar(20)
);

create table table_b1     --子表
(
  id           number         references table_a(id),         --默認是受限刪除
  country      varchar2(30)    
)

SQL> insert into table_a values(1,'lijiaman');
 
1 row inserted
 
SQL> insert into table_b1 values(1,'test');
 
1 row inserted
 
SQL> commit;
 
Commit complete
 
SQL> delete table_a where id = 1;         --子表有關聯數據,導致父表數據也無法刪除
 
delete table_a where id = 1
 
ORA-02292: 違反完整約束條件 (LIJIAMAN.SYS_C0013519) - 已找到子記錄
 
SQL> insert into table_a values(2,'fg');
 
1 row inserted
 
SQL> delete table_a where id = 2;        --子表無關聯數據,父表數據可以刪除
 
1 row deleted
 
SQL> commmit;

 

(2)級聯刪除,刪除父表數據的同時也會將外鍵關聯的子表的記錄刪除;

例子5.級聯刪除外鍵約束會刪除子表關聯數據

SQL> drop table table_b1;        --刪除table_b1
 
Table dropped

create table table_b2             --子表
(
  id           number         references table_a(id) on delete cascade,                          --級聯刪除外鍵約束
  country      varchar2(30)    
);
SQL> insert into table_b2 values(1,'ch');
 
1 row inserted

SQL> select * from table_a ;                                       --兩個表各有1行關聯數據
 
        ID NAME
---------- --------------------
         1 lijiaman
 
SQL> select * from table_b2;
 
        ID COUNTRY
---------- ------------------------------
         1 ch
 
SQL> delete table_a where id = 1;                         --刪除父表數據,子表關聯數據也隨之刪除
 
1 row deleted
 
SQL> commit;
 
Commit complete
 
SQL> select * from table_a;
 
        ID NAME
---------- --------------------
 
SQL> select * from table_b2;
 
        ID COUNTRY
---------- ------------------------------

 

(3)置空刪除,父表數據刪除后,子表中關聯記錄的外鍵約束的列值置為空;

例子6.置空刪除外鍵約束會將子表關聯記錄的外鍵列置為空值

create table table_b3          --子表
(
  id           number         references table_a(id) on delete set null,  --置空刪除外鍵約束
  country      varchar2(30)    
);

SQL> insert into table_a values(1,'adrci');                --往兩個表插入1行關聯數據
 
1 row inserted
 
SQL> insert into table_b3 values(1,'srvctl');
 
1 row inserted

SQL> commit;
 
Commit complete
 
SQL> select * from table_a;
 
        ID NAME
---------- --------------------
         1 adrci
 
SQL> select * from table_b3;
 
        ID COUNTRY
---------- ------------------------------
         1 srvctl
 
SQL> delete table_a where id = 1;                     --刪除id=1的數據,父表整條記錄被刪除,子表僅置空了關聯數據的外鍵列值
 
1 row deleted
 
SQL> select * from table_a;
 
        ID NAME
---------- --------------------
 
SQL> select * from table_b3;
 
        ID COUNTRY
---------- ------------------------------
           srvctl

 

(七)與約束相關的數據字典

視圖名稱 說明
DBA_CONSTRAINTS
ALL_CONSTRAINTS
USER_CONSTRAINTS
包含數據庫中所有約束的定義信息;
包含當前用戶可以看到的所有約束的定義信息;
包含當前用戶擁有的約束的定義信息;
DBA_CONS_COLUMNS
ALL_CONS_COLUMNS
USER_CONS_COLUMNS
記錄了約束列信息,DBA_ 、ALL_ 、USER_的用法與前面相同


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM