MySQL数据库必备知识

MySQL数据库基础知识

一、数据库说明

1.1 什么是数据库

数据库(Database)是一种存储结构化数据的方式,一般存在两种类型的数据库: 关系型数据库、非关系型数据库。

关系型数据库: 存储二维关系表的仓库, 二维关系表是由列(特征)和行组成的。提供标准的SQL语句进行管理(创建、修改、删除)。关系型数据库一般都支持约束、索引、视图、函数、存储过程、触发器、表、字典(动态视图)等对象。【重点】

非关系型数据库: 不需要使用SQL,通过SDK(软件开发环境-模块或库, Software Development Kit)相关的方法进行操作,不支持二维关系结构,又称之为NoSQL数据库。包含redis、mongodb等。

1.2 有哪些关系型数据库

大厂的关系型数据库: DB2(IBM公司)、Oracle(甲骨文公司)、MySQL(原Sun公司,目前也是甲骨文公司)。

其它的关系型数据库:MariDB(个人, 同MySQL一个作者)、 posgreSQL(开源的数据库)

Hadoop家族的数据库: Hive(依赖MySQL, MapReduce), Hbase(实时)

嵌入式设备中的数据库: sqlite3(没有特定的数据类型)、IotDB(分布式物联网存储的实时数据库)

1.3 数据范式

限制表的设计, 让表的结构更合理、减少数据冗余。

如设计存储书相关信息的表:

ID 书编号
name 书名
cover 封面图片连接
summary 介绍
author 作者
author_years 作者的写作年限
author_nickname 作者别名
author_info 作者的介绍
author_jg   作者的家乡
author_primary_book_name 作者代表作品
store_name 书店名称
store_city 书店所在的城市
store_boss 书店的老板姓名
store_tel  书店的联系电话
publish_date 书的发布时间
publisher   出版社

假如 某一个作者有10本书,作者的相关信息重复了10次,每一条数据的作者相关信息存在近500个汉字,按UTF8编码计算,每一行作者数据的字节大小为 500*3=1500,近1.2K, 10条件记录近12K。

表的第一范式: 确保每一个列保持原子性(列不可分隔)。

根据第一范式分隔书的表为某本书的表、作者表、书店表:

-- book表
ID 书编号
name 书名
cover 封面图片连接
summary 介绍
publisher   出版社
publish_date 书的发布时间

-- 作者表
author 作者姓名
author_years 作者的写作年限
author_nickname 作者别名
author_info 作者的介绍
author_jg   作者的家乡
author_primary_book_name 作者代表作品

-- store 书店表
store_name 书店名称
store_city 书店所在的城市
store_boss 书店的老板姓名
store_tel  书店的联系电话

表的第二范式: 确保每一列的数据都和主键相关, 即表中存在主键约束。

-- 作者表
ID 作者编号(主键)
author 作者姓名
author_years 作者的写作年限
author_nickname 作者别名
author_info 作者的介绍
author_jg   作者的家乡
author_primary_book_name 作者代表作品

-- store 书店表
ID 书店(主键)
store_name 书店名称
store_city 书店所在的城市
store_addres 书店的地址
store_boss 书店的老板姓名
store_tel  书店的联系电话

表的第三范式: 确保每一列都和主键直接相关,而不能间接相关。即存在主外键关系。

-- book表
ID 书编号
name 书名
..
author_id 作者的ID, 外键
store_id  书店的ID, 外键

二、DDL语句

DDL 数据库描述或定义语言(Data Definition Language),包含数据库、表、视图、函数、索引、存储过程、触发器等对象的创建、修改和删除等操作。

2.1 创建和删除数据库

创建数据库语法:

create database <数据库名> [ charset <字符集> ];

如,创建bookdb数据库

create database bookdb;

删除数据库,即将库中所有对象全部删除【慎用】

drop database [if exists] <数据库名称>;

if exists 确保SQL正常执行,如果数据库存在,则删除,不存在pass。

如,删除bookdb库

drop database bookdb;

2.2 创建表

官方文档:https://dev.mysql.com/doc/refman/8.0/en/create-table.html

创建表之前,必须先使用 use <数据库名> 语句打开某一个数据库,表示在某一数据库下创建表。

简洁的语法:

create table [if not exists] <表名>(
   <字段名> <字段类型>[ (字段数据长度) ] [约束] [comment 注释文本],
   ...,
   [constraint 表级约束语句]
) [engine=INNODB|MYISAM|MEMERY|CSV] [character set 字符集];

说明:

  • 字段名,不能和数据库的关系冲突,一般同Python语言标识符的命名类同,由字母、数字和下划线及特殊符号组成。

  • 字段类型,mysql提供了丰富的字段类型,包含:

    • 字符类型char, 固定长度的字符类型,即分配多少长度(字符的个数),即用多少长度。

      【扩展】正则表达式中匹配中文的unicode编码范围: \u4e00-\u9fa5

    • 可变字符类型varchar,与char不同,根据内容器的多少,使用多少。不会使用给定的最大长度。

    • 整数类型intinteger

    • 小数类型floatdoubledecimal(可以设置小数点后的精确位)

    • 日期类型 date

    • 日期时间类型timestamp 包含日期部分和时间部分

    • 文本类型 text

    • 大文本类型clob

    • 二进制类型 blob

  • 约束, 根据不同的约束类型,检查数据,如果不合法,则抛出异常显示违反xxx约束。

    • 主键约束 primary key: 非空,唯一的
    • 外键约束 foreign key: 值,依赖于外部主表的主键值。外键字段的值可以为空的。
    • 唯一约束 unique : 值在整个一列中是唯一的 ,值可以存在一个空值。
    • 非空约束 not null : 列值不能为空
    • 默认值 default : 列值在设计时,可以指定默认值
    • 自增 auto_increment: 列值是某一个序列的下一个值,不需要指定。
  • 引擎

    • InnoDB : 支持事务、行级锁、外键约束 【默认】
    • MEMERY: 使用hash函数, 存储于内存,使用临时表。用于缓存
    • MyISAM: 不支持事务、行级锁和外键约束
    • CSV: 以CSV格式存储数据

如,创建附合第三个范式的图书表、作者表

drop database if exists bookdb;
create database bookdb;
use bookdb;

drop table if exists author;
drop table if exists book;

create table if not exists author
(
    author_id integer primary key auto_increment,
    name varchar(20),
    city varchar(20),
    phone char(11)
);


create table if not exists book
(
    book_id integer  auto_increment comment '图书编号',
    name varchar(50) unique comment '书名',
    summary text comment '简介',
    price decimal(5, 2) comment '单价',
    act_price decimal(5, 2) comment '活动价',
    cover_url varchar(100) comment '封面的URL地址',
    author_id integer,
    constraint book_pk  primary key (book_id),
    constraint book_author_fk foreign key (author_id) references author(author_id) on delete cascade
);

show tables;

【重要说明】constraint子句

constraint [约束名称] 约束类型 [index_type: {BTREE, HASH}] (字段名,...)
[references 引用表的名称(引用的字段名)  on   ]

约束类型: primary key、unique、foreign key

只有primary key和unique 存在index_type关键字

只有foreign key 存在 references 关键字。

【扩展-docker创建与宿主机同步的mysql容器】

准备工作:

  1. 确认 /root/mysql 目录是否从某一个mysql已运行容器的/etc/mysql复制的
  2. 确认/root/mysql/my.cnf 文件中关于character-set-server 是否配置
  3. 确认/root/mysql/conf.d/mysql.cnf 文件中default-character-set是否配置
  4. 确认/root/mysql/sql/init.sql 脚本是否存在
docker run -d --name db000 -e MYSQL_ROOT_PASSWORD=root -p 3313:3306 --network db-net -v /root/mysql:/etc/mysql mysql
docker exec db000 ls /etc/mysql
docker exec -it db000 mysql -uroot -proot
mysql> show databases;
mysql> create database if not exists bookdb;
mysql> use bookdb;
mysql> source /etc/mysql/sql/init.sql
mysql> show tables;

2.3 修改表

修改表: 表名、表字段名、字段类型及字段的约束。

2.3.1 修改表名
alter table <表名> rename [to | as] <新表名>;

修改book表为tb_book

alter table book rename as tb_book;

修改author表为tb_author

alter table author rename to tb_author;
2.3.2 修改字段名
alter table <表名> change [column] <旧列名> <新列名> <类型[(长度)]>

修改tb_book表中的name字段为book_name

alter table tb_book change column name book_name varchar(40);

修改tb_book表的pricesrc_price名称,数据类型保持不变

alter table tb_book change price src_price decimal(5,2);
2.3.3 修改字段类型
alter table <表名> modify <列名> <类型[(数据长度)]> [约束]

修改tb_book表的summary的类型改为 varchar,且数据长度为200个字符

alter table tb_book modify summary varchar(200);
2.3.4 删除字段主外键约束
2.3.4.1 删除外键约束
alter table <表名> drop foreign key <约束名称>;

删除tb_book表的book_author_fk外键约束:

alter table tb_book drop foreign key book_author_fk;
2.3.4.2【查询表的相关约束】

依据information_schema字典库的table_constraints表

查询bookdb数据库中所有表的约束信息

select table_name,constraint_name, constraint_type
from information_schema.table_constraints 
where table_schema='bookdb';
+------------+-----------------+-----------------+
| TABLE_NAME | CONSTRAINT_NAME | CONSTRAINT_TYPE |
+------------+-----------------+-----------------+
| tb_author  | PRIMARY         | PRIMARY KEY     |
| tb_book    | name            | UNIQUE          |
| tb_book    | PRIMARY         | PRIMARY KEY     |
| tb_book    | book_author_fk  | FOREIGN KEY     |
+------------+-----------------+-----------------+
2.3.4.3 删除主键约束
alter table <表名> drop primary key;

删除tb_author表的主键约束

alter table tb_author modify author_id integer ;
alter table tb_author drop primary key;
2.3.4.4 删除唯一约束
alter table <表名> drop {
  index|key} 唯一约束名或列名

【注意】默认情况唯一约束名即为列名。

删除tb_book表的name字段的唯一约束

alter table tb_book drop index name;
2.3.5 删除字段
alter table <表名> drop [column] <字段名>; 

删除tb_book的summary字段

alter table tb_book drop summary;

删除tb_book的author_id字段

alter table tb_book drop author_id;
2.3.6 添加字段
alter table <表名> 
add [column] <列名> 数据类型[(数据长度)] [约束] [comment 注释信息]

添加tb_book的summary字段,类型为text, 不能为空

alter table tb_book
add column summary text not null;

添加tb_book的author_id字段,类型为integer

alter table tb_book
add column author_id integer;
2.3.7 添加字段约束
alter table <表名>
add [constraint [约束名] ] 
| primary key [index_type: {using btree|hash}] (字段1, 字段2, ....) 
| unique [key | index ] [index_name] [index_type] (字段1, 字段2, ...)
| foreign key (字段1, 字段2,...) references 引用表名(字段1,字段2, ...) [on delete|update restrict|cascade|set null|no action|set default]

【索引分类】主键索引、唯一索引、普通索引、组合索引

【索引类型】BTREE、HASH

添加tb_author表的author_id字段的主键约束,并设置为自增

alter table tb_author modify author_id integer primary key auto_increment;
-- alter table tb_author add primary key (author_id);

添加tb_book的author_id的外键约束,引用tb_author的author_id字段

alter table tb_book
add constraint book_author_fk foreign key (author_id) references tb_author(author_id);

2.4 删除表

drop table [if exists] <表名>

如,删除tb_book表

drop table tb_book;

【注意】无论是删除表或列,则表存在的相关约束都会被删除。

2.5 查询表结构

方式1:

DESC <表名>

方式2:

show create table <表名>

查看表创建时的SQL语句。

同样,查看数据库的创建SQL语句:

show create database <数据库名>

2.6 查看所有的表

方式1: show tables

方式2: 使用information_schema字典的tables表

select table_name,table_type,table_schema
from information_schema.tables
where table_schema='bookdb';

2.7 子查询创建表

基于SQL查询语句,快速创建一张无约束的表。

create table <表名>
select子句;

如:创建北京作者信息的表

create table tb_bejin_author
select * from tb_author where city='北京';

三、DML语句

DML(Data Manipulation Language) 数据操纵语言,主要负责数据(行或记录)的插入、更新和删除操作。

3.1 insert语句

insert语句是向表中插入一行或多行数据。

3.1.1 单行数据插入
insert into <表名> [(字段1, 字段2, ...)]
values (字段值1, 字段值2, ...)

说明:

  • 表名之后,通过()声明向哪些字段插入数据;默认是全部字段,插入值的顺序按创建表时声明字段顺序。
  • values后的()中不同类型的数据,必须按插入值字段的类型匹配,如字符类型必须使用单引号'',数值类型不能使用单引号,日期类型可以使用单引号。

如,新增一位作者,姓名为disen,电话17791692095,城市是西安

-- author_id, name, city, phone
insert into tb_author
values(1, 'disen', '西安', '17791692095');

如,新增西安城市的李九江作者,他的电话是120

insert into tb_author(city, name, phone)
values('西安','李九江','120');

【注意】如果遇到自增列auto_increment时,避免显式方式指定列值。

3.1.2 多行数据插入
insert into <表名> [((字段1, 字段2, ...))] values
(字段值1, 字段值2, ...),
(字段值1, 字段值2, ...),
(字段值1, 字段值2, ...),
...
(字段值1, 字段值2, ...);

如,插入3位作者信息

insert into tb_author(city, name, phone) values
('北京', '老邓', '18918810018'),
('北京', '老刘', '17866541239'),
('杭州', '老马', '18766541908');
3.1.3 子查询方式插入

使用场景: 一般在分表存储数据时使用。

insert into <表名> [(字段1, ...)]
select子句;

如:将tb_author表中的所有北京的作者插入到tb_bejin_author表

insert into tb_bejin_author
select * from tb_author where city='北京';

【练习-添加tb_book表数据】

insert into tb_book(book_name, src_price, summary, cover_url) values
('Python入门第一版本', 20, 'Python2.7精讲', null),
('Python3精通', 50, 'Disen主讲Python3.7', '/static/img/1001.jpg'),
('MySQL5.7', 90, 'Mysql 5.7的DDL,DML,DQL等', '/static/img/1002.jpg'),
('MySQL8.0', 12, 'MySQL 8.0的全部内容', null),
('Linux精通到放弃', 28, 'Linux Centos7', null),
('Linux Shell编程', 21, 'Shell脚本开发',null);

3.2 update语句

update主要负责数据的更新或修改。

update <表名> set
字段1=字段值1 [,字段2=字段值2, ...]
[where 子句]

说明: where子句,支持等值条件、逻辑运算、空值。

  • 等值条件: 字段名=值字段名 >= | < | <= | != 值字段名 between 起始值 and 结束值 闭区间
  • 逻辑运算: 指多个条件之间的逻辑关系,包含 andornot, 另外,字段名 in(值1, 值2, 值3,...) 等价于字段名=值1 or 字段名=值2 or 字段名=值3
  • 空值: is nullnot null

如,更新tb_author西安的disen作者的城市为上海

update tb_author set
city='上海'
where city='西安' and name='disen';

如, 修改tb_author表中disen作者的姓名为’老狄’,城市修改为’北京’

update tb_author set
city='北京',name='老狄'
where name='disen';

如,修改tb_book表,将原价的20到30之间的所有图书打7折

select book_name, src_price,act_price
from tb_book;
-- tb_book(book_id, book_name, src_price, act_price, ....)
update tb_book set
act_price=src_price*0.7
where src_price between 20 and 30;

【注意】在更新某一字值时,可以引用原字段的数据。如act_price=src_price*0.7

如,将tb_book表中所有cover_url字段为空修改为/static/img/default.jpg

select book_name, cover_url from tb_book;
update tb_book set
cover_url='/static/img/default.jpg'
where cover_url is null;

【注意】更新数据时,避免全部数据更新,即必须带有where条件

3.3 delete语句

delete删除表的数据,不会影响表结构本身。

delete from <表名>
[where 子句]

【注意】如果delete语句不存在where子句时,表示清空表的内容。

如, 删除tb_book表中活动价格低于10元的数据

select book_name, act_price from tb_book;
begin;
delete from tb_book
where act_price <= 15;
commit;

【练习-外键约束的数据插入和级联操作】

-- tb_author(author_id, name, city, phone)
-- tb_book(book_id, book_name, ...,  author_id) 

insert into tb_author(name, city, phone)
values
('老李','西安', '19887726619'),
('小王','北京', '19826661190');
mysql> select * from tb_author;
+-----------+--------+--------+-------------+
| author_id | name   | city   | phone       |
+-----------+--------+--------+-------------+
|         1 | 老李   | 西安   | 19887726619 |
|         2 | 小王   | 北京   | 19826661190 |
+-----------+--------+--------+-------------+
2 rows in set (0.00 sec)
mysql> select book_id,book_name, author_id from tb_book;
+---------+----------------------+-----------+
| book_id | book_name            | author_id |
+---------+----------------------+-----------+
|       2 | Python3精通          |      NULL |
|       3 | MySQL5.7             |      NULL |
|       4 | MySQL8.0             |      NULL |
|       5 | Linux精通到放弃      |      NULL |
+---------+----------------------+-----------+
-- 修改tb_book表的book_id是2的author_id为3,是否可以成功呢?如果不成功,抛出什么错误呢?
-- 原因: 更改的author_id不在tb_author表的主键中。
update tb_book
set author_id=3
where book_id=2;
mysql> update tb_book
    -> set author_id=3
    -> where book_id=2;
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`bookdb`.`tb_book`, CONSTRAINT `book_author_fk` FOREIGN KEY (`author_id`) REFERENCES `tb_author` (`author_id`) ON DELETE CASCADE)
-- 将所有书的作者全部修改为author_id为1的作者
update tb_book
set author_id=1;
-- 删除author_id为1的作者记录
-- 外键约束的级联操作: ON DELETE CASCADE 级联删除
delete from tb_author where author_id=1;

【注意】当事务开启后,且执行了多个DML语句,在未提交事务之前,如果发生了DDL语句,则会自动提交事务。

alter table tb_book
drop foreign key book_author_fk;
-- 添加tb_book和tb_author的外键约束,支持级联删除和级联更新
alter table tb_book
add constraint book_author_fk foreign key (author_id) 
references tb_author(author_id) on delete cascade on update cascade;
-- ON UPDATE CASCADE 级联更新
-- 修改author_id为1的作者编号为110:  如果外键约束中存在级联更新,则直接修改外键字段的值。
update tb_author
set author_id=110
where author_id=1;
-- 外键约束:级联删除置空
alter table tb_book
drop foreign key book_author_fk;

alter table tb_book
add constraint book_author_fk foreign key (author_id) 
references tb_author(author_id) on delete set null;

begin;
delete from tb_author where author_id=110;
select book_name, author_id from tb_book;
rollback;

四、DQL语句

DQL(Data Query Language)数据查询语言,主要负责数据的查询,包含单表查询、多表查询、子查询、分组查询、条件查询、模糊查询、分页查询、窗口函数统计等。

官方文档:https://dev.mysql.com/doc/refman/8.0/en/select.html

4.1 select语句

select [distict] 字段名|表达式 [ [AS] 别名] [, 字段|表达式,...]
[ from <表名>| [[as] 别名] on (连接条件),... ]
[where 子句]
[group by 子句]
[having 子句]
[order by 列名|表达式 [ASC | DESC]]
[limit offset, rows]
4.1.1 select中的字段

在select子句中,可以选择表中的字段,也可以使用表达式(算术、函数、 关系、逻辑)。

如,查看当前时间(current_date、now())

select current_date;
select now();
mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-09-03 06:09:03 |
+---------------------+
mysql> select now() 'this time';
+---------------------+
| this time           |
+---------------------+
| 2021-09-03 06:09:03 |
+---------------------+
mysql>  select current_date as cdate;
+------------+
| cdate      |
+------------+
| 2021-09-03 |
+------------+
mysql> select 100>20 as ret;
+-----+
| ret |
+-----+
|   1 |
+-----+
1 row in set (0.00 sec)

mysql> select 100<20 as ret;
+-----+
| ret |
+-----+
|   0 |
+-----+
1 row in set (0.00 sec)


mysql> select 1 and 2 or 0 a123;
+------+
| a123 |
+------+
|    1 |
+------+

mysql> select uuid();
+--------------------------------------+
| uuid()                               |
+--------------------------------------+
| 8f232ae9-0c80-11ec-96d6-0242ac110002 |
+--------------------------------------+

mysql> select replace(uuid(), '-', '') as USERID;
+----------------------------------+
| USERID                           |
+----------------------------------+
| bca7edc00c8011ec96d60242ac110002 |
+----------------------------------+
【扩展-面试题】
create table A(year int, month int, amount float);
insert into A values
(1991, 1, 1.1),
(1991,2, 1.2),
(1992,1, 2.1),
(1992,2, 2.2);

问题存在一张A表,内容如下:

+------+-------+--------+
| year | month | amount |
+------+-------+--------+
| 1991 |     1 |    1.1 |
| 1991 |     2 |    1.2 |
| 1992 |     1 |    2.1 |
| 1992 |     2 |    2.2 |
+------+-------+--------+

请写出如下结果的SQL语句:

+------+-------+--------+
| year | m1    | m2     |
+------+-------+--------+
| 1991 |   1.1 |   1.2  |
| 1992 |   2.1 |   2.2  |

最有效的写法-SQL:

select year, 
  round(max(if(month=1,amount,0.0)),1) as m1,
  round(max(if(month=2, amount,0.0)),1) as m2 
from A
group by year;
4.1.2 from子句

from 关键字后面可以跟表名或子查询,如果是子查询时,必须提供别名,作为子查询结果的临时表名。 表名的别名,可以在select子句中使用。

from 后跟多个表时,需要用逗号分隔。 如果从多个表中查询数据,必须提供多个表之间的连接条件,否则会出现笛卡尔集

select b.book_name, b.author_id, a.name as author_name
from tb_book b, tb_author a
where b.author_id = a.author_id; 

4.2 where子句

where子句主要的作用是限制数据的范围,在select 的where子句中的字段,一般都是index索引字段(加速查询)。

where 子句中支持非常丰富的条件表达式,包含between-and、like、函数表达式、in、is null、not null等。

-- 查看活动价格在10-20之间的所有书的信息
select book_id,book_name,act_price
from tb_book
where act_price between 10 and 20;
-- 查看姓名中带`李`的作者
select * from tb_author
where name like '%李%';

【like说明】like是一种模糊匹配的查询条件,可以使用%_通配符。

  • % 代表任意长度的任意字符
  • _ 代表一个长度的任意字符
-- 查看姓名中第三个字符为`丽`的作者
select * from tb_author
where name like '__丽%';
-- 查看书编号为1或3或5的书信息
select * from tb_book
where book_id in (1, 3, 5);

-- 查看除作者编号为1和5之外的所有作者信息
select * from tb_author
where author_id not in (1, 5);

4.3 join语句

join语句支持多个表之间的连接,通过on指定表连接的条件。

使用join可以减少where等值连接的子句。

4.3.1 内连接

内连接即表示两个表都具有的数据

mysql> update tb_book set author_id=null where book_id=4;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select book_id,book_name, author_id from tb_book;
+---------+---------------+-----------+
| book_id | book_name     | author_id |
+---------+---------------+-----------+
|       2 | Python3精通   |       110 |
|       3 | MySQL5.7      |       110 |
|       4 | MySQL8.0      |      NULL |
+---------+---------------+-----------+

mysql> select author_id,name from tb_author;
+-----------+--------+
| author_id | name   |
+-----------+--------+
|         2 | 小王   |

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