MySQL基础(三)增删改查、数据类型、约束

目录

创建数据库

管理数据库

查看当前的数据库有哪些:

切换数据库

查看数据表

修改数据库

更改数据库字符集

删除数据库

创建数据表

修改表

添加一个字段

修改一个字段

重命名一个字段

删除一个字段

重命名表

清空表

commit 和 rollback 

拓展:MySQL8新特性—DDL的原子化

增删改

插入数据

更新数据

删除数据

计算列

数据类型精讲

整数类型

浮点类型

定点数(重要)

位类型 

日期与时间类型

  YEAR类型

 DATE类型

 TIME类型

 DATETIME类型 

TIMESTAMP类型 

文本字符串类型

 CHAR与VARCHAR类型

TEXT类型 

 ENUM类型

二进制字符串类型

约束

约束的分类

非空约束

唯一性约束

PRIMARY KEY 约束

自增列:AUTO_INCREMENT

 MySQL 8.0新特性—自增变量的持久化

外键约束

check约束

DEFAULT约束


创建数据库

方式1: 

CREATE DATABASE mytest

用这种方法创建数据库使用的是默认的字符集

方式2: 

也可以指明数据库的字符集

CREATE DATABASE mytest CHARACTER SET 'gbk'

方式3:

CREATE DATABASE IF NOT EXISTS mytest CHARACTER SET 'gbk'

当数据库不存在时才创建

管理数据库

查看当前的数据库有哪些

SHOW DATABASES

切换数据库

USE mytest

查看数据表

SHOW TABLES FROM mytest

修改数据库

更改数据库字符集

ALTER DATABASE mytest CHARACTER SET 'UTF8'

mysql不支持修改数据库的名字

删除数据库

DROP DATABASE mytest

创建数据表

数据类型

MySQL基础(三)增删改查、数据类型、约束_第1张图片

创建数据表: 


create tabLE IF NOT EXISTS mytable(
id int,
your_name varchar(15),
hire_Data date
);

方式2:基于现有的表,同时导入数据

并且这个时候的别名将作为新表的字段名

CREATE TABLE mytest1
AS
SELECT e.employee_id,e.last_name,d.department_name
FROM employees e JOIN departments d
ON e.department_id = d.department_id

案例:创建一个新表,复制employees表,但是不要表数据

create table mytest2
as
select *
from employees 
where 1= 2 

修改表

添加一个字段

ALTER TABLE mytest1
ADD salary DOUBLE(10,2)

默认是添加到表的最后

也可以添加到设定的位置,例如加到employ_id的后面

ALTER TABLE mytest1
ADD phone_number varchar(10) after employee_id

修改一个字段

修改数据类型

ALTER TABLE mytest1
MODIFY last_name VARCHAR(35)

重命名一个字段

ALTER TABLE mytest1
change salary money double(10,2)

删除一个字段

ALTER TABLE mytest1
DROP COLUMN money

重命名表

ALTER TABLE mytest1
RENAME TO mytest2

清空表

TRUNCATE TABLE mytest1
DELETE FROM mytest1

 对比TRUNCATETABLEDELETE FROM

  • # 相同点:都可以实现对表中所有数据的删除,同时保留表结构。
  • #不同点:
    • TRUNCATE TABLE:一旦执行此操作,表数据全部清除。同时,数据是不可以回滚的。会自动commit
    • DELETE FROM:一旦执行此操作,表数据可以全部清除(不带WHERE)。同时,数据是可以实现回滚

commit 和 rollback 

commit :提交数据,提交完之后不能撤销

rollback:回滚数据,类似于撤销

  DDL和DML的说明

  • DDL的操作一旦执行,就不可回滚。指令set autocommit = FALSE对DDL操作失效。
  • DML的操作默认情况,一旦执行,也是不可回滚的。但是,如果在执行DML之前,执行了SET autocommit = FALSE,则执行的DML操作就可以实现回滚。

 结果下面的操作,表不变

COMMIT ;
SET autocommit = FALSE;
DELETE FROM mytest1;
ROLLBACK ;COMMIT ;
SET autocommit = FALSE;
DELETE FROM mytest1;
ROLLBACK ;

拓展:MySQL8新特性—DDL的原子化

在MySQL 8.0版本中,InnoDB表的DDL支持事务完整性,即 DDL操作要么成功要么回滚 。DDL操作回滚日志 写入到data dictionary数据字典表mysql.innodb_ddl_log(该表是隐藏的表,通过show tables无法看到) 中,用于回滚操作。通过设置参数,可将DDL操作日志打印输出到MySQL错误日志中。

举个例子,先创建一个表

CREATE DATABASE mytest;
USE mytest;
CREATE TABLE book1(
book_id INT ,
book_name VARCHAR(255)
);
SHOW TABLES;

 然后删除

DROP TABLE book1,book2

这里肯定是会报错的,因为不存在book2这个表,但是新特性显示,book1也没被删除,即要么全部成功,要么全部不成功

增删改

插入数据

方式1:

INSERT INTO mytest1
VALUES(244,232323,'lee','noo9')

这种方法一定要按照声明字段的先后顺序添加

方式2 :指明字段的顺序(推荐)

insert into mytest1(phone_number,last_name,department_name,employee_id)
values(322323,'lee','nooo',1000)

当然也可以添加多个数据

INSERT INTO mytest1(phone_number,last_name,department_name,employee_id)
VALUES
(322323,'lee','nooo',1000),
(322328,'lee1','nooo1',1001)

方式3:将查询结果插入表中

INSERT INTO mytest1(last_name,department_name,employee_id)
SELECT e.last_name,e.first_name,e.employee_id
FROM employees e
WHERE e.department_id IN(60,70)

注意,在这个例子中,mytest1的三个字段的数据结果一定要比employees这三个字段数据结构更长

更新数据

UPDATE mytest
SET last_name = 'lee'
WHERE employee_id = 100

使用 UPDATE ...SET....,一般来说搭配where使用,否则会批量修改

删除数据

DELETE FROM mytest
WHERE employee_id =101

同上

计算列

一个列是由另外几个列计算得到的

这里有几种情况

1、现在有一个表,且有一些数据了,希望创造一个列,由另外几个列计算得到

        首先添加一个列

        然后更新这个列

ALTER TABLE mytest
ADD salary1 DOUBLE(10,2);

UPDATE mytest
SET salary = employee_id*4;

这种方法得到的结果,salary不能随着employee_id变化而变化

2、现在有一个表,且有一些数据了,希望创造一个列,由另外几个列计算得到,且能随因变量变化而变

ALTER TABLE mytest
ADD salary1 DOUBLE(10,2) generated always AS (employee_id*3) virtual

使用这种方法salary能随着employee_id变化而变化

3、初始定义一个表,定义一个计算列

CREATE TABLE mytest1(
a INT,
b INT, 
c INT generated always AS (a+b)  virtual
)

那么后续在添加数据时只需要添加a和b,c会自动计算

数据类型精讲

整数类型

整数类型一共有 5 种,包括 TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)和 BIGINT。
它们的区别如下表所示:

MySQL基础(三)增删改查、数据类型、约束_第2张图片

显示范围,可以在定义时设置显示范围,一般搭配zerofill使用

意思是如果字符不足5位,那么前面拿0填充,超过5位不管

CREATE TABLE mytest2(
a INT,
b INT(5) ZEROFILL
)
  •  TINYINT :一般用于枚举数据,比如系统设定取值范围很小且固定的场景。
  • SMALLINT :可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等。
  • MEDIUMINT :用于较大整数的计算,比如车站每日的客流量等。
  • INT、INTEGER :取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号。
  • BIGINT :只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等

浮点类型

 浮点数和定点数类型的特点是可以处理小数 ,你可以把整数看成小数的一个特例。因此,浮点数和定点
数的使用场景,比整数大多了。 MySQL支持的浮点数类型,分别是 FLOAT、DOUBLE、REAL

MySQL基础(三)增删改查、数据类型、约束_第3张图片

 REAL默认就是 DOUBLE

为什么浮点数类型的无符号数取值范围,只相当于有符号数取值范围的一半,也就是只相当于有符号数取值范围大于等于零的部分呢?
MySQL 存储浮点数的格式为:符号(S) 、尾数(M)和 阶码(E) 。因此,无论有没有符号,MySQL 的浮点数都会存储表示符号的部分。因此, 所谓的无符号数取值范围,其实就是有符号数取值范围大于等于零的部分

MySQL允许使用非标准语法 (其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么
用): FLOAT(M,D)或 DOUBLE(M,D) 。这里,M称为精度 ,D称为标度 。(M,D)中 M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30。 

浮点数类型有个缺陷,就是不精准。比如,我们设计一个表,有f1这个字段,插入值分别为0.47,0.44,0.19,我们期待的运行结果是:0.47 + 0.44 + 0.19 =1.1。而使用sum之后查询 却是1.0999999

MySQL 用 4 个字节存储 FLOAT 类型数据,用 8 个字节来存储 DOUBLE 类型数据。无论哪个,都是采用二进制的方式来进行存储的。比如 9.625,用二进制来表达,就是 1001.101,或者表达成 1.001101×2^3。如果尾数不是 0 或 5(比如 9.624),你就无法用一个二进制数来精确表达。进而,就只好在取值允许的范围内进行四舍五入。

定点数(重要)

MySQL基础(三)增删改查、数据类型、约束_第4张图片

使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65,0<=D<=30,D

  •  DECIMAL(M,D)的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的。DECIMAL 的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节。也就是说,在一些对精度要求不高的场景下,比起占用同样字节长度的定点数,浮点数表达的数值范围可以更大一些。
  • 定点数在MySQL内部是以字符串的形式进行存储,这就决定了它一定是精准的。
  • 当DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。
  • 浮点数 vs 定点数
  • 浮点数相对于定点数的优点是在长度一定的情况下,浮点类型取值范围大,但是不精准,适用于需要取值范围大,又可以容忍微小误差的科学计算场景(比如计算化学、分子建模、流体动力学等)
  • 定点数类型取值范围相对小,但是精准,没有误差,适合于对精度要求极高的场景 (比如涉及金额计算的场景

位类型 

 BIT类型,如果没有指定(M),默认是1位。这个1位,表示只能存1位的二进制值。这里(M)是表示二进制的位数,位数最小值为1,最大值为64

日期与时间类型

MySQL基础(三)增删改查、数据类型、约束_第5张图片

  YEAR类型

YEAR类型用来表示年份,在所有的日期时间类型中所占用的存储空间最小,只需要 1个字节的存储空间。
在MySQL中,YEAR有以下几种存储格式:

  • 以4位字符串或数字格式表示YEAR类型,其格式为YYYY,最小值为1901,最大值为2155。
  • 以2位字符串格式表示YEAR类型,最小值为00,最大值为99。

当取值为01到69时,表示2001到2069;
当取值为70到99时,表示1970到1999;
当取值整数的0或00添加的话,那么是0000年;
当取值是日期/字符串的'0'添加的话,是2000年。

从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”,没必要写成YEAR(4),
从MySQL 8.0.19开始,不推荐使用指定显示宽度的YEAR(4)数据类型。

CREATE TABLE test_year(
f1 YEAR,
f2 YEAR(4)
);

 DATE类型

 DATE类型表示日期,没有时间部分,格式为 YYYY-MM-DD ,其中,YYYY表示年份,MM表示月份,DD表示日期。需要 3个字节的存储空间。在向DATE类型的字段插入数据时,同样需要满足一定的格式条件。

  • 以 YYYY-MM-DD格式或者 YYYYMMDD格式表示的字符串日期,其最小取值为1000-01-01,最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式。
  • 以 YY-MM-DD格式或者 YYMMDD格式表示的字符串日期,此格式中,年份为两位数值或字符串满足YEAR类型的格式条件为:当年份取值为00到69时,会被转化为2000到2069;当年份取值为70到99时,会被转化为1970到1999。
  • 使用 CURRENT_DATE()或者 NOW()函数,会插入当前系统的日期

 TIME类型

 TIME类型用来表示时间,不包含日期部分。在MySQL中,需要 3个字节的存储空间来存储TIME类型的数据,可以使用“HH:MM:SS”格式来表示TIME类型,其中,HH表示小时,MM表示分钟,SS表示秒。


在MySQL中,向TIME类型的字段插入数据时,也可以使用几种不同的格式

(1)可以使用带有冒号的字符串,比如' D HH:MM:SS' 、' HH:MM:SS '、' HH:MM '、' D HH:MM '、' D HH '或' SS '格式,都能被正确地插入TIME类型的字段中。其中D表示天,其最小值为0,最大值为34。如果使用带有D格式的字符串插入TIME类型的字段时,D会被转化为小时,计算格式为D*24+HH。当使用带有冒号并且不带D的字符串表示时间时,表示当天的时间,比如12:10表示12:10:00,而不是00:12:10。

(2)可以使用不带有冒号的字符串或者数字,格式为' HHMMSS '或者 HHMMSS 。如果插入一个不合法的字符串或者数字,MySQL在存储数据时,会将其自动转化为00:00:00进行存储。比如1210,MySQL会将最右边的两位解析成秒,表示00:12:10,而不是12:10:00。 (3)使用 CURRENT_TIME()或者 NOW() ,会插入当前系统的时间

 DATETIME类型 

DATETIME类型在所有的日期时间类型中占用的存储空间最大,总共需要 8个字节的存储空间。在格式上为DATE类型和TIME类型的组合,可以表示为 YYYY-MM-DD HH:MM:SS ,其中YYYY表示年份,MM表示月份,DD表示日期,HH表示小时,MM表示分钟,SS表示秒

  • YYYY-MM-DD HH:MM:SS格式或者 YYYYMMDDHHMMSS格式的字符串插入DATETIME类型的字段时,最小值为1000-01-01 00:00:00,最大值为9999-12-03 23:59:59。
  • YYYYMMDDHHMMSS格式的数字插入DATETIME类型的字段时,会被转化为YYYY-MM-DD HH:MM:SS格式
  • 以 YY-MM-DD HH:MM:SS格式或者 YYMMDDHHMMSS格式的字符串插入DATETIME类型的字段时,两位数的年份规则符合YEAR类型的规则,00到69表示2000到2069;70到99表示1970到1999。
  • 使用函数 CURRENT_TIMESTAMP()和 NOW() ,可以向DATETIME类型的字段插入系统的当前日期和时间。

TIMESTAMP类型 

TIMESTAMP类型也可以表示日期时间,其显示格式与DATETIME类型相同,都是 YYYY-MM-DDHH:MM:SS ,需要4个字节的存储空间。但是TIMESTAMP存储的时间范围比DATETIME要小很多,只能存储“1970-01-01 00:00:01 UTC”到“2038-01-19 03:14:07 UTC”之间的时间。其中,UTC表示世界统一时间,也叫作世界标准时间。


存储数据的时候需要对当前时间所在的时区进行转换,查询数据的时候再将时间转换回当前的时区。因此,使用TIMESTAMP存储的同一个时间值,在不同的时区查询时会显示不同的时间。


向TIMESTAMP类型的字段插入数据时,当插入的数据格式满足YY-MM-DD HH:MM:SS和YYMMDDHHMMSS时,两位数值的年份同样符合YEAR类型的规则条件,只不过表示的时间范围要小很多。如果向TIMESTAMP类型的字段插入的时间超出了TIMESTAMP类型的范围,则MySQL会抛出错误信息

 TIMESTAMP和DATETIME的区别:

  • TIMESTAMP存储空间比较小,表示的日期时间范围也比较小
  • 底层存储方式不同,TIMESTAMP底层存储的是毫秒值,距离1970-1-1 0:0:0 0毫秒的毫秒值。
  • 两个日期比较大小或日期计算时,TIMESTAMP更方便、更快。
  • TIMESTAMP和时区有关。TIMESTAMP会根据用户的时区不同,显示不同的结果。而DATETIME则只能
  • 反映出插入时当地的时区,其他时区的人查看数据必然会有误差的

可以使用set time_zone = '+9:00',设置时区(这里是东九区)

文本字符串类型

MySQL中,文本字符串总体上分为 CHAR 、 VARCHAR 、 TINYTEXT 、 TEXT 、 MEDIUMTEXT 、LONGTEXT 、 ENUM 、 SET等类型

MySQL基础(三)增删改查、数据类型、约束_第6张图片

 CHAR与VARCHAR类型

MySQL基础(三)增删改查、数据类型、约束_第7张图片

 CHAR类型:

  • CHAR(M) 类型一般需要预先定义字符串长度。如果不指定(M),则表示长度默认是1个字符。
  • 如果保存时,数据的实际长度比CHAR类型声明的长度小,则会在右侧填充空格以达到指定的长度。当MySQL检索CHAR类型的数据时,CHAR类型的字段会去除尾部的空格。
  • 定义CHAR类型字段时,声明的字段长度即为CHAR类型字段所占的存储空间的字节数。

VARCHAR类型:

  • VARCHAR(M) 定义时,必须指定长度M,否则报错。这个M相当于最长的长度
  • MySQL4.0版本以下,varchar(20):指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) ;MySQL5.0版本以上,varchar(20):指的是20字符。
  • 检索VARCHAR类型的字段数据时,会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加1个字节。

TEXT类型 

在MySQL中,TEXT用来保存文本类型的字符串,总共包含4种类型,分别为TINYTEXT、TEXT、
MEDIUMTEXT 和 LONGTEXT 类型。
在向TEXT类型的字段保存和查询数据时,系统自动按照实际长度存储,不需要预先定义长度。这一点和VARCHAR类型相同。
每种TEXT类型保存的数据长度和所占用的存储空间不同,如下:

MySQL基础(三)增删改查、数据类型、约束_第8张图片

由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做主键。遇到这种情况,你只能采用CHAR(M),或者 VARCHAR(M)。 

 ENUM类型

 ENUM类型也叫作枚举类型,ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时,ENUM类型只允许从成员中选取单个值,不能一次选取多个值

  • 当ENUM类型包含1~255个成员时,需要1个字节的存储空间;
  • 当ENUM类型包含256~65535个成员时,需要2个字节的存储空间。
  • ENUM类型的成员个数的上限为65535个。

 举个例子,创建了一个表,里面设置了一个枚举变量season,设置了五个范围,那么插入的值只能从这五个值中选择

CREATE TABLE test_enum(
season ENUM('春','夏','秋','冬','unknow')
);

可以直接插入值:

INSERT INTO test_enum
VALUES('春'),('秋');

插入索引也是ok的

INSERT INTO test_enum
VALUES('1'),(3);

二进制字符串类型

MySQL中的二进制字符串类型主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数
据。
MySQL中支持的二进制字符串类型主要包括BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和LONGBLOB类型

约束

约束是表级的强制规定。
可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束

约束的分类

根据约束数据列的限制,约束可分为:
        单列约束:每个约束只约束一列
        多列约束:每个约束可约束多列数据        
根据约束的作用范围,约束可分为:
        列级约束:只能作用在一个列上,跟在列的定义后面
        表级约束:可以作用在多个列上,不与列一起,而是单独定义
根据约束起的作用,约束可分为:
        NOT NULL 非空约束,规定某个字段不能为空
        UNIQUE 唯一约束,规定某个字段在整个表中是唯一的
        PRIMARY KEY 主键(非空且唯一)约束
        FOREIGN KEY 外键约束
        CHECK 检查约束
        DEFAULT 默认值约束

查看已经存在的约束:

SELECT * FROM information_schema.table_constraints 
WHERE table_name = '表名称';

非空约束

限定某个字段/某列的值不允许为空,只能针对某个列设置

  • 默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
  • 非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
  • 一个表可以有很多列都分别限定了非空空字符串''不等于NULL,0也不等于NULL

1、在创建表的时候添加:

CREATE TABLE constest(
id INT NOT NULL,
lastname CHAR(10) NOT NULL,
job CHAR(15)
)

2、在alter table时添加约束

ALTER TABLE constest
MODIFY job CHAR(15) NOT NULL

3、删除约束

ALTER TABLE constest
MODIFY job CHAR(15) NULL

唯一性约束

用来限制某个字段/某列的值不能重复

  • 同一个表可以有多个唯一约束。
  • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。
  • 唯一性约束允许列值为空。
  • 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。
  • MySQL会给唯一约束的列上默认创建一个唯一索引

 添加约束:

CREATE TABLE constest(
id INT UNIQUE,
lastname CHAR(10),
job CHAR(15),
CONSTRAINT uk_constest UNIQUE(lastname)
)

这里添加约束用了两种方法,第二种可以给约束命名、

或者

CREATE TABLE constest1(
id INT UNIQUE,
lastname CHAR(10),
job CHAR(15),
UNIQUE(lastname)
)

如果不人为命名,则拿列名作为约束名字

注意,可以在申明UNIQUE的字段上添加null值,且可以多次添加

添加约束2:

ALTER TABLE constest
MODIFY job CHAR(15) UNIQUE
#or
ALTER TABLE constest
ADD UNIQUE KEY(job)
#or
ALTER TABLE constest
ADD CONSTRAINT uk_constest UNIQUE(lastname)

 添加表级约束

CREATE TABLE constest(
id INT UNIQUE,
lastname CHAR(10) NOT NULL,
job CHAR(15),
CONSTRAINT uk_constest_pwd UNIQUE(id,lastname)
)

只要id和lastname不同时一样就OK

删除唯一性约束

  • 添加唯一性约束的列上也会自动创建唯一索引。
  • 删除唯一约束只能通过删除唯一索引的方式删除。
  • 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。
  • 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。
ALTER TABLE constest
DROP INDEX 约束名字

约束名字可以通过以下方式查询

SELECT * FROM information_schema.table_constraints 
WHERE table_name = '表名字';

PRIMARY KEY 约束

用来唯一标识表中的一行记录。

主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。

  • 一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别上创建。
  • 主键约束对应着表中的一列或者多列(复合主键)
  • 如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
  • MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
  • 当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了。
  • 需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性
create table temp(
    id int primary key,
    name varchar(20)
);

 删除主键约束(在实际中不可能做这个操作)

alter table 表名称 drop primary key;

自增列:AUTO_INCREMENT

某个字段的值自增

(1)一个表最多只能有一个自增长列
(2)当需要产生唯一标识符或顺序值时,可设置自增长
(3)自增长列约束的列必须是键列(主键列,唯一键列)
(4)自增约束的列的数据类型必须是整数类型
(5)如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值

 这里主要关注第3点,自增列必须设置为 主键列或者唯一键列,这个很好理解,因为自增列是很适合作为唯一标识的

CREATE TABLE test2(
    id INT PRIMARY KEY AUTO_INCREMENT,
    ename VARCHAR(20)
);

INSERT INTO test2(ename)
VALUES('aa'),('bb')

 MySQL 8.0新特性—自增变量的持久化

可以执行以下操作

CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT
);

插入四个空值

INSERT INTO test1
VALUES(0),(0),(0),(0)

这个时候id应该是1,2,3,4

删除id为4的数据

DELETE FROM test1 WHERE id = 4;

再次插入一个空值

INSERT INTO test1 VALUES(0);

这个时候id 是1,2,3,5

再删除id为5 的数据

DELETE FROM test1 WHERE id = 5;

然后重启mysql,重新插入一个空值。

INSERT INTO test1 values(0);

在MySQL 5.7系统中,对于自增主键的分配规则,是由InnoDB数据字典内部一个计数器来决定的,而该计数器只在内存中维护 ,并不会持久化到磁盘中。当数据库重启时,该计数器会被初始化。     

所以此时id为1,2,3,4

MySQL 8.0将自增主键的计数器持久化到重做日志中。每次计数器发生改变,都会将其写入重做日志中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。

所以此时id为1,2,3,6

外键约束

限定某个表的某个字段的引用完整性。
比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。

MySQL基础(三)增删改查、数据类型、约束_第9张图片

 例如这里,department表(主表)中的department_id是主键promary key,employees表(子表)中的department_id是外键,那么外键的值必须包含在主键中

特点:

(1)从表的外键列,必须引用/参考主表的主键或唯一约束的列
为什么?因为被依赖/被参考的值必须是唯一的
(2)在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名(例如student_ibfk_1;),也可以指定外键约束名。
(3)创建(CREATE)表时就指定外键约束的话,先创建主表,再创建从表
(4)删表时,先删从表(或先删除外键约束),再删除主表
(5)当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据
(6)在“从表”中指定外键约束,并且一个表可以建立多个外键约束
(7)从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。如果类型不一样,创建子表时,就会出现错误“ERROR 1005 (HY000): Can't create
table'database.tablename'(errno: 150)”

(8)当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是外键的约束名。(根据外键查询效率很高)
(9)删除外键约束后,必须手动删除对应的索引

CONSTRAINT FOREIGN KEY(外键约束列) REFERENCES 主表(主键约束列) 

CREATE TABLE father(
fid INT PRIMARY KEY,
lastname CHAR(10)
);

CREATE TABLE son(
sid INT,
firstname CHAR(11),
CONSTRAINT FOREIGN KEY(sid) REFERENCES father(fid)
)
  • 添加了外键约束后,主表的修改和删除数据受约束
  • 添加了外键约束后,从表的添加和修改数据受约束
  • 在从表上建立外键,要求主表必须存在
  • 删除主表时,要求从表从表先删除,或将从表中外键引用该主表的关系先删除

 约束等级 

  • Cascade方式 :在父表上update/delete记录时,同步update/delete掉子表的匹配记录
  • Set null方式 :在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null
  • No action方式 :如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
  • Restrict方式 :同no action, 都是立即检查外键约束
  • Set default方式 (在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别 

如果没有指定等级,就相当于Restrict方式。
对于外键约束,最好是采用: ON UPDATE CASCADE ON DELETE RESTRICT 的方式,也就是说在修改时可以同步修改,删除时限制删除

CREATE TABLE son1(
sid INT,
firstname CHAR(11),
CONSTRAINT FOREIGN KEY(sid) REFERENCES father(fid) ON UPDATE CASCADE ON DELETE RESTRICT
)

  在 MySQL 里,外键约束是有成本的,需要消耗系统资源。对于大并发的 SQL 操作,有可能会不适合。比如大型网站的中央数据库,可能会因为外键约束的系统开销而变得非常慢 。所以, MySQL 允许你不使用系统自带的外键约束,在应用层面完成检查数据一致性的逻辑。也就是说,即使你不用外键约束,也要想办法通过应用层面的附加逻辑,来实现外键约束的功能,确保数据的一致性

(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发 ,不适合分布式 、高并发集群 ;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度 

check约束

检查某个字段的值是否符号xx要求,一般指的是值的范围

MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警告,但是MySQL 8.0中可以使用check约束了

CREATE TABLE test10(
id INT,
lastname CHAR(15),
salary DECIMAL(10,2) CHECK(salary > 2000)
)

DEFAULT约束

给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。

create table employee(
    eid int primary key,
    ename varchar(20) not null,
    gender char default '男',
    tel char(11) not null default '' #默认是空字符串
);

面试1、为什么建表时,加 not null default '' 或 default 0
答:不想让表中出现null值。
面试2、为什么不想要 null 的值
答:(1)不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
(2)效率不高。影响提高索引效果。因此,我们往往在建表时 not null default '' 或 default 0
面试3、带AUTO_INCREMENT约束的字段值是从1开始的吗?

在MySQL中,默认AUTO_INCREMENT的初始值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一
条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。
面试4、并不是每个表都可以任意选择存储引擎? 外键约束(FOREIGN KEY)不能跨引擎使用。
MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的

你可能感兴趣的:(MySQL,数据库)