掌握实体完整性的定义和维护方法。
定义实体完整性,删除实体完整性。能够写出两种方式定义实体完整性的SQL 语句:创建表时定义实体完整性﹑创建表后定义实体完整性。设计SQL语句验证完整性约束是否起
作用。
(1)创建供应商表(Supplier1)时定义实体完整性(列级实体完整性)
CREATE TABLE Supplier1 (
suppkey INT PRIMARY KEY,
name CHAR(100),
address VARCHAR(100),
nationkey INT,
phone CHAR(30),
acctbal NUMERIC(12, 2),
comment VARCHAR(100)
);
DESC Supplier1;
运行结果如下:
(2)创建供应商表(Supplier2)时定义实体完整性(表级实体完整性)
CREATE TABLE Supplier2 (
suppkey INT,
name CHAR(100),
address VARCHAR(100),
nationkey INT,
phone CHAR(30),
acctbal NUMERIC(12, 2),
comment VARCHAR(100),
PRIMARY KEY (suppkey)
);
DESC Supplier2;
运行结果如下:
(3)创建供应商表(Supplier3),在创建表后再定义实体完整性。
CREATE TABLE Supplier3 (
suppkey INT,
name CHAR(100),
address VARCHAR(100),
nationkey INT,
phone CHAR(30),
acctbal NUMERIC(12, 2),
comment VARCHAR(100)
);
DESC Supplier3;
ALTER TABLE Supplier3
CHANGE COLUMN suppkey suppkey INT PRIMARY KEY;
DESC Supplier3;
运行结果:
(4)定义供应关系表(PartSupp1)的实体完整性
主码由多个属性组成
CREATE TABLE partsupp1 (
partkey INT,
suppkey INT,
avialqty INT,
supplycost NUMERIC(10, 2),
comment VARCHAR(200),
PRIMARY KEY (partkey, suppkey)
);
DESC partsupp1;
运行结果:
可以看到主码为(partkey, suppkey)
(5)有多个候选码时定义实体完整性
定义国家表(nation1)的实体完整性,其中nationkey和name 都是候选码,选择nationkey 作主码,name 上定义唯一性约束。
CREATE TABLE nation1 (
nationkey INT PRIMARY KEY,
name CHAR(25) UNIQUE,
regionkey INT,
comment VARCHAR(150)
);
DESC nation1;
运行结果:
(6)增加两条相同记录,验证实体完整性是否起作用
给国家表(nation1)增加两条相同记录
INSERT INTO nation1 VALUES(40,'中国',1,'');
SELECT * FROM nation1;
INSERT INTO nation1 VALUES(40,'中国',1,'');
SELECT * FROM nation1;
可以发现,会报错
(7)删除实体完整性
删除国家表(nation1)的主码
ALTER TABLE nation1 DROP PRIMARY KEY;
DESC nation1;
可以看到,即使删除了主码,其属性仍不为空
(1)所有列级完整性约束都可以改写为表级完整性约束,而表级完整性约束不一定能改写为列级完整性约束。请举例说明。
多属性主码只能通过表级完整性约束定义。
(2)什么情况下会违反实体完整性约束,DBMS 将做何种违约处理?
当更新数据时,新的数据可能违反实体完整性约束。此时 DBMS 会拒绝执行。
掌握参照完整性的定义和维护方法。
定义参照完整性,定义参照完整性的违约处理,删除参照完整性。写出两种方式定义参照完整性的SQL语句:创建表时定义参照完整性、创建表后定义参照完整性。
(1)创建表时定义参照完整性
先定义地区表的实体完整性,再定义国家表上的参照完整性。
CREATE TABLE region1 (
regionkey INT PRIMARY KEY,
name CHAR(25),
comment VARCHAR(150)
);
DESC region1;
CREATE TABLE nation2 (
nationkey INT PRIMARY KEY,
name CHAR(25),
regionkey INT,
FOREIGN KEY (regionkey) REFERENCES region1 (regionkey),
comment VARCHAR(150)
);
DESC nation2;
运行结果:
(2)创建表后定义参照完整性
定义国家表的参照完整性。
CREATE TABLE nation3 (
nationkey INT PRIMARY KEY,
name CHAR(25),
regionkey INT,
comment VARCHAR(150)
);
ALTER TABLE nation3
ADD CONSTRAINT fk_nationkey FOREIGN KEY (regionkey) REFERENCES region1 (regionkey);
DESC nation3;
(3)定义参照完整性(外码由多个属性组成)
定义订单项目表的参照完整性。
CREATE TABLE partsupp1(
partkey INT,
suppkey INT,
availqty INT,
supplycost NUMERIC(10,2),
comment VARCHAR(200),
PRIMARY KEY(partkey,suppkey)
);
CREATE TABLE lineitem1 (
orderkey INT,
partkey INT,
suppkey INT,
linenumber INT,
quantity INT,
extendedprice NUMERIC(8, 2),
discount NUMERIC(3, 2),
tax NUMERIC(3, 2),
returnflag CHAR(1),
linestatues CHAR(1),
shipdate date,
commitdate date,
receiptdate date,
shipinstruct CHAR(25),
shipmode CHAR(10),
comment VARCHAR(40),
PRIMARY KEY (orderkey, linenumber),
CONSTRAINT FOREIGN KEY (partkey,suppkey) REFERENCES partsupp1 (partkey,suppkey)
);
DESC lineitem1;
(4)定义参照完整性的违约处理
定义国家表的参照完整性,当删除或修改被参照表记录时,设置参照表中相应记录的值为空值。
CREATE TABLE nation4 (
nationkey INT PRIMARY KEY,
name CHAR(25),
regionkey INT,
comment VARCHAR(150),
CONSTRAINT fk_nation_regionkey FOREIGN key(regionkey) REFERENCES region1(regionkey)
ON DELETE SET NULL ON UPDATE SET NULL
);
可以看到,当删除了regionkey为1的地区时,在nation表中其nationkey的值被设为空值
(5)插入一条国家记录,验证参照完整性是否起作用
INSERT INTO Nation3 (nationkey, name, regionkey, comment)
VALUES (1001, ' nation1 ', 1001, ' comment1 ');
报错,说明参照完整性起作用
(6)删除参照完整性
删除国家表的外码
ALTER TABLE nation4 DROP FOREIGN KEY fk_nation_regionkey;
可以看到,外键删除成功
对于自引用表,例如课程表(课程号、课程名、先修课程号、学分)中的先修课程号引用该表的课程号,请完成如下任务:
(1)写出课程表上的实体完整性和参照完整性。
CREATE TABLE COURSE(
CNO CHAR(4),
CNAME VARCHAR(40),
CPNO CHAR(4),
CCREDIT SMALLINT
);
ALTER TABLE COURSE
ADD PRIMARY KEY(CNO);
ALTER TABLE COURSE
ADD CONSTRAINT FK_CPNO
FOREIGN KET(CPNO) REFERENCES COURSE(CNO);
(2)在考虑实体完整性约束的条件下,试举出几种录入课程数据的方法。
在录入数据时,可以按照引用的顺序录入数据(总是先录入不存在引用或引用已存在的数据),也可以临时移除完整性约束,在录入数据后,再添加完整性约束。
如果数据本身无法满足约束,则引入约束时会失败。
掌握用户自定义完整性的定义和维护方法。
针对具体应用语义,选择NULL/NOT NULL、DEFAULT、UNIQUE、CHECK等,定义属性上的约束条件。
(1)定义属性NULL/NOT NULL约束
定义地区表各属性的NULL/NOT NULL属性。
CREATE TABLE region2 (
regionkey INT NOT NULL PRIMARY KEY,
name CHAR(25) NOT NULL,
comment VARCHAR(150) NULL
);
DESC region2;
定义成功
(2)定义属性 DEFAULT约束
定义国家表的regionkey的缺省属性值为0值,表示其他地区。
CREATE TABLE nation5 (
nationkey INT PRIMARY KEY,
name CHAR(25),
regionkey INT DEFAULT 0,
FOREIGN KEY (regionkey) REFERENCES region1 (regionkey),
comment VARCHAR(150)
);
DESC nation5;
(3)定义属性UNIQUE约束
定义国家表的名称属性必须唯一的完整性约束。
CREATE TABLE nation6 (
nationkey INT PRIMARY KEY,
name CHAR(25) UNIQUE,
regionkey INT,
comment VARCHAR(150)
);
DESC nation6;
(4)使用CHECK
使用CHECK定义订单项目表中某些属性应该满足的约束。
单明细表(Lineitem2)中某些属性应该满足的约束。如:装运日期< 签收日期,退货标记为A,R或N中某一个
CREATE TABLE lineitem2 (
orderkey INT,
partkey INT,
suppkey INT,
linenumber INT,
quantity INT,
extendedprice NUMERIC(8, 2),
discount NUMERIC(3, 2),
tax NUMERIC(3, 2),
returnflag CHAR(1),
linestatues CHAR(1),
shipdate date,
commitdate date,
receiptdate date,
shipinstruct CHAR(25),
shipmode CHAR(10),
comment VARCHAR(40),
PRIMARY KEY (orderkey, linenumber),
CONSTRAINT FOREIGN KEY (partkey,suppkey) REFERENCES partsupp1 (partkey,suppkey),
CHECK (shipdate < receiptdate),
CHECK (returnflag IN ('A', 'R', 'N'))
);
(5)修改Lineitem2的一条记录验证是否违反CHECK约束
首先插入数据
INSERT INTO lineitem2 (orderkey, linenumber, returnflag, shipdate, receiptdate)
VALUES (15, 20, 'A', '2022-11-29', '2022-12-31');
UPDATE lineitem2
SET returnflag = 'H'
WHERE orderkey = 15;
UPDATE lineitem2
SET shipdate = '2023-12-30'
WHERE orderkey = 15;
都会报错,不满足用户自定义CHECK约束
(1)请分析哪些完整性约束只针对单个属性,哪些完整性约束可以针对多个属性?哪些只针对一个表,哪些针对多个表?
答:在列级完整性约束中,每个约束只能涉及到一个属性;在表级完整性约束中,每个约束可以涉及多个属性。实体完整性只针对一个表,参照完整性可以涉及多个表。用户定义完整性涵盖实体完整性和参照完整性。
(2)对表中某一列数据类型进行修改时,要修改的列是否必须为空列?
假设字段有数据,则改为varchar2(40)执行时会弹出:“ORA-01439:要更改数据类型,则要修改的列必须为空”,这时要用下面方法来解决这个问题:
- 修改原字段名name为name_tmp
alter table tb rename column name to name_tmp;- 增加一个和原字段名同名的字段name
alter table tb add name varchar2(40);- 将原字段name_tmp数据更新到增加的字段name
update tb set name=trim(name_tmp);- 更新完,删除原字段name_tmp
alter table tb drop column name_tmp;
总结:
1、当字段没有数据或者要修改的新类型和原类型兼容时,可以直接modify修改。
2、当字段有数据并用要修改的新类型和原类型不兼容时,要间接新建字段来转移。
照完整性。
(2)对表中某一列数据类型进行修改时,要修改的列是否必须为空列?
假设字段有数据,则改为varchar2(40)执行时会弹出:“ORA-01439:要更改数据类型,则要修改的列必须为空”,这时要用下面方法来解决这个问题:
- 修改原字段名name为name_tmp
alter table tb rename column name to name_tmp;- 增加一个和原字段名同名的字段name
alter table tb add name varchar2(40);- 将原字段name_tmp数据更新到增加的字段name
update tb set name=trim(name_tmp);- 更新完,删除原字段name_tmp
alter table tb drop column name_tmp;
总结:
1、当字段没有数据或者要修改的新类型和原类型兼容时,可以直接modify修改。
2、当字段有数据并用要修改的新类型和原类型不兼容时,要间接新建字段来转移。
通过本次实验,我掌握了实体完整性的定义和维护方法,动手操作了定义实体完整性,删除实体完整性,并且可以设计SQL语句验证完整性约束是否起作用。同时,掌握了参照完整性的定义和维护方法,动手体验了定义参照完整性,并且操作了定义参照完整性的违规处理以及删除参照完整性。除此之外,还掌握了用户自定义完整性的定义和维护此次实验使我学习了完整性相关知识,更促使我进一步学习。