SQL 表的完整性--约束

--表的完整性

--缺省值
--若表字段未明确声明缺省值,则默认缺省值为NULL
--缺省值在表定义中类型后定义的

CREATE TABLE Products (
    product_no integer,
    name text,
    price numeric DEFAULT 9.99
);

DROP TABLE Products;
--序列对象暂时还未创建
/*--nextval()从一个序列对象提供后继的值
CREATE TABLE Products (
    product_no integer DEFAULT nextval('Products_product_no_seq'),
    name text,
    price numeric 
);*/
--也可以这样写

CREATE TABLE Products (
    products_no SERIAL
);
DROP TABLE Products;
--2.约束
--表中数据必须是表达式为真,否则会引发错误
--2.1:检查约束

CREATE TABLE Products (
    product_no SERIAL,
    name text,
    price numeric CHECK(price > 0)
);
DROP TABLE Products;
--可以给检查约束设置名字
CREATE TABLE Products (
    product__no SERIAL,
    name text,
    price numeric CONSTRAINT positive_price CHECK(price > 0)
);
DROP TABLE Products;
--2.1.2 表约束 当表中某约束需要综合引用表中各字段,则需要表约束
CREATE TABLE Products (
    product_no SERIAL,
    name text,
    price numeric CONSTRAINT positive_price CHECK(price > 0),
    discounted_price numeric CONSTRAINT positive_discounted_price CHECK(discounted_price > 0),
    CONSTRAINT price_gt_dicounted CHECK(price > discounted_price)
);
--CONSTRAINT price_gt_discounted引用了其他定义字段且不再字段定义后面,是表约束
DROP TABLE Products;
--字段约束和表约束即检查约束若无明确指定并不隔绝表达式返回NULL的值,如果需要非空,则需要添加非空约束
--2.2  非空约束
--再字段类型定义后以NOT NULL指定
--非空约束可以看成字段约束的一种等同于 CHECK(column_name IS NOT NULL)但非空约束效率一般更高
CREATE TABLE Products (
    product_no  integer NOT NULL,
    name text  NOT NULL,
    price numeric NOT NULL
);
DROP TABLE Products;
--2.3  唯一约束
--单一字段唯一 写成字段约束
CREATE TABLE Products (
    product_no integer,
    name text UNIQUE,
    price numeric
);

DROP TABLE Products;
--单一字段唯一 写成表约束

CREATE TABLE Products (
    product_no integer,
    name text,
    price numeric,
    UNIQUE(name)
);
DROP TABLE Products;
--组合字段唯一  必须表约束

CREATE TABLE Products (
    product_no integer,
    name text,
    price numeric,
    pos integer,
    UNIQUE(name,pos)
);

DROP TABLE Products;
--NULL在多字段唯一约束下被认为是不等的,所以我们为了程序的健壮性需要添加非空约束
--给唯一约束命名

CREATE TABLE Products (
    product_no integer,
    name text NOT NULL,
    price numeric,
    pos integer NOT NULL,
    CONSTRAINT product_unique UNIQUE(name,pos)
);
DROP TABLE Products;
--非空约束和唯一约束的组合其实在技术上是等同于主键约束的
--2.4 主键约束

CREATE TABLE Products (
    product_no integer,
    name text UNIQUE,
    price numeric UNIQUE,
    pos integer,
    PRIMARY KEY (name,pos),
    UNIQUE(name,price)
);

--2.5 外键约束 
--使得表中某字段与另一表某字段具有相同行为 保证了表的参照完整性
--单一字段外键
CREATE TABLE Pro_Record (
    pro_name text REFERENCES Products(name),
    price numeric
    --or use under method
);

DROP TABLE Pro_Record;

--组合字段外键


CREATE TABLE Pro_Record (
    pro_name text,
    price numeric,
    FOREIGN KEY(pro_name,price) REFERENCES Products(name,price)
);
--引用的单一或组合字段需要满足唯一约束才能指定为外键
DROP TABLE Pro_Record;
DROP TABLE Products;

--注:外键所以引发的删除问题--更新行为也是类似
--假如存在学生表Student和Stu_Record表,Student_Record引用了学生表的学号,那么删除学生表的某条记录会有什么行为呢?
--下列删除的定义在后面,写在这里是为了方便调试其行为
DROP TABLE Student_Record;
DROP TABLE Student;
DROP TABLE DR1;
DROP TABLE DR2;
DROP TABLE R1;
DROP TABLE R2;
CREATE TABLE Student (
    number numeric(8,0) PRIMARY KEY
    --maybe have a lot....
);

CREATE TABLE Student_Record (
    stu_number numeric(8,0) REFERENCES Student(number) --equal to NO ACTION
);

INSERT INTO Student(number) VALUES (20161000),(20162000),(20163000),(20164000);

SELECT * FROM Student;
SELECT * FROM Student_Record;

INSERT INTO Student_Record(stu_number) VALUES (20161000),(20162000),(20163000),(20164000);
--删除Student存在于Student_Record的值
--缺省行为  抛出错误 删除操作被撤销
DELETE FROM Student WHERE number = 20161000;

CREATE TABLE R1 (
    code numeric(8,0) PRIMARY KEY
);

CREATE TABLE DR1 (
    code numeric(8,0) REFERENCES R1(code) ON DELETE RESTRICT
);
CREATE TABLE R2 (
    code numeric(8,0) PRIMARY KEY
);
CREATE TABLE DR2 (
    code numeric(8,0) REFERENCES R2(code) ON DELETE CASCADE
);

INSERT INTO R1(code) VALUES (20161000);
INSERT INTO DR1(code) VALUES (20161000);
INSERT INTO R2(code) VALUES (20161000),(20162000);
INSERT INTO DR2(code) VALUES (20161000);

DELETE FROM R1 WHERE code = 20161000;
DELETE FROM R2 WHERE code = 20161000;

--查看记录
--CASCADE保证了数据的级联删除:即先删除DR2数据再无障碍的删除R2数据
--RESTRICT 禁止删除DR2中存在的数据
SELECT * FROM R1;
SELECT * FROM R2;
SELECT * FROM DR1;
SELECT * FROM DR2;
--RESTRICT 和 默认行为NO ACTION区别:RESTRICT反应比NO ACTION快,NO ACTION等到事务结束时才反应出错
--除了NO ACTION CASCADE RESTRICT等行为外还有 SET NULL 和 SET DEFAULT


--2.6 排他约束
--排他约束:排他约束保证了表中任意两行的被约束字段必须是约束操作符为假
CREATE TABLE Price (
    price INT,
    EXCLUDE USING btree(price WITH =) --保证插入的价格不相同
);

INSERT INTO Price(price) VALUES (200);
INSERT INTO Price(price) VALUES (300);
INSERT INTO Price(price) VALUES (200);
SELECT * FROM Price;
DROP TABLE Price;
约束种类 作用 语句
检查约束/字段约束 通过在字段类型后用[CONSTRAINT CHECK_NAME] CHECK(expression)添加字段约束,使得避免使表达式为假的脏数据(若无明确指定则无法避免NULL) [CONSTRAINT CHECK_NAME] CHECK(expression)
检查约束/表约束 通过在表定义中添加[CONSTRAINT CHECK_NAME] CHECK(expression)添加约束,表约束可以引用表中多个字段,而字段约束只能引用自身字段 [CONSTRAINT CHECK_NAME] CHECK(expression)
唯一约束 通过设定唯一约束,使得字段不得相同(NULL除外) [CONSTRAINT CHECK_NAME] UNIQUE(a,b….)
非空约束 使得字段不得为空 NOT NULL
主键 设置主键使得字段内各值不能相同(包括NULL) [CONSTRAINT CHECK_NAME]PRIMARY KEY(a,b…)
外键 设置外键可以使得表A和表B具有参照性,含外键的表里元素必须是引用表的存在的 [CONSTRAINT FOREIGN_KEY_NAME] FOREIGN KEY (a,b…) REFERENCES B(a,b…) {[ON DELETE][ON UPDATE] [NO ACTION / RESTRICT / CASCADE]}/{SET DEFAULT / SET NULL}
排他约束 避免表中任意两行使得字段操作表达式为真,若为真则操作出错,为假和NULL可以 [CONSTAINT CHECK_NAME] EXCLUDE UISNG 搜索途径名(字段名 WITH 操作符)

你可能感兴趣的:(PostgreSQL实践)