国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【postgresql 基礎(chǔ)入門】表的約束(二) 唯一unique、非空not null、check、exclusion約束,原理機(jī)制以及多列組合約束

這篇具有很好參考價(jià)值的文章主要介紹了【postgresql 基礎(chǔ)入門】表的約束(二) 唯一unique、非空not null、check、exclusion約束,原理機(jī)制以及多列組合約束。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

表的約束(二)

?專欄內(nèi)容

  • postgresql內(nèi)核源碼分析
  • 手寫數(shù)據(jù)庫toadb
  • 并發(fā)編程

個(gè)人主頁:我的主頁
管理社區(qū):開源數(shù)據(jù)庫
座右銘:天行健,君子以自強(qiáng)不息;地勢坤,君子以厚德載物.

一、概述


在數(shù)據(jù)庫中,數(shù)據(jù)類型可以限制數(shù)據(jù)存儲(chǔ)的大小,也能在一定程度上限制存儲(chǔ)的數(shù)據(jù)種類,但是對于數(shù)據(jù)庫應(yīng)用來講,它太寬泛了,比如有些表示人名的字段,就不能為空,貨物數(shù)量的字段,不能為負(fù)值,這與實(shí)際生活符合,而數(shù)據(jù)類型并不能做這些約束,這就需要數(shù)據(jù)庫提供一套更貼近應(yīng)用,或者說與現(xiàn)實(shí)世界更符合的規(guī)則,來約束數(shù)據(jù)的有效性。

約束的定義

數(shù)據(jù)庫的約束是一種規(guī)則,用于限制或規(guī)范數(shù)據(jù)庫中的數(shù)據(jù),確保數(shù)據(jù)的完整性和一致性。這些約束可以定義在表級別或列級別,處理機(jī)制是一致的。約束不占用任何數(shù)據(jù)庫空間,而是存在于數(shù)據(jù)字典中,并在執(zhí)行SQL期間使用。用戶可以指明約束是啟用的還是禁用的,當(dāng)約束啟用時(shí),它增強(qiáng)了數(shù)據(jù)的完整性。

約束的分類

postgresql數(shù)據(jù)庫中的約束類型主要包括以下幾種:

  1. 主鍵約束(Primary Key):主鍵約束相當(dāng)于唯一約束和非空約束的組合。它確保表中的每一行數(shù)據(jù)都有一個(gè)唯一標(biāo)識符,不允許重復(fù),也不允許出現(xiàn)空值。每個(gè)表最多只允許一個(gè)主鍵。當(dāng)創(chuàng)建主鍵約束時(shí),系統(tǒng)默認(rèn)會(huì)在所在的列或列組合上建立對應(yīng)的唯一索引。
  2. 外鍵約束(Foreign Key):外鍵約束用于保證一個(gè)或兩個(gè)表之間的參照完整性。它構(gòu)建于一個(gè)表的兩個(gè)字段或是兩個(gè)表的兩個(gè)字段之間的參照關(guān)系。
  3. 唯一約束(Unique):唯一約束要求指定的表列或列組合的值不能重復(fù),保證數(shù)據(jù)的唯一性。同一個(gè)表可以有多個(gè)唯一約束。在創(chuàng)建唯一約束時(shí),如果不給唯一約束名稱,就默認(rèn)和列名相同。與主鍵約束不同,唯一約束允許空值的存在,但只能出現(xiàn)一個(gè)空值。
  4. 非空約束(NOT NULL):非空約束用于確保當(dāng)前列的值不為空值。它只能出現(xiàn)在表對象的列上。
  5. 檢查約束(Check):檢查約束會(huì)判斷指定的條件是否為true,當(dāng)為true時(shí)符合約束。
  6. 排除約束(Exclude): 在排除約束指定的表達(dá)式返回false或null時(shí),才符合約束。

這些約束在數(shù)據(jù)庫設(shè)計(jì)中起著至關(guān)重要的作用,它們有助于維護(hù)數(shù)據(jù)的準(zhǔn)確性和一致性,防止無效數(shù)據(jù)的插入和更新。

二、唯一約束


唯一約束來限制當(dāng)前列中不能出現(xiàn)重復(fù)值,在postgresql中,創(chuàng)建唯一約束時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè)唯一性索引在對應(yīng)的列上,通過唯一性索引來提高檢查重復(fù)值的效率。

添加唯一約束的SQL語法如下:

CREATE TABLE table_name (
 ...
  column1 data_type UNIQUE,
  ...
);

也可以在定義的尾部,給多個(gè)列為一組添加唯一約束

CREATE TABLE table_name (
 ...
  column1 data_type ,
  column2 data_type ,
  ...
  UNIQUE (column1, column2)
);

當(dāng)表已經(jīng)創(chuàng)建時(shí),可以通過修改表的方式來添加,但是這里與其它不同之處是,有兩種方式,一種是直接添加唯一性約束,當(dāng)然會(huì)自動(dòng)創(chuàng)建唯一性索引;另一種是先創(chuàng)建唯一性索引,再將索引以唯一性約束的形式應(yīng)用到表上。

我們這里演示一下第一種方式

下面演示一下,創(chuàng)建一張表。

postgres=# drop table products ;
DROP TABLE
postgres=# create table products(product_id int primary key,product_name varchar not null,price double precision);
CREATE TABLE
postgres=# \d products
                      Table "test1.products"
    Column    |       Type        | Collation | Nullable | Default
--------------+-------------------+-----------+----------+---------
 product_id   | integer           |           | not null |
 product_name | character varying |           | not null |
 price        | double precision  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (product_id)

創(chuàng)建了一張products表,然后再通過修改表定義的方式添加唯一性索引。

postgres=# alter table products add constraint products_unique_contraint unique (price);
ALTER TABLE
postgres=# \d products
                      Table "test1.products"
    Column    |       Type        | Collation | Nullable | Default
--------------+-------------------+-----------+----------+---------
 product_id   | integer           |           | not null |
 product_name | character varying |           | not null |
 price        | double precision  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (product_id)
    "products_unique_contraint" UNIQUE CONSTRAINT, btree (price)

可以看到添加成功,索束的名稱由數(shù)據(jù)庫自動(dòng)生成。

插入數(shù)據(jù)試驗(yàn)一下。

postgres=# insert into products values(1,'a',1);
INSERT 0 1
postgres=# insert into products values(2,'b',1);
ERROR:  duplicate key value violates unique constraint "products_unique_contraint"
DETAIL:  Key (price)=(1) already exists.

插入兩條數(shù)據(jù),在第二條數(shù)據(jù)中,字段price與第一條數(shù)據(jù)相同,可以看到違反了唯一性約束,報(bào)錯(cuò)插入不成功。

postgres=# insert into products(product_id,product_name) values(2,'b');
INSERT 0 1
postgres=# insert into products(product_id,product_name) values(3,'c');
INSERT 0 1
postgres=# select * from products ;
 product_id | product_name | price
------------+--------------+-------
          1 | a            |     1
          2 | b            |
          3 | c            |
(3 rows)

再插入兩條數(shù)據(jù),而字段price的值并沒有賦值,也就是null值,可以看到都插入成功了,這就是null含義,未知,它與任何值都不相等。

第二種方式式的SQL語法示例如下:

  • 先要?jiǎng)?chuàng)建一個(gè)唯一性索引
CREATE UNIQUE INDEX  unique_index_name 
ON table_name (column1,...);
  • 然后將表的列應(yīng)用此唯一性索引
ALTER TABLE table_name 
ADD CONSTRAINT unique_constraint_name 
UNIQUE USING INDEX unique_index_name;

這里涉及到三個(gè)名字,第一個(gè)是表名,第二個(gè)是唯一性約束的名稱,第三個(gè)是前一步創(chuàng)建的唯一性索引的名稱。

在第一步創(chuàng)建完索引后,其實(shí)通過索引已經(jīng)實(shí)現(xiàn)不能有重復(fù)值出現(xiàn),但是查看表定義時(shí),并不是以約束的形式出現(xiàn),直到第二步添加約束后,可以看到表上出現(xiàn)了唯一性約束。

特別說明的是,null是一個(gè)特殊性,null與null并不相等,在有唯一性約束的列上可能出現(xiàn)多行數(shù)據(jù)都是null的情況,如果要改變這種默認(rèn)行為,可以在unique關(guān)鍵字后面再追加NULLS NOT DISTINCT。

增加了NULLS NOT DISTINCT關(guān)鍵字后,null值也不允許重復(fù)了,下面來演示一下。

postgres=# drop table products ;
DROP TABLE
postgres=# create table products(product_id int primary key,product_name varchar not null,price double precision unique NULLS NOT DISTINCT);
CREATE TABLE

先刪除表,重新創(chuàng)建一下,仍然price字段創(chuàng)建唯一性約束,同時(shí)增加nulls not distinct字段。

postgres=# insert into products(product_id,product_name) values(2,'b');
INSERT 0 1
postgres=# insert into products(product_id,product_name) values(3,'c');
ERROR:  duplicate key value violates unique constraint "products_price_key"
DETAIL:  Key (price)=(null) already exists.

然后同樣插入兩條price字段為null的數(shù)據(jù),可以看到確實(shí)null值也不能重復(fù)了。

三、非空約束


NULL在數(shù)據(jù)庫中是一個(gè)特殊值,表示不知道、沒有任何信息,它不等于任何值,包括它自己。而在我們現(xiàn)實(shí)生活中,有些信息是必須要存在,比如商品的編號或名稱,如何不存在,那就不能唯一標(biāo)識這種商品,也就意味著這種商品不存在。

為了約束這種情況的發(fā)生,就增加一種not null的約束,它的SQL語法如下:

CREATE TABLE table_name(
   ...
   column1 data_type NOT NULL,
   ...
);

在某一列定義后加not null關(guān)鍵字。

當(dāng)然它也可以通過修改表的方式來添加,SQL語法如下:

ALTER TABLE table_name
ALTER COLUMN column1 SET NOT NULL;

定義了主鍵,同時(shí)在product_name列上定義了not null約束。

查看表的定義信息,

postgres=# \d products
                      Table "test1.products"
    Column    |       Type        | Collation | Nullable | Default
--------------+-------------------+-----------+----------+---------
 product_id   | integer           |           | not null |
 product_name | character varying |           | not null |
 price        | double precision  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (product_id)

可以看到在Nullable是否為空列中,有兩個(gè)字段都是not null約束,主鍵默認(rèn)是帶有非空約束的。

四、檢查約束


check檢查約束,通過一個(gè)結(jié)果為布爾值的表達(dá)式來檢查字段數(shù)據(jù)的有效性,只有表達(dá)式結(jié)果為true時(shí)才能被insert或update,這一約束保證了數(shù)據(jù)的實(shí)體完整性。

check約束可以在創(chuàng)建表時(shí)添加,SQL語法形式如下:

可以在列的定義后面追加check約束,它表明只針對本列的約束

CREATE TABLE table_name(
   column1 datatype CHECK(condition_expression1),
   column2 datatype CONSTRAINT check_constraint_name CHECK(condition_expression2),
   ...
);

其中可以用關(guān)鍵字CONSTRAINT來指定一個(gè)約束的名稱,如果不指定名稱,數(shù)據(jù)庫會(huì)自動(dòng)生成一個(gè)名稱。

也可以將check約束單獨(dú)放為一行定義,它可能會(huì)涉及多行,盡量與它關(guān)聯(lián)的行靠近定義。

CREATE TABLE table_name(
   column1 datatype,
   ...,
   column2 datatype,
   CONSTRAINT check_constraint_name CHECK(condition_expression1),
   ...,
   column3 datatype,
   CHECK(condition_expression2)
   ...
);

也可以通過修改表的定義來添加,

ALTER TABLE table_name
ADD CONSTRAINT check_constraint_name CHECK (condition_expression1);

下面我們來演示一下check約束,

postgres=# drop table products ;
DROP TABLE
postgres=# CREATE TABLE products (
    product_no integer,
    name text,
    price numeric,
    CHECK (price > 0),
    discounted_price numeric,
    CHECK (discounted_price > 0),
    CONSTRAINT valid_discount CHECK (price > discounted_price)
);
CREATE TABLE

price,discounted_price檢查,它們都需要大于0,同時(shí)打折價(jià)discounted_price必須要小于原價(jià)price,不能虧本吧。

注意,check約束盡量是簡單的表達(dá)式,它不能區(qū)分update中修改前與修改后的值,另外也不包括自定義的function在表達(dá)式中,因?yàn)樗闹凳遣淮_定的。

五、排除約束


exclusion約束,與check約束正好相反,它也是指定一個(gè)表達(dá)式和操作符,如果表達(dá)式與操作符結(jié)果返回false或null時(shí),就可以插入或更新。

exclusion約束是通過在指定列或幾列上創(chuàng)建gin索引來實(shí)現(xiàn)快速比較。

它主要用途在集合或圖形方面,表達(dá)邏輯是兩行數(shù)據(jù)表示的集合或圖形不包含,不相交。

下面來簡單演示一個(gè)例子。

postgres=# CREATE TABLE circles (
    c circle,
    EXCLUDE USING gist (c WITH &&)
);
CREATE TABLE

創(chuàng)建一個(gè)記錄圓形的表,增加約束限制,兩個(gè)圓不能有重疊,也就是在c列上指定操作符為&&,在檢查時(shí)會(huì)執(zhí)行運(yùn)算c1 && c2,如果重疊返回值就為true,會(huì)違返exclusion約束。

postgres=# insert into circles values('(0,1),5');
INSERT 0 1
postgres=# select * from circles ;
     c
-----------
 <(0,1),5>
(1 row)

postgres=# insert into circles values('(0,2),5');
ERROR:  conflicting key value violates exclusion constraint "circles_c_excl"
DETAIL:  Key (c)=(<(0,2),5>) conflicts with existing key (c)=(<(0,1),5>).

postgres=# insert into circles values('(0,12),5');
INSERT 0 1

圓的輸入是圓心坐標(biāo) + 半徑, 插入一條以(0,1)圓心,半徑為5的圓的數(shù)據(jù),再次插入以(0,2)為圓心半徑為5的圓時(shí),它們會(huì)重疊,違反排除約束。

而我們再次插入一條以(0,12)為圓心半徑為5的圓時(shí),沒有與它重疊的圖形,可以插入成功。

六、總結(jié)


本章節(jié)介紹了在postgresql中的幾種約束,unique唯一性約束,not null非空約束,check條件檢查約束,還有exclusion排除約束,通過原理介紹,并在一些案例中進(jìn)行實(shí)踐來加深理解,當(dāng)然它們都可以組合使用,有效利用約束可以使我們的數(shù)據(jù)更加有效和完整。

七、結(jié)尾


非常感謝大家的支持,在瀏覽的同時(shí)別忘了留下您寶貴的評論,如果覺得值得鼓勵(lì),請點(diǎn)贊,收藏,我會(huì)更加努力!

作者郵箱:study@senllang.onaliyun.com
如有錯(cuò)誤或者疏漏歡迎指出,互相學(xué)習(xí)。

注:未經(jīng)同意,不得轉(zhuǎn)載!文章來源地址http://www.zghlxwxcb.cn/news/detail-844276.html

到了這里,關(guān)于【postgresql 基礎(chǔ)入門】表的約束(二) 唯一unique、非空not null、check、exclusion約束,原理機(jī)制以及多列組合約束的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包