宇辰恒笛

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

约束(非常重要)
什么是约束? constraint
在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性、有效性!!!

约束的作用:保证表中的数据有效

约束的种类
非空约束:not null

唯一性约束: unique

主键约束: primary key (简称PK)

外键约束:foreign key(简称FK)

检查约束:check(mysql不支持,oracle支持)

我们这里重点学习前四个约束。

非空约束:not null
非空约束not null约束的字段不能为NULL。

drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null // not null只有列级约束,没有表级约束!
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');

insert into t_vip(id) values(3);
ERROR 1364 (HY000): Field 'name' doesn't have a default value

小插曲:
xxxx.sql这种文件被称为sql脚本文件。sql脚本文件中编写了大量的sql语句。我们执行sql脚本文件的时候,该文件中所有的sql语句会全部执行!批量的执行SQL语句,可以使用sql脚本文件,用来初始化数据库。
在mysql当中怎么执行sql脚本呢?—— source

mysql> source D:\MySQL\document\vip.sql
1
唯一性约束: unique
唯一性约束unique约束的字段不能重复,但是可以为NULL。

drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique,
email varchar(255)
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');
insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');
select * from t_vip;

insert into t_vip(id,name,email) values(4,'wangwu','wangwu@sina.com');
ERROR 1062 (23000): Duplicate entry 'wangwu' for key 'name'

insert into t_vip(id) values(4);
insert into t_vip(id) values(5);
+------+----------+------------------+
| id | name | email |
+------+----------+------------------+
| 1 | zhangsan | zhangsan@123.com |
| 2 | lisi | lisi@123.com |
| 3 | wangwu | wangwu@123.com |
| 4 | NULL | NULL |
| 5 | NULL | NULL |
+------+----------+------------------+

注意看:name字段虽然被unique约束了,但是可以为NULL。

unique表级约束
新需求:假设name和email两个字段联合起来具有唯一性!!!!

drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique, // 约束直接添加到列后面的,叫做列级约束。
email varchar(255) unique
);

这张表这样创建是不符合以上“新需求”的。这样创建表示:name具有唯一性,email具有唯一性。各自唯一。

以下这样的数据是符合“新需求”的,但如果采用以上方式创建表的话,肯定创建失败,因为’zhangsan’和’zhangsan’重复了。

insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');

怎么创建这样的表,才能符合新需求呢?

drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
email varchar(255),
unique(name,email) // 约束没有添加在列的后面,这种约束被称为表级约束。
);

insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');
select * from t_vip;

name和email两个字段联合起来唯一!

insert into t_vip(id,name,email) values(3,'zhangsan','zhangsan@sina.com');
ERROR 1062 (23000): Duplicate entry 'zhangsan-zhangsan@sina.com' for key 'name'

什么时候使用表级约束呢?
需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。

unique 和not null可以联合吗?
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null unique
);

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(255) | NO | PRI | NULL | |
+-------+--------------+------+-----+---------+-------+

在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段。(注意:oracle中不一样!)

insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'zhangsan'); //错误了:name不能重复
insert into t_vip(id) values(2); //错误了:name不能为NULL。

主键约束(primary key,简称PK)重点
主键约束的相关术语(废话)
主键约束:就是一种约束。

主键字段:该字段上添加了主键约束,这样的字段叫做:主键字段

主键值:主键字段中的每一个值都叫做:主键值。

什么是主键?有啥用?
主键值是每一行记录的唯一标识。比如:主键值是每一行记录的身份证号!!!

记住:任何一张表都应该有主键,没有主键,表无效!!

主键的特征:not null + unique(主键值不能是NULL,同时也不能重复!)

怎么给一张表添加主键约束呢?

drop table if exists t_vip;
// 1个字段做主键,叫做:单一主键
create table t_vip(
id int primary key, //列级约束
name varchar(255)
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');

//错误:不能重复
insert into t_vip(id,name) values(2,'wangwu');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'

//错误:不能为NULL
insert into t_vip(name) values('zhaoliu');
ERROR 1364 (HY000): Field 'id' doesn't have a default value

可以这样添加主键吗,使用表级约束? 可以

drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
primary key(id) // 表级约束
);
insert into t_vip(id,name) values(1,'zhangsan');

//错误
insert into t_vip(id,name) values(1,'lisi');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

表级约束主要是给多个字段联合起来添加约束?

drop table if exists t_vip;
// id和name联合起来做主键:复合主键!!!!
create table t_vip(
id int,
name varchar(255),
email varchar(255),
primary key(id,name)
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');

//错误:不能重复
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');
ERROR 1062 (23000): Duplicate entry '1-lisi' for key 'PRIMARY'

在实际开发中不建议使用:复合主键。建议使用单一主键!

因为主键值存在的意义就是这行记录的身份证号,只要意义达到即可,单一主键可以做到。

复合主键比较复杂,不建议使用!!!

一个表中主键约束能加两个吗?

drop table if exists t_vip;
create table t_vip(
id int primary key,
name varchar(255) primary key
);
ERROR 1068 (42000): Multiple primary key defined

结论:一张表,主键约束只能添加1个。(主键只能有1个。)

主键值建议使用:int、 bigint、char等类型。

不建议使用:varchar来做主键。主键值一般都是数字,一般都是定长的!

主键的另外一种分类方式
主键除了:单一主键和复合主键之外,还可以这样进行分类:

自然主键:主键值是一个自然数,和业务没关系。

业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值。这就是业务主键!

在实际开发中自然主键使用比较多,因为主键只要做到不重复就行,不需要有意义。
业务主键不好,因为主键一旦和业务挂钩,那么当业务发生变动的时候,可能会影响到主键值,所以业务主键不建议使用。尽量使用自然主键。

在mysql当中,有一种机制,可以帮助我们自动维护一个主键值 ——auto_increment ,此时主键类型最好是int,bigint。

drop table if exists t_vip;
create table t_vip(
id int primary key auto_increment, //auto_increment表示自增,从1开始,以1递增!
name varchar(255)
);
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
select * from t_vip;

+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
| 2 | zhangsan |
| 3 | zhangsan |
| 4 | zhangsan |
| 5 | zhangsan |
| 6 | zhangsan |
| 7 | zhangsan |
| 8 | zhangsan |
+----+----------+

外键约束(foreign key,简称FK)重点
外键约束的相关术语(继续废话)
外键约束:一种约束(foreign key)

外键字段:该字段上添加了外键约束

外键值:外键字段当中的每一个值。

业务背景:
请设计数据库表,来描述“班级和学生”的信息?

第一种方案:班级和学生存储在一张表中
t_student
no(pk) name classno classname
----------------------------------------------------------------------------------
1 jack 100 北京市大兴区亦庄镇第二中学高三1班
2 lucy 100 北京市大兴区亦庄镇第二中学高三1班
3 lilei 100 北京市大兴区亦庄镇第二中学高三1班
4 hanmeimei 100 北京市大兴区亦庄镇第二中学高三1班
5 zhangsan 101 北京市大兴区亦庄镇第二中学高三2班
6 lisi 101 北京市大兴区亦庄镇第二中学高三2班
7 wangwu 101 北京市大兴区亦庄镇第二中学高三2班
8 zhaoliu 101 北京市大兴区亦庄镇第二中学高三2班

以上方案的缺点:

数据冗余,空间浪费!!这个设计是比较失败的!

第二种方案:班级一张表、学生一张表
t_class 班级表
classno(pk) classname
------------------------------------------------------
100 北京市大兴区亦庄镇第二中学高三1班
101 北京市大兴区亦庄镇第二中学高三1班

t_student 学生表
no(pk) name cno(FK引用t_class这张表的classno)
----------------------------------------------------------------
1 jack 100
2 lucy 100
3 lilei 100
4 hanmeimei 100
5 zhangsan 101
6 lisi 101
7 wangwu 101
8 zhaoliu 101

当cno字段没有任何约束的时候,可能会导致数据无效。可能出现一个102,但是102班级不存在。所以为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束。那么:cno字段就是外键字段。cno字段中的每一个值都是外键值。

注意:t_class是父表、 t_student是子表

删除表的顺序:先删子,再删父。
创建表的顺序:先创建父,再创建子。
删除数据的顺序:先删子,再删父。
插入数据的顺序:先插入父,再插入子。
思考:子表中的外键引用的父表中的某个字段,被引用的这个字段必须是主键吗?

不一定是主键,但至少具有unique约束。

思考测试:外键可以为NULL吗?

外键值可以为NULL。

完成上述表的设计:

drop table if exists t_students;
drop table if exists t_class;
create table t_class(
classno int primary key,
classname varchar(255)
);
create table t_student(
no int primary key auto_increment,
name varchar(255),
cno int)
foreign key(cno) references t_class(classno)
);

存储引擎
什么是存储引擎,有什么用
存储引擎是MySQL中特有的一个术语,其它数据库中没有。(Oracle中有,但是不叫这个名字)
实际上存储引擎是一个表存储/组织数据的方式。
不同的存储引擎,表存储数据的方式不同。
怎么给表添加/指定“存储引擎”呢?

show create table t_student;//展示出创建该表的存语句
可以在建表的时候给表指定存储引擎。

CREATE TABLE `t_student` (
`no` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cno` int(11) DEFAULT NULL,
PRIMARY KEY (`no`),
KEY `cno` (`cno`),
CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `t_class` (`classno`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

在建表的时候可以在最后小括号的")"的右边使用:

ENGINE来指定存储引擎。

CHARSET来指定这张表的字符编码方式。

结论:

mysql默认的存储引擎是:InnoDB

mysql默认的字符编码方式是:utf8

建表时指定存储引擎,以及字符编码方式。

create table t_product(
id int primary key,
name varchar(255)
)engine=InnoDB default charset=gbk;//此时可以向表中写入中文了

如何查看mysql支持哪些存储引擎呢?
命令:

show engines \G

*************************** 1. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: FEDERATED
Support: NO
Comment: Federated MySQL storage engine
Transactions: NULL
XA: NULL
Savepoints: NULL
*************************** 5. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 6. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 7. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 8. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 9. row ***************************
Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
Transactions: NO
XA: NO
Savepoints: NO
9 rows in set (0.01 sec)

mysql支持九大存储引擎,版本不同支持情况不同。

mysql常用的存储引擎
MyISAM存储引擎
它管理的表具有以下特征:
使用三个文件表示每个表:
①格式文件 — 存储表结构的定义(mytable.frm)desc …
②数据文件 — 存储表行的内容(mytable.MYD)
③索引文件 — 存储表上索引(mytable.MYI):索引相当于目录,缩小扫描范围,是提高查询效率的一种机制。
提示:对于一张表来说,只要是主键,或者加有unique约束的字段上会自动创建索引。

MyISAM存储引擎特点:
①由于该存储引擎全是文件形式,所以可被转换为压缩、只读表来节省空间.
②MyISAM不支持事务机制,安全性低。

InnoDB存储引擎
这是mysql默认的存储引擎,同时也是一个重量级的存储引擎。
InnoDB支持事务,支持数据库崩溃后自动恢复机制。

InnoDB存储引擎最主要的特点是:非常安全。

它管理的表具有下列主要特征:
①每个 InnoDB 表在数据库目录中以.frm 格式文件表示,.ibd存放数据和索引。
② InnoDB 表空间 tablespace 被用于存储表的内容(表空间是一个逻辑名称。表空间存储数据+索引。)
③提供一组用来记录事务性活动的日志文件
④ 用 COMMIT(提交)、SAVEPOINT 及ROLLBACK(回滚)支持事务处理
⑤提供全 ACID 兼容
⑥在 MySQL 服务器崩溃后提供自动恢复
⑦多版本(MVCC)和行级锁定
⑧支持外键及引用的完整性,包括级联删除和更新

InnoDB最大的特点就是支持事务:
以保证数据的安全。效率不是很高,并且也不能压缩,不能转换为只读,不能很好的节省存储空间。

MEMORY存储引擎
使用 MEMORY 存储引擎的表,其数据存储在内存中,且行的长度固定,这两个特点使得 MEMORY 存储引擎非常快。

MEMORY 存储引擎管理的表具有下列特征:
①在数据库目录内,每个表均以.frm 格式的文件表示。
② 表数据及索引被存储在内存中。(目的就是快,查询快!)
③表级锁机制。
④不能包含 TEXT 或 BLOB 字段。

MEMORY 存储引擎以前被称为HEAP 引擎。

MEMORY引擎优点:查询效率是最高的。不需要和硬盘交互。

MEMORY引擎缺点:不安全,关机之后数据消失。因为数据和索引都是在内存当中。

 

各种存储引擎对比
————————————————
版权声明:本文为CSDN博主「Dutkig」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44824574/article/details/123031150

posted on 2023-03-06 11:19  宇辰滴滴  阅读(20)  评论(0编辑  收藏  举报