数据库约束

数据库约束

约束的作用:

对添加进表中的数据进行限制和检查,保证表中的数据正确性、有效性和完整性。

-- 建议在创建表的时候创建约束,因为这里表中没有数据。

约束种类:

约束名 约束关键字
主键 primary key
唯一 unique
非空 not null
默认 default
外键 foreign key

主键约束

主键的作用

几乎每张表都需要创建主键,用来唯一标识表中的每一条记录。

每个表都应该有一个主键,并且每个表只能有一个主键。

哪个字段应该作为表的主键?

通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。

-- 主键是给数据库和程序使用的,不是给最终的客户使用的。

所以主键有没有含义没有关系,只要不重复,非空就行。

主键的特点:

-- 1) 唯一

-- 2) 非空

-- 3)主键可以多个字段(联合主键)

创建主键方式:

1. 在创建表的时候给字段添加主键 
字段名 字段类型 PRIMARY KEY

2. 在已有表中添加主键 
ALTER TABLE 表名 ADD PRIMARY KEY(字段名);
-- 创建表学生表st1, 包含字段(id, name, age)将id做为主键

CREATE TABLE st1(

    id INT PRIMARY KEY ,

    NAME VARCHAR(20),

    age INT     

);

CREATE TABLE tab(
   rid INT,
   `date` DATE,
   uid INT,
   PRIMARY KEY(rid,uid),   -- 联合主键
);
 


-- 插入重复的主键值
INSERT INTO st1 VALUES(1, '张三', 20);

-- 报错
-- Duplicate entry '1' for key 'PRIMARY'  重复的记录
INSERT INTO st1 VALUES(1, '李四', 30);

 
-- 插入NULL的主键值  Column 'id' cannot be null  列不能为空
INSERT INTO st1 VALUES(NULL, '李四',30);

删除主键

删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;

具体操作:
-- 删除 st1 表的主键   通常情况下,一般不删除主键
ALTER TABLE st1 DROP PRIMARY KEY;

-- 在已有表中添加主键 
ALTER TABLE st1 ADD PRIMARY KEY(id);

主键自增

主键如果让我们自己添加很有可能重复,
 
我们通常希望在每次插入新记录时,数据库自动生成主键字段的值
 
AUTO_INCREMENT 表示自动增长(字段类型必须是整数类型)
 
 
默认地 AUTO_INCREMENT 的开始值是 1

如果希望修改起始值,请使用下列 SQL 语法 
创建表时指定起始值
CREATE TABLE 表名(
    列名 int primary key AUTO_INCREMENT
) AUTO_INCREMENT=起始值;
 
创建好以后修改起始值
ALTERTABLE 表名 AUTO_INCREMENT=起始值;
-- 创建学生表st2时, 包含字段(id, name, age)将id做为主键并自动增长

CREATE TABLE st2 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   NAME VARCHAR(20),
   age INT
);

SELECT * FROM st2;

-- 插入数据
-- Column count doesn't match value count at row 1
INSERT INTO st2 VALUES('张三',18);

 
INSERT INTO st2 (NAME,age) VALUES('张三',18);

INSERT INTO st2 (NAME,age) VALUES('李四',20);

 
-- 另一种写法
INSERT INTO st2 VALUES(NULL, '李白',20);


-- 删除表
DROP TABLE IF EXISTS st2;

-- 创建表时指定起始值
-- 指定自增长从1000开始
CREATE TABLE st2 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   NAME VARCHAR(20),
   age INT
) AUTO_INCREMENT = 1000;



INSERT INTO st2 (NAME,age) VALUES('张三',18);
INSERT INTO st2 (NAME,age) VALUES('李四',20);

SELECT * FROM  st2;

 

-- 再创建表

CREATE TABLE st2 (

   id INT PRIMARY KEY AUTO_INCREMENT,

   NAME VARCHAR(20),

   age INT

);

-- 创建学生表st2后, 将id添加自动增长
ALTER TABLE st2 MODIFY id INT  AUTO_INCREMENT;

-- 创建好以后修改起始值
ALTER TABLE st2 AUTO_INCREMENT=2000;

INSERT INTO st2 (NAME,age) VALUES('张三',18);
INSERT INTO st2 (NAME,age) VALUES('李四',20);

SELECT * FROM  st2;

DELETE和TRUNCATE对自增长的影响

DELETE:不会影响自增长的值,使用原来的自增长。

TRUNCATE:会,从1开始重新计数

唯一约束

-- 什么是唯一约束:表中某一列不同出现重复的值

-- 唯一约束的基本格式  

字段名 字段类型 UNIQUE

实现唯一约束

-- 创建学生表st3, 包含字段(id, name),name这一列设置唯一约束,不能出现同名的学生

CREATE TABLE st3 (

    id INT PRIMARY KEY,

    NAME VARCHAR(20) UNIQUE

);

 

DESC st3;

-- 添加一个同名的学生

INSERT INTO st3 VALUES (1, '张三');

SELECT * FROM st3;

-- Duplicate entry '张三' for key 'name'

INSERT INTO st3 VALUES (2, '张三');

 

-- 重复插入多个null会怎样?

INSERT INTO st3 VALUES (2, NULL);

INSERT INTO st3 VALUES (3, NULL);

SELECT * FROM st3;

非空约束

什么是非空约束:

表中的某一列不能为NULL

非空约束的基本语法格式

字段名 字段类型 NOT NULL

-- 创建表学生表st4, 包含字段(id,name,gender)其中name不能为NULL

CREATE TABLE st4 (

   id INT PRIMARY KEY,

   NAME VARCHAR(20) NOT NULL,

   gender CHAR(1)

);

 
DESC st4;

-- 添加一条记录其中姓名不赋值
INSERT INTO st4 VALUES(1,'张三','男');

 

SELECT * FROM st4;

-- Column 'name' cannot be null
INSERT INTO st4 VALUES(2,NULL,'男');

默认值

什么是默认值:
某一列,如果没有输入值,则使用指定的默认值。

默认值的语法:
字段名 字段类型 DEFAULT 默认值

-- 创建一个学生表 st5,包含字段(id,name,address), 地址默认值是广州

CREATE TABLE st5 (

    id INT PRIMARY KEY,

    NAME VARCHAR(20),

    address VARCHAR(20) DEFAULT '广州'
);

 

DESC st5;

 

-- 添加一条记录,使用默认地址

INSERT INTO st5 (id,NAME) VALUES (1,'张三');

SELECT * FROM st5;

 

-- 添加一条记录,不使用默认地址

INSERT INTO st5  VALUES (2,'张三疯','深圳');

 

INSERT INTO st5  VALUES (3,'李白',NULL);

 

INSERT INTO st5  VALUES (4,'李白',DEFAULT);


-- 加一个性别属性,默认为男
ALTER TABLE st5 ADD sex CHAR(1) DEFAULT '男';

外键约束

单表的缺点

创建一个员工表包含如下列(id, name, age, dep_name, dep_location),id主键并自动增长,添加5条数据

CREATE TABLE emp (

    id INT PRIMARY KEY AUTO_INCREMENT,

    NAME VARCHAR(30),

    age INT,

    dep_name VARCHAR(30),

    dep_location VARCHAR(30)

);

-- 添加数据

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('张三', 20, '研发部', '广州');

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('李四', 21, '研发部', '广州');

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('王五', 20, '研发部', '广州');

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('老王', 20, '销售部', '深圳');

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('大王', 22, '销售部', '深圳');

INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小王', 18, '销售部', '深圳');

以上数据表的缺点:

出现大量重复的数据,假如有1000个员工,有10个部门。大量部门的数据是重复的。

解决方案:

创建成两张表,一张员工表,另一张部门表


-- 创建一个部门表,主表(主表是一方)

CREATE TABLE department(

    id INT PRIMARY KEY AUTO_INCREMENT,   -- 主键

    dep_name VARCHAR(20),

    dep_location VARCHAR(30)

);

 

-- 添加部门数据

INSERT INTO department VALUES (NULL,'研发部','广州'),(NULL,'销售部','深圳');

 
SELECT * FROM department;


-- 创建一个员工表,有外键的表是从表,(从表是多方)

CREATE TABLE employee(

    id INT PRIMARY KEY AUTO_INCREMENT,  -- 主键

    NAME VARCHAR(20),

    age INT,

    dep_id INT   -- 创建一个外键

);

 

SELECT * FROM employee;

INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);

问题:当我们在employee的dep_id里面输入不存在的部门,数据依然可以添加.

但是并没有对应的部门,实际应用中不能出现这种情况。

employee的dep_id中的数据只能是department表中存在的id

目标: 需要约束dep_id只能是department表中已经存在id

解决方式: 使用外键约束

什么是外键约束

-- 什么是外键: 从表中引用了主表中主键的那一列

-- 主表: 一方就是主表,约束别人的一方

-- 从表: 多方就是从表,被约束的一方

创建约束的语法

 新建表时增加外键: 
[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)


 已有表增加外键: 
 ALTER TABLE 从表 ADD 
 [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主键字段名);
-- 1)   删除副表/从表 employee

DROP TABLE employee;

-- 2)   创建从表 employee 并添加外键约束emp_depid_fk, 如果没有起名,系统也会自动添加一个名字

CREATE TABLE employee(

    id INT PRIMARY KEY AUTO_INCREMENT,  -- 主键

    NAME VARCHAR(20),

    age INT,

    dep_id INT,   -- 创建一个外键

    -- 添加外键约束

    CONSTRAINT emp_depid_fk FOREIGN KEY (dep_id) REFERENCES department(id)

);

 

-- 3)   正常添加数据

INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);

 

INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);

SELECT * FROM employee;

-- 4)   部门错误的数据添加失败
-- Cannot add or update a child row:   从表中的记录
INSERT INTO employee (NAME, age, dep_id) VALUES ('小小王', 16, 6);

删除外键

-- 删除employee表的emp_depid_fk外键
ALTER TABLE employee DROP FOREIGN KEY emp_depid_fk;

-- 在employee表情存在的情况下添加外键
ALTER TABLE employee ADD CONSTRAINT aaa_bbb FOREIGN KEY(dep_id) REFERENCES department(id);

外键的级联

出现新的问题:要把部门表中的id值2,改成5,能不能直接更新呢?

-- Cannot delete or update a parent row:   不能更新主表中的行

UPDATE department SET id=5 WHERE id=2;

 

-- 要删除部门id等于1的部门, 能不能直接删除呢?

-- Cannot delete or update a parent row 不能删除主表中的行

DELETE FROM department WHERE id=1;

什么是级联操作:

在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作。

-- 只能在创建表的时候创建级联

ON UPDATE CASCADE 级联更新 
ON DELETE CASCADE 级联删除 

-- 删除employee表(从表)

-- 如果从表存在的情况下,不能直接删除主表
-- Cannot delete or update a parent row: a foreign key constraint fails
DROP TABLE department;

DROP TABLE employee;

 

-- 重新创建employee表,添加级联更新和级联删除-- 只能在创建表的时候创建级联
CREATE TABLE employee(

    id INT PRIMARY KEY AUTO_INCREMENT,  -- 主键

    NAME VARCHAR(20),

    age INT,

    dep_id INT,   -- 创建一个外键

    -- 添加外键约束

    CONSTRAINT emp_depid_fk FOREIGN KEY (dep_id) REFERENCES department(id) ON UPDATE CASCADE ON DELETE CASCADE

);

 

-- 再次添加数据到员工表和部门表

INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);

INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);

 

INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);

INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);

 

SELECT * FROM employee;

SELECT * FROM department;

-- 把部门表中id等于1的部门改成id等于9

UPDATE department SET id=9 WHERE id=1;

 

-- 删除部门号是2的部门

DELETE FROM department WHERE id=2;

数据约束小结

约束名 关键字 说明
主键 primary key 1) 唯一2) 非空3) 可以有多列
默认 default 如果没有输入值,使用默认值
非空 not null 不能为空
唯一 unique 不能重复
外键 foreign key 从表中的外键值,不能出现主表中没有的主键值

创建员工表和部门表,使用级联更新
    1) 创建主键和外键约束
    2) 员工表的主键使用整型,宽3位,使用自动增长,零填充,从100开始。
    2) 员工姓名使用非空唯一约束
    3) 员工加一个性别属性,默认为男
    4) 添加3个部门。向1号部门添加2个员工,向2号部门添加2个员工,向3号部门添加1个员工。
    5) 将102号员工转到3号部门中
    6) 更新1号部门为10号部门,观察部门表和员工表的变化。
    7) 删除3号部门,看会不会出现问题。
    8) 添加一个员工到5号部门,看有没有问题。
-- 部门表

CREATE TABLE depart (

    id INT PRIMARY KEY AUTO_INCREMENT,

    NAME VARCHAR(20)   -- 部门名

)

-- 员工表

CREATE TABLE employee (

    id INT(3) ZEROFILL PRIMARY KEY AUTO_INCREMENT,--zerofill 零填充

    NAME VARCHAR(20) NOT NULL UNIQUE,

    gender CHAR(1) DEFAULT '男',

    depart_id INT,

    FOREIGN KEY (depart_id) REFERENCES depart(id) ON UPDATE CASCADE

) AUTO_INCREMENT = 100;

-- 添加3个部门。向1号部门添加2个员工,向2号部门添加2个员工,向3号部门添加1个员工。

INSERT INTO employee (NAME,gender,depart_id) VALUES ('张三','男',1),('张四','女',1),('王五','男',2),('刘六','男',2),('孙七','男',3);

SELECT * FROM employee;

-- 将2号员工转到3号部门中

UPDATE employee SET depart_id = 3 WHERE id = 102;

-- 更新1号部门为10号部门,观察部门表和员工表的变化。

UPDATE depart SET id=10 WHERE id=1;

SELECT * FROM employee;

-- 删除3号部门,看会不会出现问题(删除异常)

DELETE FROM depart WHERE id=3;

-- 添加一个员工到5号部门,看有没有问题。(出现异常)

INSERT INTO employee (NAME,gender,depart_id) VALUES ('小红','女',5);

猜你喜欢

转载自blog.csdn.net/h294590501/article/details/80370658