为了规范数据格式, 在用户进行插入、修改、删除等操做时,DBMS(数据库管理系统(Data Base Management System))自动按照约束条件对数据进行监测, 使不符合规范的数据不能进入数据库, 以确保数据的完整性和惟一性python
表完整性约束条件与字段数据类型的宽度同样, 都是可选参数,分为如下几种:mysql
完整性约束关键字 | 含义 |
---|---|
NULL | 标识字段值能够为空 |
NOT NULL | 约束字段值不为空 |
DEAFAULT | 设置字段值为默认值 |
UNIQUE KEY(UK) | 约束字段的值惟一 |
PRIMARY KEY(PK) | 设置字段为表的主键 |
FOREIGN KEY(FK) | 设置字段为表的外键 |
AUTO_INCREAMENT | 约束字段的值为自动递增 |
UNSIGNED | 无符号 |
AEROFILL | 使用 0 填充 |
create table t04(id int); insert t04 value(); # values() 也能够 value() insert t04 value(null); # 而且 into 能够省略 insert t04 value(1);
create table t05(name char(16) not null); insert t05 value(); insert t05 value(null); insert t05 value("shawn");
create table t06(name char not null default "shawn"); insert t06 value(); insert t06 value(null); create table t07(name char not null dafault null); # 直接报错
create table t07(id int unique,name char(16)); insert t07 value(1,"shawn"),(2,"song"); insert t07 value(1,"xing"); # 报错提示重复
create table t08(id int,ip varchar(16),port int,unique(ip,port)); # ip + port 联合单个能够重复, 联合不能相同 insert t08 value(1,"127.0.0.1",8090); insert t08 value(2,"127.0.0.1",8091); insert t08 value(3,"127.0.0.1",8090); # 联合与id为1的相同, 报错
主键约束(primary key)sql
ps : InnoDB引擎表是基于B+树的索引组织表(IOT)(自行百度)数据库
create table t09(id int primary key); # 设置主键 insert t09 value(1),(2); insert t09 value(null); # 插入 null 报错 insert t09 value(1); # 插入id 1 报错 insert t09 value(2); # 插入id 2 也报错
create table t10( id int not null unique, # 设置 id 字段不为空,且惟一 name char(16) not null, age int, sex char(3) not null ); desc t10; # 查看表结构
create table t11( id int primary key, name varchar(16) ); desc t11;
create table t12( ip varchar(16), port int, primary key(ip,port) # 设置 IP + port 联合主键 ); insert t12 value("127.0.0.1",8090); insert t12 value("127.0.0.1",8091); # 单个字段能够相同 insert t12 value("127.0.0.1",8090); # 连个字段不能相同, 报错
create table t13( id int primary key auto_increment, name varchar(16) ); insert t13(name) value("shawn"),("xing");
insert t13 value(7,"xing"),(9,"hai");
insert t13(name) value("hello"); # 再次不指定 id
🍓"delete"删除表再插入记录演示 delete from t13; insert t13(name) value("shawn");
🍓"truncate"清空表再插入记录演示 insert t13(name) value("song"),("hai"),("xing"); # 先插入几条记录 truncate t13; insert t13(name) value("aaa"),("bbb"),("ccc"); # 再次插入记录
alter table t13 auto_increment=18; insert t13(name) value("ddd"),("eee"),("fff"); select * from t13;
create table t14( id int primary key auto_increment, name varchar(16), sex enum("male","female") default "male" )auto_increment=5; # 初始值的设置为表选项,应该放到括号外 insert t14(name) value("aaa"),("bbb"),("ccc");
ps : 得出表关系结论须要双向进行观察对比 (固然没有关系也是一种关系数据结构
)测试
从上面的表中咱们不难发现缺点(以上只演示了7个员工, 假设有一万个员工) :优化
- 部门名和职能说明重复, 浪费磁盘空间
- 组织结构不是很清晰
- 数据的扩展性差 (重点)
表已经抽离成功, 咱们使用 dep_id 将两个表创建联系设计
正常来讲, 一个员工只能对应一个部门, 一个部门能够包含多个员工code
结论 : 员工表与部门表是 一对多(或多对一) 的关系索引
- 一对多关系表, 外键关键字设置在多的一方(emp)
- 在建表时, 需先创建被关联的表(主表)(dep), 否则先建立附表会报错
- 插入数据时, 必须先往被关联的表(主表)插入(dep)
语法 :
foreign key([子表字段]) references [主表名]([主表字段])
🍓先建立被关联的表(主表)(dep) create table dep( id int primary key auto_increment, dep_name varchar(16), dep_dec varchar(50) ); insert dep(dep_name,dep_dec) value ("销售部","销售公司产品"), ("采购部","采购公司所需原材料"), ("售后部","为客户提供售后服务"); # 插入部门数据 🍓再建立附表(子表)(emp) create table emp( id int primary key auto_increment, emp_name varchar(16), emp_age int, dep_id int, foreign key(dep_id) references dep(id) ); insert emp(emp_name,emp_age,dep_id) value ("派大星",22,2),("章鱼哥",32,2), ("蟹老板",34,1),("海绵宝宝",23,3), ("珍妮",18,1),("痞老板",54,3), ("珍珍",25,2); # 插入员工数据
update dep set id=100 where id=1; # 报错 update emp set dep_id=200 where dep_id=2; # 报错
delete from dep where id=2; # 报错 delete from emp where id=4; # 能够删除成功
on update cascade
), 同步删除(on delete cascade
)🍓新建一个子表,并设置级联(emp2) create table emp2( id int primary key auto_increment, emp2_name varchar(16), emp2_age int, dep_id int, foreign key(dep_id) references dep(id) on delete cascade on update cascade ); insert emp2(emp2_name,emp2_age,dep_id) value ("派大星",22,2),("章鱼哥",32,2), ("蟹老板",34,1),("海绵宝宝",23,3), ("珍妮",18,1),("痞老板",54,3), ("珍珍",25,2); # 插入员工数据
drop table emp; # 测试以前先删除 emp 表,以避免受影响 update dep set id=100 where id=1; # 将主表 id 为 1 的改成 100 update emp2 set dep_id=300 where dep_id=3; # 子表没法更新外键(报错)
delete from dep where id=100; # 删除 id 为 100 的记录(销售部门) select * from emp2; # 查看 emp2 受到的影响
是否左表的多条记录能够对应右表的一条记录,若是是,则证实左表的一个字段能够 foreign key 右表一个字段(一般是id)
是否右表的多条记录能够对应左表的一条记录,若是是,则证实右表的一个字段能够 foreign key 左表一个字段(一般是id)
多对一 : 若是只有步骤1成立,则是左表多对一右表, 若是只有步骤2成立,则是右表多对一左表
多对多 : 若是步骤1和2同时成立,则证实这两张表时一个双向的多对一,即多对多,须要定义一个这两张表的关系表(中间表)来专门存放两者的关系
一对一 : 若是1和2都不成立,而是左表的一条记录惟一对应右表的一条记录,反之亦然, 这种状况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique便可
上面的"员工表(emp)"与"部门表(dep)"就是多对一的关系
场景演示 : 做者和书的对应关系
对应关系 : 一个做者能够写多本书, 一本书也能够对应多个做者(合著) , 双向的一对多,即多对多
关联方式 : 设置外键(froeign key), 并使用一张中间表创建两表的联系
设计思路 : 建立一张中间表(au_bo), au_bo的一个id对应多个图书表(book)的id, 也对应做者表(author)的多个id, 反过来则是多对一, 因而咱们就能够在au_bo表内设置两个外键foreign key 来分别关联book表的id和author表的id
🍓先建立"book"和"author"两张表,并插入值 create table book( id int primary key auto_increment, title varchar(30) not null, price float(10,2) not null ); insert book(title,price) value ("《蟹堡秘籍》",1000.5),("《菠萝房建成手册》",5000.25), ("《章鱼哥做息日记》",2000),("《派大星哲学》",15000); create table author( id int primary key auto_increment, name varchar(16) not null, age int not null ); insert author(name,age) value("海绵宝宝",35),("派大星",34); 🍓再建立中间表"au_bo", 并设置外键创建联系 create table au_bo( id int primary key auto_increment, book_id int not null, author_id int not null, foreign key(book_id) references book(id) # 设置外键 on update cascade on delete cascade, # 设置级联更新和删除 foreign key(author_id) references author(id) # 设置外键 on update cascade on delete cascade # 设置级联更新和删除 ); insert au_bo(book_id,author_id) value(1,1),(1,2),(2,1),(3,1),(3,2),(4,2); select * from book; select * from author; select * from au_bo;
场景演示 : 一我的要去公司入职一个部门, 入职后就是员工, 部门对应的这我的是惟一的, 不可能有两个如出一辙的人, 而这名员工对应的就这一个部门, 还好比一张身份证对应一我的
注意 : 必定得保证设置外键的字段惟一, 外键健在哪一方均可以, 建议建在查询频率较高的表中
🍓建立"people"表,并插入内容 create table card( id int primary key auto_increment, phone int not null, ID_card varchar(19) not null ); insert card(phone,ID_card) value (458796,"3675454567855544555"), (784555,"3732458220113245979"), (458755,"2332214578621525545"); 🍓建立"card"表,并插入内容 create table people( id int primary key auto_increment, name varchar(16) not null, sex enum("male","female") default "male", card_id int not null unique, foreign key(card_id) references card(id) on update cascade on delete cascade ); insert people(name,sex,card_id) value ("shawn","male",1), ("song","female",2), ("xing","male",3); select * from people; select * from card;
---end---