SQL——完整性約束

完整性約束的作用在于保證授權(quán)用戶對數(shù)據(jù)庫所做的修改不會破壞數(shù)據(jù)的一致性?;蛘哒f,防止的是對數(shù)據(jù)的意外破壞。

單個關(guān)系的約束

一般而言,約束是在創(chuàng)建表的時候生成,例如我們在之前的《SQL——SQL數(shù)據(jù)定義》
有這樣的例子

CREATE TABLE department(
  dept_name VARCHAR(20),
  building VARCHAR(15),
  budget NUMERIC(12,2),
  PRIMARY KEY (dept_name)
);

完整性約束有三種:

  • not null
  • unique
  • check(<P>)

not null 約束

not null 約束是使得被約束的屬性的值不能 (禁止)為空值。例如,我們要將dept_name設(shè)置為非空:

dept_name VARCHAR(20) NOT NULL

不過在這里dept_name也可以不加not null,因為這里not null 是主碼,是默認不能為空。

unique 約束

通式:

unique<A1,A2,...An>

unique聲明<A1,A2,...An>是一個候選碼,即在關(guān)系中沒有兩個元祖在所有這些列出的屬性上取值相同,但可以同時為空。因為空值不等于任何值。

示例:

unique(building)
#或者
unique(building,budget)
#或者(該方法只適用于約束單個屬性)
building unique

check子句

check子句自定一個謂詞P,關(guān)系中的每一個元組都必須滿足謂詞P,例如:

#保證department中的budget>0,那么可以這樣寫:
CREATE TABLE department(
  dept_name VARCHAR(20),
  building VARCHAR(15),
  budget NUMERIC(12,2),
  PRIMARY KEY (dept_name),
  CHECK(budget>0)
);
#保證section表的semester是集合中的字符串
check(semester in{'fall','spring','winter','summer'})

參照完整性

我們常常希望保證在一個關(guān)系中給定屬性集上的取值也在另一關(guān)系的特定屬性集的取值中出現(xiàn),這種情況稱為參照完整性

我們令關(guān)系r1和關(guān)系r2的屬性集為R1和R2,主碼分別為K1和K2。如果要求對r2中任意元組t2,均存在r1中元組t1使得t.K1=t2.α,我們稱R2的子集α為參照關(guān)系r1中K1的外碼。

這種要求稱為參照完整性約束或者子集依賴。

SQL中 外碼參照的是被參照表中的主碼屬性,可用reference指定,指定的屬性列表必須被聲明為被參照關(guān)系的候選碼,即被primary或者unique約束的屬性。
例如

#dept_name是外碼,department是被參照關(guān)系,department中dept_name為主碼
dept_name varchar(20)reference department
#或者寫成下面的形式
dept_name varchar(20),
foreign key(dept_name) reference department(dept_name)

復(fù)雜check條件和斷言

復(fù)雜check條件

SQL標準定義,check子句中的謂詞可以是包含子查詢的任意謂詞。如果一個數(shù)據(jù)庫實現(xiàn)支持在check子句中出現(xiàn)子查詢(如果不支持就不能這樣使用),我們就可以在關(guān)系section上聲明如下所示的參照完整性約束:

check (time_slot_id in(select time_slot_id from time_slot))

像這樣的復(fù)雜check條件在我們希望確保數(shù)據(jù)完整性的時候是很有用的,但是其檢測開銷可能會很大。例如,check子句中的謂詞不僅需要在section關(guān)系發(fā)生更新時計算,而且也可能在time_slot關(guān)系發(fā)生更新時檢測,因為time_slot在子查詢中被引用了。

斷言

一個斷言(assertion)就是謂詞,它表達了我們希望數(shù)據(jù)庫總能滿足的一個條件。域約束和參照完整性約束是斷言的特殊形式。前面幾種約束(像not null等),有些約束不能僅用這幾種約束來表達。例如:

  • 對于student關(guān)系中的每個元組,它在屬性tol_cred上的取值必須等于該學(xué)生所成功修完課程的學(xué)分總和。

  • 每位教師不能在同一學(xué)期的同一時間段在兩個不同的教室授課。
    這是需用斷言來實現(xiàn),斷言為如下的形式

create assertion <assertion-name> check <predicate>;

SQL不提供“for all X,P(X)”,即不提供對于任意x,使得P(x)的結(jié)構(gòu),那么我們只能通過等價的“not exists X such that not P(x)”,即不存在X,使得非P(x)。對于第一個例子可以這樣實現(xiàn):

CREATE ASSERTION credit_earned_constraint CHECK (
  NOT exists(
      SELECT id
      FROM student
      WHERE tol_cred<>(
        SELECT sum(credits)
        FROM takes NATURAL JOIN course
        WHERE student.id = takes.id
        AND grade IS NOT NULL AND grade>=60
      )
  )
);

當創(chuàng)建斷言時,系統(tǒng)要檢測其有效性。如果斷言有效,則今后只有不破壞斷言的數(shù)據(jù)庫修改才被允許。如果斷言較復(fù)雜,則檢測會帶來相當大的開銷,應(yīng)該注意。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 2017/3/14 RDBMS:關(guān)系型數(shù)據(jù)庫管理系統(tǒng) 關(guān)系模型獨立于語言 SQL有幾種不同類型的語言:數(shù)據(jù)定義語言...
    ancherl閱讀 1,804評論 0 6
  • 入門心法:要練此功,先廢其功。(先忘記已學(xué)的其他語言,用T-SQL來思考。)所需代碼:https://github...
    張中華閱讀 1,831評論 2 32
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,688評論 19 139
  • 提示:文章只是用來記錄本人自己在學(xué)習(xí)過程中所遇到的一些問題的解決方案,如果有什么意見可以留言提出來,不喜勿噴哦! ...
    KorsJJ閱讀 1,484評論 0 3
  • 某天突然發(fā)生的某個場景讓人覺得似曾相識,我是不是在xxx中見過?我是不是經(jīng)歷過?我是不是說過?無數(shù)次腦海里會冒出很...
    isnowdone閱讀 431評論 0 1

友情鏈接更多精彩內(nèi)容