Oracle筆記(十) 約束

來源:互聯網
上載者:User

標籤:針對   oid   否則   需要   範圍   enc   而且   表的操作   表結構   

Oracle筆記(十) 約束

表雖然建立完成了,但是表中的資料是否合法並不能有所檢查,而如果要想針對於表中的資料做一些過濾的話,則可以通過約束完成,約束的主要功能是保證表中的資料合法性,按照約束的分類,一共有五種約束:非空約束、唯一約束、主鍵約束、檢查約束、外鍵約束。

一、非空約束(NOT NULL):NK

當資料表中的某個欄位上的內容不希望設定為null的話,則可以使用NOT NULL進行指定。

範例:定義一張資料表

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL
);

因為此時存在了“NOT NULL”約束,所以下面插入兩組資料。

範例:正確的資料

INSERT INTO member(mid,name) VALUES(1,‘張三‘);
INSERT INTO member(mid,name) VALUES(null,‘李四‘);
INSERT INTO member(name) VALUES(‘王五‘);

範例:插入錯誤的資料

INSERT INTO member(mid,name) VALUES(9,null);
INSERT INTO member(mid) VALUES(10);

此時了出現的錯誤提示:

ORA-01400: 無法將 NULL 插入 ("SCOTT"."MEMBER"."NAME")

本程式之中,直接表示出了“使用者”.“表名稱”.“欄位”出現了錯誤。

二、唯一約束(UNIQUE):UK

唯一約束指的是每一列上的資料是不允許重複的,例如:email地址每個使用者肯定是不重複的,那麼就使用唯一約束完成。

 

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    email VARCHAR2(50) UNIQUE
);

 

範例:插入正確的資料

INSERT INTO member(mid,name,email) VALUES(1,‘張三‘,‘[email protected]‘);
INSERT INTO member(mid,name,email) VALUES(2,‘李四‘,null);

範例:插入錯誤的資料 —— 重複資料

INSERT INTO member(mid,name,email) VALUES(3,‘王五‘,‘[email protected]‘);

此時會出現如下的錯誤提示:

ORA-00001: 違反唯一約束條件 (SCOTT.SYS_C005272)

可是這個時候的錯誤提示與之前的非空約束相比並不完善,因為現在只是給出了一個代號而已,這是因為在定義約束的時候沒有為約束指定一個名字,所以由系統預設分配了,而且約束的名字建議的格式“約束類型_欄位”,例如:“UK_email”,指定約束名稱使用CONSTRAINT完成。

 

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    email VARCHAR2(50),
    CONSTRAINT UK_email UNIQUE(email)
);

 

以後再次增加錯誤資料時,提示資訊如下:

ORA-00001: 違反唯一約束條件 (SCOTT.UK_EMAIL)

已經可以很明確的提示使用者錯誤的位置。

三、主鍵約束(Primary Key):PK

主鍵約束 = 非空約束 + 唯一約束,在之前設定唯一的約束的時候發現可以設定為null,而如果現在使用了主鍵約束之後則不可為空,而且主鍵一般作為資料的唯一的一個標記出現,例如:人員的ID。

範例:建立主鍵約束

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER PRIMARY KEY,
    name VARCHAR2(50) NOT NULL
);

範例:增加正確的資料

INSERT INTO member(mid,name) VALUES(1,‘張三‘);

範例:錯誤的資料 —— 主鍵設定為null

INSERT INTO member(mid,name) VALUES(null,‘張三‘);

錯誤資訊,與之前的非空約束的錯誤資訊提示是一樣的;

ORA-01400: 無法將 NULL 插入 ("SCOTT"."MEMBER"."MID")

範例:錯誤的資料 —— 主鍵重複

INSERT INTO member(mid,name) VALUES(1,‘張三‘);

錯誤資訊,這個錯誤資訊就是唯一約束的錯誤資訊,但是資訊不明確,因為沒起名字。

ORA-00001: 違反唯一約束條件 (SCOTT.SYS_C005276)

所以為了約束的使用方便,下面為主鍵約束起一個名字。

 

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid)
);

 

此時,重複插入資料,則錯誤資訊如下:

ORA-00001: 違反唯一約束條件 (SCOTT.PK_MID)

從正常的開發角度而言,一張表一般都只設定一個主鍵,但是從SQL文法的規定而言,一張表卻可以設定多個主鍵,而此種做法稱為複合主鍵,例如:參考如下代碼:

 

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid,name)
);

 

在複合主鍵的使用之中,只有兩個欄位的內容都一樣的情況下,才被稱為重複資料。

範例:插入正確的資料

INSERT INTO member(mid,name) VALUES(1,‘張三‘);
INSERT INTO member(mid,name) VALUES(1,‘李四‘);
INSERT INTO member(mid,name) VALUES(2,‘李四‘);

範例:插入錯誤的資料

INSERT INTO member(mid,name) VALUES(1,‘張三‘);

錯誤資訊:

ORA-00001: 違反唯一約束條件 (SCOTT.PK_MID)

但是從開發的實際角度而言,一般都不使用複合主鍵,所以這個知識只是作為其相關的內容做一個介紹。只要是資料表,永遠都只設定一個主鍵。

四、檢查約束(Check):CK

檢查約束指的是為表中的資料增加一些過濾條件,例如:

  • 設定年齡的時候範圍是:0~200;
  • 設定性別的時候應該是:男、女;

範例:設定檢查約束

 

DROP TABLE member PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    sex VARCHAR2(10) NOT NULL,
    age NUMBER(3),
    CONSTRAINT pk_mid PRIMARY KEY(mid),
    CONSTRAINT ck_sex CHECK(sex IN(‘男‘,‘女‘)),
    CONSTRAINT ck_age CHECK(age BETWEEN 0 AND 200)
);

 

範例:增加正確的資料

INSERT INTO member(mid,name,sex,age) VALUES(1,‘張三‘,‘男‘,‘26‘);

範例:增加錯誤的性別 —— ORA-02290: 違反檢查約束條件 (SCOTT.CK_SEX)

INSERT INTO member(mid,name,sex,age) VALUES(2,‘李四‘,‘非‘,‘26‘);

範例:增加錯誤的年齡 —— ORA-02290: 違反檢查約束條件 (SCOTT.CK_AGE)

INSERT INTO member(mid,name,sex,age) VALUES(2,‘李四‘,‘女‘,‘260‘);

檢查的操作就是對輸入的資料進行一個過濾。

五、主-外鍵約束

之前的四種約束都是在單張表中進行的,而主-外鍵約束是在兩張表中進行的,這兩張表是存在父子關係的,即:子表中某個欄位的取值範圍由父表所決定。

例如,現在要求表示出一種關係,每一個人有多本書,應該定義兩張資料表:member(主)、book(子);

 

DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
    bid NUMBER,
    title VARCHAR2(50) NOT NULL,
    mid NUMBER,
    CONSTRAINT pk_bid PRIMARY KEY(bid)
);

 

此時只是根據要求建立了兩張獨立的資料表,那麼下面插入幾條資料:

 

INSERT INTO member(mid,name) VALUES(1,‘張三‘);
INSERT INTO member(mid,name) VALUES(2,‘李四‘);
INSERT INTO book(bid,title,mid) VALUES(101,‘Java開發‘,1);
INSERT INTO book(bid,title,mid) VALUES(102,‘Java Web開發‘,2);
INSERT INTO book(bid,title,mid) VALUES(103,‘EJB開發‘,2);
INSERT INTO book(bid,title,mid) VALUES(105,‘Android開發‘,1);
INSERT INTO book(bid,title,mid) VALUES(107,‘AJAX開發‘,1);

 

要想驗證這個資料是否有意義,最簡單的做法,就是寫兩個查詢。

範例:統計每個人員擁有書的數量

SELECT m.mid,m.name,COUNT(b.bid)
FROM member m,book b
WHERE m.mid=b.mid
GROUP BY m.mid,m.name;

範例:查詢出每個人員的編號,姓名,擁有書的名稱

SELECT m.mid,m.name,b.title
FROM member m,book b
WHERE m.mid=b.mid;

即,現在的book.mid欄位應該是與member.mid欄位相關聯的,但是由於本程式沒有設定約束,所以,現在以下的資料也是可以增加的:

INSERT INTO book(bid,title,mid) VALUES(108,‘PhotoShop使用手冊‘,3);
INSERT INTO book(bid,title,mid) VALUES(109,‘FLEX開發手冊‘,8);

現在增加了兩條新的記錄,而且記錄可以儲存在資料表之中,但是這兩條記錄沒有意義,因為member.mid欄位的內容沒有3和8,而要想解決這個問題就必須依靠外鍵約束來解決。

讓book.mid的欄位的取值由member.mid所決定,如果member.mid的資料真實存在,則表示可以更新。

 

DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
    bid NUMBER,
    title VARCHAR2(50) NOT NULL,
    mid NUMBER,
    CONSTRAINT pk_bid PRIMARY KEY(bid),
    CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid)
);

 

此時,只是增加了一個約束,這樣一來如果輸入的資料有錯誤,則會出現如下的提示:

ORA-02291: 違反完整約束條件 (SCOTT.FK_MID) - 未找到父項關鍵字

因為member.mid沒有指定的資料,所以book.mid如果資料有錯誤,則無法執行更新操作。

使用外鍵的最大好處是控制了子表中某些資料的取值範圍,但是同樣帶來了不少的問題;

1、  刪除資料的時候,如果主表中的資料有對應的子表資料,則無法刪除;

範例:刪除member表中mid為1的資料

DELETE FROM member WHERE mid=1;

錯誤提示資訊:“ORA-02292: 違反完整約束條件 (SCOTT.FK_MID) - 已找到子記錄”。

此時,只能先刪除子表記錄,之後再刪除父表記錄:

DELETE FROM book WHERE mid=1;
DELETE FROM member WHERE mid=1;

但是這種操作明顯不方便,如果說現在希望主表資料刪除之後,子表中對應的資料也可以刪除的話,則可以在建立外鍵約束的時候指定一個串聯刪除的功能,修改資料庫建立指令碼:

 

DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
    bid NUMBER,
    title VARCHAR2(50) NOT NULL,
    mid NUMBER,
    CONSTRAINT pk_bid PRIMARY KEY(bid),
    CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE
);

 

此時由於存在串聯刪除的操作,所以主表中的資料刪除之後,對應的子表中的資料也都會被同時刪除。

2、  刪除資料的時候,讓子表中對應的資料設定為null

當主表中的資料刪除之後,對應的子表中的資料相關項目也希望將其設定為null,而不是刪除,此時,可以繼續修改資料表的建立指令碼:

 

DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
    bid NUMBER,
    title VARCHAR2(50) NOT NULL,
    mid NUMBER,
    CONSTRAINT pk_bid PRIMARY KEY(bid),
    CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE SET NULL
);
INSERT INTO member(mid,name) VALUES(1,‘張三‘);
INSERT INTO member(mid,name) VALUES(2,‘李四‘);
INSERT INTO book(bid,title,mid) VALUES(101,‘Java開發‘,1);
INSERT INTO book(bid,title,mid) VALUES(102,‘Java Web開發‘,2);
INSERT INTO book(bid,title,mid) VALUES(103,‘EJB開發‘,2);
INSERT INTO book(bid,title,mid) VALUES(105,‘Android開發‘,1);
INSERT INTO book(bid,title,mid) VALUES(107,‘AJAX開發‘,1);

 

3、  刪除父表之前必須首先先刪除對應的子表,否則無法刪除

DROP TABLE book PURGE;
DROP TABLE member PURGE;

但是這樣做明顯很麻煩,因為對於一個未知的資料庫,如果要按照此類方式進行,則必須首Crowdsourced Security Testing道其父子關係,所以在Oracle之中專門提供了一個強制性刪除表的操作,即:不再關心約束,在刪除的時候寫上一句“CASCADE CONSTRAINT”。

DROP TABLE member CASCADE CONSTRAINT PURGE;
DROP TABLE book CASCADE CONSTRAINT PURGE;

此時,不關心子表是否存在,直接強制性的刪除父表。

合理做法:在以後進行資料表刪除的時候,最好是先刪除子表,之後再刪除父表。

六、修改約束

約束本身也屬於資料庫物件,那麼也肯定可以進行修改操作,而且只要是修改都使用ALTER指令,約束的修改主要指的是以下兩種操作:

  • 為表增加約束:
  • 刪除表中的約束:
ALTER TABLE 表名稱 ADD CONSTRAINT 約束名稱 約束類型(欄位);
ALTER TABLE 表名稱 DROP CONSTRAINT 約束名稱;

可以發現,如果要維護約束,肯定需要一個正確的名字才可以,可是在這五種約束之中,非空約束作為一個特殊的約束無法操作,現在有如下一張資料表:

 

DROP TABLE member CASCADE CONSTRAINT PURGE;
CREATE TABLE member(
    mid NUMBER,
    name VARCHAR2(50) NOT NULL,
    age NUMBER(3)
);

 

範例:為表中增加主鍵約束

ALTER TABLE member ADD CONSTRAINT pk_mid PRIMARY KEY(mid);

增加資料:

INSERT INTO member(mid,name,age) VALUES(1,‘張三‘,30);
INSERT INTO member(mid,name,age) VALUES(2,‘李四‘,300);

現在在member表中已經存在了年齡上的非法資料,所以下面為member表增加檢查約束:

ALTER TABLE member ADD CONSTRAINT ck_age CHECK(age BETWEEN 0 AND 250);

這個時候在表中已經存在了違反約束的資料,所以肯定無法增加。

範例:刪除member表中的mid上的主鍵約束

ALTER TABLE member DROP CONSTRAINT pk_mid;

可是,跟表結構一樣,約束最好也不要修改,而且記住,表建立的同時一定要將約束定義好,以後的使用之中建議就不要去改變了。

七、查詢約束

在Oracle之中所有的對象都會在資料字典之中儲存,而約束也是一樣的,所以如果要想知道有哪些約束,可以直接查詢“user_constraints”資料字典:

SELECT owner,constraint_name,table_name FROM user_constraints;

但是這個查詢出來的約束只是告訴了你名字,而並沒有告訴在哪個欄位上有此約束,所以此時可以查看另外一張資料字典表“user_cons_columns”;

COL owner FOR A15;
COL constraint_name FOR A15;
COL table_name FOR A15;
COL column_name FOR A15;
SELECT owner,constraint_name,table_name,column_name FROM user_cons_columns;

這些維護工作大部分由專門的DBA負責。

Oracle筆記(十) 約束

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.