目录
创建数据库
管理数据库
查看当前的数据库有哪些:
切换数据库
查看数据表
修改数据库
更改数据库字符集
删除数据库
创建数据表
修改表
添加一个字段
修改一个字段
重命名一个字段
删除一个字段
重命名表
清空表
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
数据类型
创建数据表:
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
对比TRUNCATETABLE和DELETE FROM
- # 相同点:都可以实现对表中所有数据的删除,同时保留表结构。
- #不同点:
- TRUNCATE TABLE:一旦执行此操作,表数据全部清除。同时,数据是不可以回滚的。会自动commit
- DELETE FROM:一旦执行此操作,表数据可以全部清除(不带WHERE)。同时,数据是可以实现回滚
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 ;
在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。
它们的区别如下表所示:
显示范围,可以在定义时设置显示范围,一般搭配zerofill使用
意思是如果字符不足5位,那么前面拿0填充,超过5位不管
CREATE TABLE mytest2(
a INT,
b INT(5) ZEROFILL
)
- TINYINT :一般用于枚举数据,比如系统设定取值范围很小且固定的场景。
- SMALLINT :可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等。
- MEDIUMINT :用于较大整数的计算,比如车站每日的客流量等。
- INT、INTEGER :取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号。
- BIGINT :只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等
浮点数和定点数类型的特点是可以处理小数 ,你可以把整数看成小数的一个特例。因此,浮点数和定点
数的使用场景,比整数大多了。 MySQL支持的浮点数类型,分别是 FLOAT、DOUBLE、REAL
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),你就无法用一个二进制数来精确表达。进而,就只好在取值允许的范围内进行四舍五入。
使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65,0<=D<=30,D BIT类型,如果没有指定(M),默认是1位。这个1位,表示只能存1位的二进制值。这里(M)是表示二进制的位数,位数最小值为1,最大值为64 YEAR类型用来表示年份,在所有的日期时间类型中所占用的存储空间最小,只需要 1个字节的存储空间。 当取值为01到69时,表示2001到2069; 从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”,没必要写成YEAR(4), DATE类型表示日期,没有时间部分,格式为 YYYY-MM-DD ,其中,YYYY表示年份,MM表示月份,DD表示日期。需要 3个字节的存储空间。在向DATE类型的字段插入数据时,同样需要满足一定的格式条件。 TIME类型用来表示时间,不包含日期部分。在MySQL中,需要 3个字节的存储空间来存储TIME类型的数据,可以使用“HH:MM:SS”格式来表示TIME类型,其中,HH表示小时,MM表示分钟,SS表示秒。 (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类型在所有的日期时间类型中占用的存储空间最大,总共需要 8个字节的存储空间。在格式上为DATE类型和TIME类型的组合,可以表示为 YYYY-MM-DD HH:MM:SS ,其中YYYY表示年份,MM表示月份,DD表示日期,HH表示小时,MM表示分钟,SS表示秒 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和DATETIME的区别: 可以使用set time_zone = '+9:00',设置时区(这里是东九区) MySQL中,文本字符串总体上分为 CHAR 、 VARCHAR 、 TINYTEXT 、 TEXT 、 MEDIUMTEXT 、LONGTEXT 、 ENUM 、 SET等类型 CHAR类型: VARCHAR类型: 在MySQL中,TEXT用来保存文本类型的字符串,总共包含4种类型,分别为TINYTEXT、TEXT、 由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做主键。遇到这种情况,你只能采用CHAR(M),或者 VARCHAR(M)。 ENUM类型也叫作枚举类型,ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时,ENUM类型只允许从成员中选取单个值,不能一次选取多个值 举个例子,创建了一个表,里面设置了一个枚举变量season,设置了五个范围,那么插入的值只能从这五个值中选择 可以直接插入值: 插入索引也是ok的 MySQL中的二进制字符串类型主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数 约束是表级的强制规定。 根据约束数据列的限制,约束可分为: 查看已经存在的约束: 限定某个字段/某列的值不允许为空,只能针对某个列设置 1、在创建表的时候添加: 2、在alter table时添加约束 3、删除约束 用来限制某个字段/某列的值不能重复 添加约束: 这里添加约束用了两种方法,第二种可以给约束命名、 或者 如果不人为命名,则拿列名作为约束名字 注意,可以在申明UNIQUE的字段上添加null值,且可以多次添加 添加约束2: 添加表级约束 只要id和lastname不同时一样就OK 删除唯一性约束 约束名字可以通过以下方式查询 用来唯一标识表中的一行记录。 主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。 删除主键约束(在实际中不可能做这个操作) 某个字段的值自增 (1)一个表最多只能有一个自增长列 这里主要关注第3点,自增列必须设置为 主键列或者唯一键列,这个很好理解,因为自增列是很适合作为唯一标识的 可以执行以下操作 插入四个空值 这个时候id应该是1,2,3,4 删除id为4的数据 再次插入一个空值 这个时候id 是1,2,3,5 再删除id为5 的数据 然后重启mysql,重新插入一个空值。 在MySQL 5.7系统中,对于自增主键的分配规则,是由InnoDB数据字典内部一个计数器来决定的,而该计数器只在内存中维护 ,并不会持久化到磁盘中。当数据库重启时,该计数器会被初始化。 所以此时id为1,2,3,4 MySQL 8.0将自增主键的计数器持久化到重做日志中。每次计数器发生改变,都会将其写入重做日志中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。 所以此时id为1,2,3,6 限定某个表的某个字段的引用完整性。 例如这里,department表(主表)中的department_id是主键promary key,employees表(子表)中的department_id是外键,那么外键的值必须包含在主键中。 特点: (1)从表的外键列,必须引用/参考主表的主键或唯一约束的列 (8)当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是外键的约束名。(根据外键查询效率很高) CONSTRAINT FOREIGN KEY(外键约束列) REFERENCES 主表(主键约束列) 约束等级 如果没有指定等级,就相当于Restrict方式。 在 MySQL 里,外键约束是有成本的,需要消耗系统资源。对于大并发的 SQL 操作,有可能会不适合。比如大型网站的中央数据库,可能会因为外键约束的系统开销而变得非常慢 。所以, MySQL 允许你不使用系统自带的外键约束,在应用层面完成检查数据一致性的逻辑。也就是说,即使你不用外键约束,也要想办法通过应用层面的附加逻辑,来实现外键约束的功能,确保数据的一致性 (概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发 ,不适合分布式 、高并发集群 ;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度 检查某个字段的值是否符号xx要求,一般指的是值的范围 MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警告,但是MySQL 8.0中可以使用check约束了 给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。 面试1、为什么建表时,加 not null default '' 或 default 0 在MySQL中,默认AUTO_INCREMENT的初始值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一
位类型
日期与时间类型
YEAR类型
在MySQL中,YEAR有以下几种存储格式:
当取值为70到99时,表示1970到1999;
当取值整数的0或00添加的话,那么是0000年;
当取值是日期/字符串的'0'添加的话,是2000年。
从MySQL 8.0.19开始,不推荐使用指定显示宽度的YEAR(4)数据类型。CREATE TABLE test_year(
f1 YEAR,
f2 YEAR(4)
);
DATE类型
TIME类型
在MySQL中,向TIME类型的字段插入数据时,也可以使用几种不同的格式。 DATETIME类型
TIMESTAMP类型
存储数据的时候需要对当前时间所在的时区进行转换,查询数据的时候再将时间转换回当前的时区。因此,使用TIMESTAMP存储的同一个时间值,在不同的时区查询时会显示不同的时间。
向TIMESTAMP类型的字段插入数据时,当插入的数据格式满足YY-MM-DD HH:MM:SS和YYMMDDHHMMSS时,两位数值的年份同样符合YEAR类型的规则条件,只不过表示的时间范围要小很多。如果向TIMESTAMP类型的字段插入的时间超出了TIMESTAMP类型的范围,则MySQL会抛出错误信息
文本字符串类型
CHAR与VARCHAR类型
TEXT类型
MEDIUMTEXT 和 LONGTEXT 类型。
在向TEXT类型的字段保存和查询数据时,系统自动按照实际长度存储,不需要预先定义长度。这一点和VARCHAR类型相同。
每种TEXT类型保存的数据长度和所占用的存储空间不同,如下: ENUM类型
CREATE TABLE test_enum(
season ENUM('春','夏','秋','冬','unknow')
);
INSERT INTO test_enum
VALUES('春'),('秋');
INSERT INTO test_enum
VALUES('1'),(3);
二进制字符串类型
据。
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 = '表名称';
非空约束
CREATE TABLE constest(
id INT NOT NULL,
lastname CHAR(10) NOT NULL,
job CHAR(15)
)
ALTER TABLE constest
MODIFY job CHAR(15) NOT NULL
ALTER TABLE constest
MODIFY job CHAR(15) NULL
唯一性约束
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)
)
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)
)
ALTER TABLE constest
DROP INDEX 约束名字
SELECT * FROM information_schema.table_constraints
WHERE table_name = '表名字';
PRIMARY KEY 约束
create table temp(
id int primary key,
name varchar(20)
);
alter table 表名称 drop primary key;
自增列:AUTO_INCREMENT
(2)当需要产生唯一标识符或顺序值时,可设置自增长
(3)自增长列约束的列必须是键列(主键列,唯一键列)
(4)自增约束的列的数据类型必须是整数类型
(5)如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值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)
DELETE FROM test1 WHERE id = 4;
INSERT INTO test1 VALUES(0);
DELETE FROM test1 WHERE id = 5;
INSERT INTO test1 values(0);
外键约束
比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。
为什么?因为被依赖/被参考的值必须是唯一的
(2)在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名(例如student_ibfk_1;),也可以指定外键约束名。
(3)创建(CREATE)表时就指定外键约束的话,先创建主表,再创建从表
(4)删表时,先删从表(或先删除外键约束),再删除主表
(5)当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据
(6)在“从表”中指定外键约束,并且一个表可以建立多个外键约束
(7)从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。如果类型不一样,创建子表时,就会出现错误“ERROR 1005 (HY000): Can't create
table'database.tablename'(errno: 150)”
(9)删除外键约束后,必须手动删除对应的索引
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)
)
对于外键约束,最好是采用: 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
)
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 '' #默认是空字符串
);
答:不想让表中出现null值。
面试2、为什么不想要 null 的值
答:(1)不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
(2)效率不高。影响提高索引效果。因此,我们往往在建表时 not null default '' 或 default 0
面试3、带AUTO_INCREMENT约束的字段值是从1开始的吗?
条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。
面试4、并不是每个表都可以任意选择存储引擎? 外键约束(FOREIGN KEY)不能跨引擎使用。
MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的