python四十一期---mysql创表时---字段名约束条件

昨日内容回顾

  • 字符编码与配置文件

    在登录mysql客户端的前提下:
    \s	查看mysql相关信息,
    
    在windows中默认配置文件是my-default.ini
    需要拷贝并重命名my.init
    	[mysqld]
        	服务端配置
    	[mysql]
        	自己写的客户端配置
    	[client]
        	第三方客户端
    
    配置文件中针对服务端相关配置修改之后一定要重启服务端!!!
    
  • 数据库存储引擎

针对数据采取不同的存取策略
查看mysql中能够切换的引擎名称的命令
show engines;
--------------------------------------
MyISAM
	mysql5.5及之前默认的存储引擎
InnoDB
	mysql5.5之后默认的存储引擎
	支持事务、行锁、外键
Memory
	基于内存存取数据
BlackHole
	任何写入的数据都会消失
-------------------
我们在创建表的时候是可以自定义存储引擎 
不同的存储引擎对应到硬盘上的文件个数也各不相同

.

  • 创建表的完整语法
create table 表名(
	字段名 字段类型(数字) 约束条件,
	字段名 字段类型(数字) 约束条件,
	字段名 字段类型(数字) 约束条件
  );

.

  • 字段类型之整型
tinyint
smallint
int
bigint
   1.存储的数字范围不同
   2.有正负数之分(默认带有符号)
      id int unsigned

.

  • 字段类型之浮点型
float
double
decimal
  1.精确度不同
  2.(数字1,数字2) 数字1应该大于等于数字2

.

  • sql_mode
show variables like '%mode%';
set session
set global
  命令的形式修改是替换 所以之前的配置也需要重新写逗号隔开添加多个

.

  • 字段类型之字符型
char		 定长
varchar		 变长
  1.两者的优缺点
  2.char_length()

.
.

  • 字段类型之枚举与集合
枚举
	多选一		性别
	gender enum('male','female','others')
--------------
集合
	多选多		爱好
	hobbies set('篮球','足球','双色球')

.

  • 字段类型之日期类型
datetime
date
time
year

.

今日内容概要

主题:字段约束条件

  • 无符号、零填充
  • 非空
  • 默认值
  • 唯一值
  • 主键
  • 自增
  • 外键

创建表的完整语法
create table 表名(
字段名1 字段类型(数字) 约束条件,
字段名2 字段类型(数字) 约束条件,
字段名3 字段类型(数字) 约束条件
);

约束条件是基于字段类型之上的额外限制!!!

怎么理解:字段类型用来限制,字段名1下面只能插入对应字段类型,约束条件条件用来限制插入了对应字段类型的数据必须要符合限制条件
有点类似与层层加限制条件,对要插入表的数据进行一个筛选的感觉!!!

今日内容详细

.
.
.
.

字段约束条件1--------无符号、零填充


unsigned                   无符号
	id int unsigned
zerofill                   零填充
	id int(5) zerofill

.
.
.
.

字段类型后面------无约束条件情况:


create table t1(
	id int,
	name varchar(16)
);

insert into t1(id) values(1);
insert into t1(name) values('jason');
insert into t1(name,id) values('kevin',2);  # 还可以打破位置字段名的顺序进行传参

---------------------------------------------

我们之前学的是insert into t1 values();
这种结构语法,这种情况下必须要按照每一个字段名的顺序一一传参
也就是说你只要insert into 表名

表名后面没加括号,括号里面没加字段名,
那么values的括号里面必须按照字段名的顺序全部传一遍!!!

----------------------------------------------

insert into t1(id) values(1);
在t1后边加字段名后,就可以指定只给该字段添加数据!!其他字段默认就不添加了!!!
补充:所有字段类型不加(非空约束条件)的情况下,默认都可以为空!!!!!!
NULL 空

-------------------------------------------------

image
.
image
.
image
.
.
.
.
.
.

字段约束条件2--------非空


create table t2(
	id int,
	name varchar(16) not null
);
insert into t2(id) values(1);     # 报错!!因为默认了name不能为空了!!
insert into t2(name) values('jason');
insert into t2 values(1,'');  # 不报错!!不管你给什么,只要不是null,就算有值!
insert into t2 values(2,null);  # 报错!!!

-------------------------------------

关键字:not null 非空   在字段类型后面加上该约束条件后,
在传数据时,该字段名就必须要传数据了!!

image
.
.
.
.
.
.

字段约束条件3-------------默认值


create table t3(
	id int default 666,
	name varchar(16) default '匿名'
);


insert into t3 values(1);
# 报错!!注意只要t3后面括号里不接字段名,values括号里面就要每个字段都要传数据!!!
有默认值也不行,也要传!!!
只有表名后面接(字段名),后面的values的括号里面才可以只传对应的字段名,
而不用全部的字段名都要传数据!!!

---------------------------

insert into t3(id) values(1);
insert into t3(name) values('jason');
insert into t3 values(2,'kevin');
insert into t3 values(null,null);  # 这样就会插两个null进去

----------------------------

字段如果不传值,如果设置了默认值,那就会是默认值了,
和函数定义的时候的默认参数有点像,传参的时候,不给就用默认的,给了就用你给的
所以有时候写默认值的时候,会在前面再加一个限制not null 这样就不能插一个空进去了!!!

-------------------------

image
.
.
.
.
.
.
.

字段约束条件4---------------唯一值(键)


关键字:unique
单列唯一:
create table t4(
	id int unique,
	name varchar(32) unique
);

insert into t4 values(1,'jason'),(2,'jason');  # 报错了!!插入的值里面'jason'重复了
insert into t4(id,name) values(3,'jack22');  # 这样也行!!!

insert into t4(id) values(4);
# 这样也行,这个时候name虽然约束了为唯一,但是没有约束为非空,所有不传值对应的还是默认值null

insert into t4(id) values(5);
# 可以!!!name对应的还是null,虽然上面对应的也是null,因为null是空,
# 所以并不会判定这两个name对应的null 重复了!!! 不会报错!!!

--------------------------------------------
unique 是唯一的
所以将来在字段名id与name 里面将来存值的时候,就不能重复了,只能是唯一的了!!

----------------------------------------------

关键字:unique(字段名1,字段名2)
联合唯一:几个字段组合到一起的结果必须是唯一的!!!单个单个的可以重复!!
create table t5(
	id int,
	ip varchar(32),
	port int,
	unique(ip,port)
);

insert into t5 values(1,'127.0.0.1',8080),(2,'127.0.0.1',8081),(3,'127.0.0.2',8080);

insert into t5 values(4,'127.0.0.1',8080);
# 报错!!因为因为IP与端口存进去的数据与id为1的ip与端口的数据完全一样了!!!

--------------------------------

unique(ip,port)
联合唯一的意思  就是存进去的IP与port的字段数据,
单个单个的都可以与已经存入的数据重复,
但是ip与port拼在一起的结果不能与已经存入的数据重复!!!
就是存进去的数据ip与port有一个重复没事,
如果两个都与存进去的一组数据中的ip与port一样,就不行了!!!

单例唯一:
image
.
.联合唯一
image
.
特殊情况,name对应的还是null,虽然上面对应的也是null,因为null是空,
所以并不会判定这两个name对应的null 重复了!!! 不会报错!!!
image
.
.
.
.
.

字段约束条件4---------主键 primary key 非空且唯一!!!


# 单从约束层面上而言:主键相当于not null + unique  非空且唯一

关键字:primary key
--------------------------------------

create table t6(
	id int primary key,
	name varchar(32)
);

insert into t6(name) values('jason');  # 报错!!已经规定id非空且唯一了,所以必须要传值!!!
insert into t6 values(1,'kevin');
insert into t6 values(1,'jerry');  # 报错!!已经有一个id等于1了!!!

------------------------------------------------------

id int primary key
这样一写,将来针对id字段插入的数据不能为空,且不能与之前存进来的数据一样,
就是不能重复了!!!

------------------------------------------------------

2.InnoDB存储引擎规定了所有的表都必须有且只有一个主键!!!!!!
主键的作用:主键是组织数据的重要条件并且主键可以加快数据的查询速度!!!!!!
两种情况:
2.1.当表中没有主键也没有其他键(非空且唯一的字段)的情况下:
	InnoDB会采用一个隐藏的字段作为表的主键(因为一张表没有主键是建不起来的!!!)隐藏意味着无法使用!!!,基于该表的数据查询只能一行行查找,速度很慢!!!
------------------------------

2.2.当表中没有主键但是有其他非空且唯一的字段的情况下:
	那么会从上往下将第一个该字段自动升级为主键!!!
create table t7(
	id int,
	age int not null unique,     # 会自动变成为主键!!
	phone bigint not null unique,
	birth int not null unique,
	height int not null unique
);
-------------------------------------------------------

我们在创建表的时候应该有一个字段用来标识数据的唯一性!!!!!!
目的只有一个:标识数据,方便管理这条数据!!!!!!
并且该字段通常情况下是(编号)字段就行!! 'id' 'nid' 'pid' 'uid'...
将来我们创建表,不管表里面有多少乱七八糟的字段,首先上来必须弄一个编号字段出来!!!
create table userinfo(
	id int primary key,
	age int
	.
	.
	.
);

-------------------------------------------------------

在数据库表设计的时候,一般多对多的表,里面的两个外键,我们就可设置成联合主键
也就是说这两个字段,不仅要非空,而且要保持联合唯一!!!

image
.
image
.
.
.
.
.

字段约束条件5------主键自增 primary key auto_increment


该约束条件不能单独出现,并且一张表中只能出现一次!!!
通常情况下主要就是配合主键一起用!!!
关键字:primary key auto_increment

------------------------------
create table t8(
	id int primary key,
 	name varchar(32)
);

这种情况下,由于规定了id字段为主键,
所以每次插入数据必须要输入对应的编号且不能与以前的编号重复,就比较麻烦了!!!!!!

-------------------------
create table t9(
	id int primary key auto_increment,
 	name varchar(32)
);

insert into t9(name) values('jack'),('jax'),('kin');
insert into t9(name) values('jason');
insert into t9(name) values('george');

auto_increment 就是自动增加的意思
这个时候就可以肆无忌惮的往表里面插数据,并且可以不用考虑主键的存在了!!!
----------------------------------------------------

自增特性注意事项:
自增不会因为数据的删除而回退!!! 永远自增往前!!,
后续再插入数据的时候id不会因为数据的删除而回退!!!

-----------------------------------------------------

如果自己设置了更大的数!!!则之后按照更大的往前自增!!!!
后续再插入数据的时候id会顺着自己设置的更大的数往后增!!!

-----------------------------------------------------

image
.
image
.
image
.

如果想重置某张表的主键值 可以使用 truncate 表名; 清空表数据并重置主键!!!

.
.
.
.
.
.
.

外键前戏


我们需要一张员工表
	id	name	age		dep_name	dep_desc

1.表语义不明确(主体到底是员工还是部门)		无所谓
2.存取数据过于冗余(浪费存储空间,有些数据重复了)		无所谓
3.数据的扩展性极差(比如你要讲一个部门的名称改了,那么所有的该部门名称都要改,扩展性差!!! 		不能忽略

------------------------------------------------------

解决办法:
将上述表一分为二
	id	name	age
-------
	id	dep_name dep_desc
上述的三个问题全部解决 但是员工跟部门之间没有了关系
解决办法:
外键字段:用于标识数据与数据之间关系的字段
------------------------------------------------------

image
.
.
.
.
.

关系的判断


表关系、数据关系其实意思是一样的 知识说法上有区分
----------------
关系总共有四种
	一对多
	多对多
	一对一
	没有关系
----------------
关系的判断可以采用'换位思考'原则

.
.
.

一对多关系


以员工表和部门表为例
1.先站在员工表的角度
	问:一名员工能否对应多个部门
		答:不可以
2.再站在部门表的角度
	问:一个部门能否对应多名员工
		答:可以,所以部门是一,员工是多!!!
结论:一个方可以一个方不可以, 那么关系就是'一对多',表关系没有多对一的说法!!!
------
针对'一对多'关系,外键字段建在'多'的一方!!!!!!
其实也很好理解假如员工有几万人,部门只有10几个,如果把外键字段建在部门表里面,那么每一个部门的外键就要对应很多人
如果把外键字段建在员工表里面,那么每一个员工的外键就只要要对应一个部门就行了!!!

.
.
.

外键字段的建立------数据库层面的约束了!!!

foreign key(当前表里面的外键字段) references 被关联表名(被关联表里面的字段名)

小技巧:先定义出含有普通字段的表,之后再考虑外键字段的添加

员工表(关联表):
create table emp(
	id int primary key auto_increment,
	name varchar(32),
	age int,
	dep_id int,
	foreign key(dep_id) references dep(id)
);

dep_id int  外键字段名和外键字段对应的数据类型!!!
外键字段建立的关键字:
foreign key(当前表里面的外键字段) references 被关联表名(被关联表里面的字段名)
有两个作用:1.让上面的字段变为外键字段!!!  2.与被关联的表里面对应的字段名建立关联!!!
-------------------------------------------
部门表(被关联表):
create table dep(
	id int primary key auto_increment,
	dep_name varchar(32),
	dep_desc varchar(64)
);
--------------------------------------------
注意:
1.创建表的时候一定要先创建被关联表!!!  直接创员工表(关联表)会报错!!!
2.录入表数据的时候一定要先录入被关联表!!!
因为被关联表与关联表被创建后,假如先往关联表里面插入数据,就会出现外键字段对应的数据没法写的情况!!因为现在被关联表里面没有数据呢!!!mysql的外键关联语法,就规定了外键字段对应的数据只能够填写的是:被关联表里面的字段名里面出现过的值!!!!
------
3.修改数据的时候需要先解除关系(外键字段无法修改和删除!!!)
不解除关系,直接删被关联表里面的数据会直接报错,不给你删,或者改!!
真想改或者删被关联表里面的数据,要先解除关联关系(看被关联表里面数据对应关联表里面数据的外键编号,先把外键编号改掉,这样就解除了与想要删或者改的被关联数据表对应的数据的关系了!!! 关联的人多的话,操作就很烦!!!)
--------------------------------------------------

先创被关联表
再创关联表
image
.
录入数据的时候
一定要先录入被关联表 insert into dep(dep_name,dep_desc) values('讲师部','教书育人'),('财务部','发放工资');
再录入关联表 insert into emp(name,age,dep_id) values('jason',18,1),('tony',28,2);
image
.
.

级联更新on update cascade 级联删除on delete cascade

针对3有简化措施>>>:级联更新  级联删除
create table emp1(
	id int primary key auto_increment,
	name varchar(32),
	age int,
	dep_id int,
	foreign key(dep_id) references dep1(id)
	on update cascade  # 级联更新!!!
	on delete cascade  # 级联删除!!!
);

create table dep1(
	id int primary key auto_increment,
	dep_name varchar(32),
	dep_desc varchar(64)
);

级联更新:当修改被关联表里面的数据时,关联的表里面外键对应的数据会自动变!!
级联删除:当删除被关联表里面的数据时,关联的表里面外键对应的一行整行数据都自动删掉!!
---------------------------------------------------
外键其实是强耦合 不符合解耦合的特性
	所以很多时候 实际项目中当表较多的情况 我们可能不会使用外键!!!!!!
	而是使用代码建立逻辑层面的关系!!!

.
.
.

多对多关系

先写基表---再关系表里面关联对应的基表

以书籍表与作者表为例
1.先站在书籍表的角度
	问:一本书能否对应多个作者
		答:可以
2.再站在作者表的角度
	问:一个作者能否对应多本书
		答:可以
结论:两个都可以 关系就是'多对多'
	针对'多对多'不能在表中直接创建 需要新建第三张关系表
如果不用第三张表的话,两个表里面都有一个外键关联对方的表里面的数据,这个时候创表的创不出来了,因为我们前面学过,必须先创被关联的表,现在两个表都是被关联的表了!!!所以连表都创不起来!!!
把两个表里面的所有的外键字典都建到第三张表里面去,用第3张表来专门存储两张表数据之间的关系!!!
---------------------------------------------------
书籍表:
create table book(
	id int primary key auto_increment,
	title varchar(32),
	price float(5,2)
);
------
create table author(
	id int primary key auto_increment,
	name varchar(32),
	phone bigint
);
------
create table book2author(
	id int primary key auto_increment,
	author_id int,
	foreign key(author_id) references author(id)
	on update cascade   # 级联更新
	on delete cascade,  # 级联删除
	book_id int,
	foreign key(book_id) references book(id)
	on update cascade  # 级联更新
	on delete cascade  # 级联删除
);
-----------------
多对多的关系是最好操作的,因为操作两张单表的时候可以随意操作,因为两个表里面的数据有没有关系完全是第3表说了算的,把表里面对应的关系删掉就可以改对应关联的数据了!!

打个比方,比如第一本书有100个作者,那么第三张关系表里面book_id对应的数据就应该由100个1,每一个1对应的author_id就应该是这100作者在作者表里面对应的id号!!!

这张表可以这样看book_id为1的书对应了author_id为1与2的作者
author_id为1的作者对应了book_id为1、2、3三本书

一行只能出现一个关系!!!
image
.
.
.
.

一对一关系

以用户表与用户详情表为例
	1.先站在用户表的角度
		问:一个用户能否对应多个用户详情
		答:不可以
	2.再站在用户详情表的角度
		问:一个用户详情能否对应多个用户
		答:不可以
结论:两个都可以 关系就是'一对一'或者没有关系!!!!!!
---------
针对'一对一'外键字段建在任何一方都可以
冷数据就是使用频率较低的      热数据就是使用频率较高的!!!
但是推荐建在查询频率较高的表中!!!!!!
-----------------------------------------
create table user(
	id int primary key auto_increment,
	name varchar(32),
	detail_id int unique,
	foreign key(detail_id) references userdetail(id)
	on update cascade
	on delete cascade
);

create table userdetail(
	id int primary key auto_increment,
	phone bigint
);
-----------------------------------------
在关联表的里面外键后面加一个unique  用来限制在关联表里面外键字段detail_id存进去的数据不能重复,一旦重复就又变成一对多了!!!  限制住之后detail_id字段里面的数据,就又要在关联表里面不能重复,又要是被关联表里面id下面出现过的数据,而被关联表里面的id又是主键,非空且唯一,所以两边就只能是11的关系了!!!

.
.
.

作业

1.整理今日内容及博客
2.判断下列表数据关系 并自定义创建出表
	有些表数据关系不是确定 根据具体业务可能有变化
        服务器表与应用程序表
        课程表与班级表
        学生表与班级表
        老师表与课程表
        书籍表与出版社表
posted @   tengyifan  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示