openGauss开源数据库实战八

任务八 测试 openGauss DBMS 的数据库约束

任务目标

机构组织的业务规则,有相当一部分通过数据库约束来实现。通过本任务,读者可以掌握
openGaussDBMS的主键(PRIMARY KEY)约束、UNIQUE约束、NOT NULL约束、外键(FOR- EIGNKEY)约束、CHECK约束,并能为某个属性设置默认值(DEFAULT)。

实施步骤

一、录到数据库studentdb

用Linux用户omm,打开一个Linux终端窗口,执行如下的命令,使用数据库用户student登录到数据库studentdb:

gsql-d studentdb-h 192.168.100.91-U student-p26000-W student@ustb2020-r

二、测试CHECK约束

1.列级CHECK约束

在创建表的时候,创建列级CHECK约束:

DROP TABLE IF EXISTS test;
--  创建表,age列的值表示活着的人的年龄,是0<=age<200的整数
--  在列级创建该CHECK约束
CREATE TABLE test(age INT CHECK(age>=0 AND age<200),
                  sex INT);
INSERT INTO test VALUES(-20,1);  -- 插入值不满足CHECK约束,插入报错!
INSERT INTO test VALUES(20,1);   -- 插入值满足CHECK约束
INSERT INTO test VALUES(201,1);  -- 插入值不满足CHECK约束,插入报错!
2.表级CHECK约束

在创建表的时候,创建表级CHECK约束:

DROP TABLE IF EXISTS test;
--  创建表,age列的值表示活着的人的年龄,是0<=age<200的整数
--  在表级创建该CHECK约束
CREATE TABLE test( age INT,
                   sex INT,
                   CHECK(age>=0 AND age<200)
                  );
INSERT INTO test VALUES(-20,1);  -- 插入值不满足CHECK约束,插入报错!
INSERT INTO test VALUES(20,1);   -- 插入值满足CHECK约束
INSERT INTO test VALUES(201,1);  -- 插入值不满足CHECK约束,插入报错!

在这里插入图片描述

三、测试NOTNULL约束

在创建表的时候,创建列级NOTNULL约束:

DROP TABLE IF EXISTS test;
CREATE TABLE test( sno int NOT NULL,  --  在列级创建NOT NULL约束
                   age int CHECK(age>0 and age<200)
                   );
INSERT INTO test VALUES(1,20);      -- 插入的行满足sno列非空
INSERT INTO test VALUES (NULL,20);  -- 插入的行不满足sno列非空,出错

四、验证一个属性可以有多个列级约束

创建表的时候,可以同时指定多个列级约束:

DROP TABLE IF EXISTS test;
--  一个属性在列级可以有多个约束
--       NOT NULL约束
--       CHECK约束
CREATE TABLE test( age INT NOT NULL CHECK(age>0 AND age<200) ); 

INSERT INTO test VALUES(20);  -- 插入的行满足age列非空且满足CHECK约束
INSERT INTO test VALUES(201); -- 插入的行满足age列非空但不满足CHECK约束,出错

五、测试UNIQUE约束

执行下面的语句,测试列级UNIQUE约束:

DROP TABLE IF EXISTS test;
CREATE TABLE test(   sno INT,
                     age INT UNIQUE   -- 列级UNIQUE约束
                   );
INSERT INTO test VALUES(1,20);        -- 插入的行满足  age唯一约束
INSERT INTO test VALUES(2,20);        -- 插入的行不满足age唯一约束

执行下面的语句,测试表级UNIQUE约束:

DROP TABLE IF EXISTS test;
CREATE TABLE test(   
                    sno int,
                    col1 int,
                    col2 int,
                    UNIQUE(col1,col2)  -- 表级多列组合值唯一约束
                   );
INSERT INTO test VALUES(1,20,20);    -- 插入的行  满足多列组合值唯一约束
INSERT INTO test VALUES(2,20,20);    -- 插入的行不满足多列组合值唯一约束,出错

六、测试主键约束

执行下面的语句,测试列级主键约束:

DROP TABLE IF EXISTS test;
CREATE TABLE test(
                    sno int PRIMARY KEY, -- 列级主键约束
                    age int 
                    );
INSERT INTO test VALUES(1,20);    -- 插入的行  满足主键约束
INSERT INTO test VALUES(2,20);    -- 插入的行  满足主键约束
INSERT INTO test VALUES(2,20);    -- 插入的行不满足主键约束,出错!

七、测试DEFAULT(给属性赋默认值)

DROP TABLE IF EXISTS test;
CREATE TABLE test(
                    sno int PRIMARY KEY,
                    age int             -- 没有定义该列的默认值,默认值缺省为null
                    );
INSERT INTO test VALUES(1,20);          -- 插入的行提供了所有的值
INSERT INTO test(sno) VALUES(2);        -- 插入的行未提供age的值,赋予默认值null
SELECT * FROM test;

执行下面的语句,为某个列(属性)指定默认值:

DROP TABLE IF EXISTS test;
CREATE TABLE test(
                    sno int PRIMARY KEY,
                    age int DEFAULT 20  -- 如果没有提供该列的值,赋予默认值20
                    );
INSERT INTO test VALUES(1,20);          -- 插入的行提供了所有的值
INSERT INTO test(sno) VALUES(2);        -- 插入的行未提供age的值,赋予默认值20
SELECT * FROM test;

在这里插入图片描述

八、测试外键约束

1.测试外键约束的默认行为

外键约束的默认行为是:只能为子表添加这样的行,其外键值是父表主键值集合中的元素;只能删除父表中这些行,其主键值已经不被子表外键所引用。
第一个例子是为子表添加行的例子。水果店出售不同品种的水果,水果店销售的水果只能是水果店进货的水果,没在进货列表的水果,没法记录在销售记录表中。下面的测试说明了这一点:

DROP TABLE IF EXISTS sell;
DROP TABLE IF EXISTS fruitstock;
CREATE TABLE fruitstock ( fruitname varchar(30) PRIMARY KEY);
CREATE TABLE sell( sellno INT PRIMARY KEY,
                   fruitname varchar(30)  REFERENCES fruitstock(fruitname)
                  );

-- 水果店只卖apple、banana和pear
-- 往表fruitstock插入水果apple、banana和pear
insert into fruitstock values('apple');
insert into fruitstock values('banana');
insert into fruitstock values('pear');

-- 表sell记录销售情况,只要销售的水果名字都是表fruitstock记录的,就满足外键约束
INSERT INTO sell (sellno, fruitname) VALUES (1, 'apple'), (2, 'apple'), (3, 'banana'), (4, 'banana'), (5, 'pear'), (6, 'pear');

-- 往子表sell插入的行,水果名如果没有记录在表fruitstock中,不满足外键约束
-- 父表fruitstock的fruitname列中没有值为mongo的行
insert into sell values(7,'mango');

第二个例子是删除行的例子。我们想删除父表中的水果pear,但是由于子表中还有关于pear的销售记录,因此无法删除父表中名为pear的记录。

-- 删除父表fruitstock的pear,因为子表sell还包含值为pear的行,违背外键约束
-- 因此无法删除父表中的记录pear
delete from fruitstock where fruitname='pear';

在这里插入图片描述
如果我们先删除子表中外键值为pear的行,那么在这些行被删除之后,就可以删除父表fruitstock中包含pear值的记录了。读者可以自己完成这个操作。
在这里插入图片描述

2.测试外键约束的on delete cascade特性

查看表sell上的约束(查看表的信息就可以看到该表上的约束情况):

\d sell

若要修改表约束,只能先删除约束然后再重建约束。下面将约束特性修改为on delete cascade和 on update cascade:

\set AUTOCOMMIT off
alter table sell drop constraint sell_fruitname_fkey;
alter table sell add constraint sell_fruitname_fkey foreign key (fruitname)
      references fruitstock(fruitname) on delete cascade on update cascade;
commit;

约束具有on delete cascade特性,意味着如果删除父表的记录,同时会将子表的对应记录页删除。下面的例子中,删除父表fruitstock中的pear记录,子表sell中关于水果pear的相应记录也会被删除:

如果读者尝试了删除父表fruitstock中包含pear值的记录了,那么可以使用下面的语句加入:

INSERT INTO fruitstock VALUES('pear');
INSERT INTO sell VALUES(5, 'pear');
INSERT INTO sell VALUES(6, 'pear');
commit;

在这里插入图片描述
以看出,约束特性是ondeletecascade时,在删除父表fruitstock中的记录后,会把子表中的相应记录级联删除。最后执行回滚语句,使测试数据恢复原状,以便继续进行下面的测试。

3.测试外键约束的on update cascade特性

下面测试外键约束的on update cascade特性:
在这里插入图片描述

4.测试外键约束的on delete set null特性

首先修改外键约束特性为on delete set null和on update set null:

\set AUTOCOMMIT off
alter table sell drop constraint sell_fruitname_fkey;
alter table sell add constraint sell_fruitname_fkey foreign key (fruitname)
      references fruitstock(fruitname) on delete set null on update set null;
commit;

select * from fruitstock;
select * from sell;
-- 外键约束具有on delete set null 特性,因此可以删除父表fruitstock的pear,
-- 但是会在删除父表相关记录的同时,将子表sell中外键的相应值设置为null
delete from fruitstock where fruitname='pear';
select * from fruitstock;
select * from sell;
rollback;
5.测试外键约束的on delete set null特性

下面测试外键约束的on delete set null特性。将父表fruitstock中的pear更新为grape:

select * from fruitstock;
select * from sell;
-- 外键约束具有on update set null 特性,因此可以更新父表fruitstock的pear值为grape,
-- 但在更新父表相关记录的同时,会将子表sell中外键的相应值设置为null
update fruitstock set fruitname='grape'where fruitname='pear';
select * from fruitstock;
select * from sell;
rollback;

九、查看表的约束

使用\d tableName命令查看表及其上的约束信息:

\d instructor

十、任务的扫尾工作

DROP TABLE IF EXISTS test;
DROP TABLE IF EXISTS sell;
DROP TABLE IF EXISTS fruitstock;
\q
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值