数据库—1.数据库基础

1、MySQL数据库的介绍

  • 什么是数据库

数据库(Database)就是按照数据结构来组织,存储和管理数据的仓库

专业的数据库是专门对数据进行创建,访问,管理,搜索等操作的软件,比起我们自己用文件读写的方式对象数据进行管理更加的方便,快速,安全
 

  • 作用
    • 对数据进行持久化的保存
    • 方便数据的存储和查询,速度快,安全,方便
    • 可以处理并发访问
    • 更加安全的权限管理访问机制
  • 常见的数据库
    数据库分两大类,一类是 关系型数据库。另一类叫做 非关系型数据库。
    • 关系型数据库: MySQL,Oracle,PostgreSQL,SQLserver。。。。
    • 非关系型数据库:Redis内存数据库,MongoDB文档数据库。。。
  • 认识mysql数据库
    MySQL是最流行的关系型数据库管理系统
    • 安装mysql
  • 关于数据库的一些概念
    • 数据库 Database
    • 数据表 Tables
    • 数据字段
    • 行 row

 

2、Windows安装MySQL5.7.17

1. 在MySQL官网 http://dev.mysql.com/downloads/mysql/ 上面下载ZIP安装包(第二个:Windows (x86, 64-
bit), ZIP Archive)。

2. 下载完成后解压,将其放到想要安装的目录下。
例如:D:\MySQL5.7\mysql-5.7.17-winx64

3. 新建一个my.ini配置文件,原始的my-default.ini配置文件只是个模版,不要在里面改动。
my.ini的内容如下:
[mysql] default-character-set=utf8
[mysqld] port = 3306 basedir=D:\MySQL5.7\mysql-5.7.17-winx64 datadir=D:\MySQL5.7\mysql-5.7.17-
winx64\data max_connections=200 character-set-server=utf8 default-storage-engine=INNODB
explicit_defaults_for_timestamp=true

4. 在安装路径下新建一个空的data文件夹。

5. 以管理员身份运行cmd,进入bin目录,执行 mysqld --initialize-insecure --user=mysql 命令。不进行这一
步,安装完成之后无法启动服务。

6. 依然在管理员cmd窗口的bin目录下,执行 mysqld install 命令安装。完成后会提示安装成功。

7. 依然在管理员cmd窗口的bin目录下,执行 net start mysql 命令启动MySQL服务。

8. 修改环境变量,添加"D:\MySQL5.7\mysql-5.7.17-winx64\bin"。

9. 在普通cmd窗口中,进入bin目录,执行 mysql -u root -p 命令,默认没有密码,回车进入。

3、初识 mysql的基本命令

3.1. 登录mysql(mysql -u root -p;)

在终端mysql bin 目录下输入以下命令,进行登录:

mysql -u root -p;

3.2. 查看当前mysql中所有的库(show databases;)

库==>数据库==>就像文件夹一样,库里面可以存储很多个表)

show databases;

3.3. 选择需要操作的库,打开库(use 库名;)

3.4. 查看当前库中的所有数据表(show tables;)

3.5. 查看表中的数据

3.6. 查看表结构

desc 表名;

3.7. 库和表的概念与关系

  • 库就像是文件夹,库中可以有很多个表
  • 表就像是我们的excel表格文件一样
  • 每一个表中都可以存储很多数据
  • mysql中可以有很多不同的库,库中可以有很多不同的表
  • 表中可以定义不同的列(字段),
  • 表中可以根据结构去存储很多的数据

3.8. 如何创建自己的库?

create database 库名 default charset=utf8mb4;

3.9. 创建表的语法

create table 表名( 字段名 类型 字段约束, 字段名 类型 字段约束, 字段名 类型 字段约束, )engine=innodb default charset=utf8;

-- 创建用户表
create table user(
name varchar(20),
age int,
sex char(1)
)engine=innodb default charset=utf8mb4;
-- Query OK, 0 rows affected (0.16 sec)

3.10. 添加数据

-- 向 user 表中 添加 name,age,sex 数据
insert into user(name,age,sex) values('admin',26,'男');
-- Query OK, 1 row affected (0.00 sec)
insert into user(name,age,sex) values('张三',22,'女');
-- 查看表中的数据
select * from user;
+--------+------+------+
| name | age | sex |
+--------+------+------+
| admin | 26 | 男 |
| 张三 | 22 | 女 |
+--------+------+------+
2 rows in set (0.00 sec)

3.11. 总结:

认识 库、表的概念和关系 mysql的基本命令: 登录,查看库,选择库,查看表, 创建库,创建表,添加数据,查 询数据。

4、MySQL基础操作

使用方法:

方式一: 通过在命令行敲命令来操作 ( 有助于命令的掌握)

方式二: 通过图型界面工具,如 Navicat 等(在熟练掌握后再使用)

方式三:通过编程语言(python,php,java,go...)执行mysql命令

4.1. SQL 结构化查询语言

SQL ( Structure query language )语言分为4个部分:DDL(定义)、DML(操作)、DQL(查询)、DCL(控制)

4.2. SQL快捷键

\G 格式化输出(文本式,竖立显示)

\s 查看服务器端信息

\c 结束命令输入操作

\q 退出当前sql命令行模式

\h 查看帮助

4.3 操作数据库的步骤

连接, 打开库, 操作, 关闭退出

1.通过命令行连接MySQL

数据库语法的特点

1) SQL 语句可以换行, 要以分号结尾

2) 命令不区分大小写. 关键字和函数建议用大写

3) 如果提示符为 '> 那么需要输入一个'回车

4) 命令打错了换行后不能修改, 可以用 \c 取消

2. 数据库操作

  • 查看数据库 show databases;
  • 创建数据库 create database 库名 default charset=utf8mb4;
  • 删除数据库 drop database 库名;
  • 打开数据库 use 库名;

3. 数据表操作

数据库管理系统中, 可以有很多库, 每个数据库中可以包括多张数据表

查看表: show tables;

创建表: create table 表名(字段名1 类型,字段名2 类型)engine=innodb default charset=utf8mb4;

创建表: 如果表不存在,则创建, 如果存在就不执行这条命令

create table if not exists 表名(字段1 类型,字段2 类型);

create table if not exists users(
id int not null primary key auto_increment,
name varchar(4) not null,
age tinyint,
sex enum('男','女')
)engine=innodb default charset=utf8mb4;

删除表: drop table 表名;

表结构: desc 表名;

查看建标语句:show create table users;

4. 数据操作 增删改查

插入

insert into 表名(字段1,字段2,字段3) values(值1,值2,值3);

insert into 表名(字段1,字段2,字段3) values(a值1,a值2,a值3),(b值1,b值2,b值3);

查询

select * from 表名;

select 字段1,字段2,字段3 from 表名;

select * from 表名 where 字段=某个值;

修改

update 表名 set 字段=某个值 where 条件;

update 表名 set 字段1=值1,字段2=值2 where 条件;

update 表名 set 字段=字段+值 where 条件;

删除

delete from 表名 where 字段=某个值;

4.4 退出MySQL

exit; 或者 quit;

 

5、MySQL的数据类型

5.1 MySQL的数据类型

数据类型是定义列中可以存储什么类型的数据以及该数据实际怎样存储的基本规则

数据类型限制存储在数据列列中的数据。例如,数值数据类型列只能接受数值类型的的数据

在设计表时,应该特别重视所用的数据类型。使用错误的数据类型可能会严重地影响应用程序的功能和性能。

更改包含数据的列不是一件小事(而且这样做可能会导致数据丢失)。

数据类型:整型、浮点型、字符串、日期等

1、字符串数据类型

最常用的数据类型是串数据类型。它们存储串,如名字、地址、电 话号码、邮政编码等。

不管使用何种形式的串数据类型,串值都必须括在引号内

有两种基本的串类型,分别为定长串和变长串

  • 定长串:char
    • 接受长度固定的字符串,其长度是在创建表时指定的。
      定长列不允许存储多于指定长度字符的数据。
    • 指定长度后,就会分配固定的存储空间用于存放数据

char(7) 不管实际插入多少字符,它都会占用7个字符位置

  • 变长串 varchar
    • 存储可变长度的字符串 varchar(7) 如果实际插入4个字符, 那么它只占4个字符位置,当然插入的数据长度不能超过7 个字符。

 

注意

既然变长数据类型这样灵活,为什么还要使用定长数据类型?

回答:因为性能,MySQL处理定长列远比处理变长列快得多。

  • Text 变长文本类型存储

2、数值类型

数值数据类型存储数值。MySQL支持多种数值数据类型,每种存储的数值具有不同的取值范围。支持的取值范围越
大,所需存储空间越多

与字符串不一样,数值不应该括在引号内

decimal(5, 2) 表示数值总共5位, 小数占2位
tinyint 1字节(8位) 0-255。-128,127
int 4字节。 -21亿,21亿。0-42亿
float.
MySQL中没有专门存储货币的数据类型,一般情况下使用DECIMAL(8, 2)

有符号或无符号

所有数值数据类型(除BIT和BOOLEAN外)都可以有符号或无符号

  • 有符号数值列可以存储正或负的数值
  • 无符号数值列只能存储正数。
  • 默认情况为有符号,但如果你知道自己不需要存储负值,可以使用UNSIGNED关键字

注意

如果将邮政编码类似于01234存储为数值类型,则保存的将是数值1234,此时需要使用字符串类型

手机号应该用什么进行存储呢?也需要字符串类型

3、日期和时间类型

MySQL使用专门的数据类型来存储日期和时间值

datetime 8字节1000-01-01 00:00:00 ~ 9999-12-31 23:59:59

4、二进制数据类型

二进制数据类型可存储任何数据(甚至包括二进制信息),如图像、多媒体、字处理文档等

通常情况下,不会使用二进制数据进行多媒体数据存储

5.2. 表的字段约束

  • unsigned 无符号(给数值类型使用,表示为正数,不写可以表示正负数都可以)
  • 字段类型后面加括号限制宽度
    • char(5). varchar(7) 在字符类型后面加限制 表示 字符串的长度
    • int(4) 没有意义,默认无符号的int为int(11),有符号的int(10)
    • int(4) unsigned zerofill只有当给int类型设置有前导零时,设置int的宽度才有意义。
  • not null 不能为空,在操作数据库时如果输入该字段的数据为NULL ,就会报错
  • default 设置默认值
  • primary key 主键不能为空,且唯一.一般和自动递增一起配合使用。
  • auto_increment 定义列为自增属性,一般用于主键,数值会自动加1
  • unique 唯一索引(数据不能重复:用户名)可以增加查询速度,但是会降低插入和更新速度

5.3 MySQL的运算符

  • 算术运算符: +、 -、 *、 /、 %
  • 比较运算符: =、 >、 <、 >=、 <=、!=
  • 数据库特有的比较: in、not in、is null、is not null、like、between、and
  • 逻辑运算符: and、or、not
  • like: 支持特殊符号%和_ ;
    其中%表示任意数量的任意字符,_表示任意一位字符

5.4 主键

  • 表中每一行都应该有可以唯一标识自己的一列,用于记录两条记录不能重复,任意两行都不具有相同的主键值
  • 应该总是定义主键 虽然并不总是都需要主键,但大多数数据库设计人员都应保证他们创建的每个表具有一个主键,以便于以后的数据操纵和管理。

要求

  • 记录一旦插入到表中,主键最好不要再修改
  • 不允许NULL
  • 不在主键列中使用可能会更改的值。
    (例如,如果使用一个名字作为主键以标识某个供应商,当该供应商合并和更改其名字时,必须更改这个主键。)
  • 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键 重复,也不用自己预先生成主键
  • 可以使用多个列作为联合主键,但联合主键并不常用。使用多列作为主键时,所有列值的组合必须是唯一的

6、MySQL数据库与数据表操作

  • 数据库的操作
    • 数据库创建
    • 数据库删除
  • 数据表的操作
    • 数据表的创建
    • 数据表的修改 (表结构)
    • 数据表的删除

6.1 数据库的操作

1.数据库的创建

# 链接mysql数据库后,进入mysql后可以操作数据
# 1. 创建库
create database if not exists tlxy default charset=utf8;
-- 1. 数据库 tlxy 如果不存在则创建数据库,存在则不创建
-- 2. 创建 tlxy 数据库,并设置字符集为utf8
-- 3. 无特殊情况都要求字符集为utf8或者utf8mb4的字符编码

2.查看所有库

# 1. 查看所有库
show databases;

3.打开库/进入库/选择库

# use 库名 
use tlxy

4.删除库

删库有风险,动手需谨慎

# 删除库,那么库中的所有数据都将在磁盘中删除。
drop database 库名

6.2 数据表的操作

1.创建表

语法格式:

create table 表名(字段名,类型,【字段约束】,。。。);

实例:

# 以下创建一个 users 的表
create table users(
-- 创建ID字段,为正整数,不允许为空 主键,自动递增
id int unsigned not null primary key auto_increment,
-- 创建 存储 名字的字段,为字符串类型,最大长度 5个字符,不允许为空
username varchar(5) not null,
-- 创建存储 密码 的字段,固定长度 32位字符, 不允许为空
password char(32) not null,
-- 创建 年龄 字段,不允许为空,默认值为 20
age tinyint not null default 20
)engine=innodb default charset=utf8;
# 查看表结构
desc users;
#查看建表语句
show create table users;

创建表的基本原则:

  • 表明和字段名 尽可能的符合命名规范,并且最好能够‘见名之意’
  • 表中数据必须有唯一标示,即主键定义。无特殊情况,主键都为数字并自增即可
  • 表中字段所对应的类型设置合理,并限制合理长度
  • 表引擎推荐使用innodb,并无特殊情况都要求为utf8或者utf8mb4的字符编码

2.修改表结构

语法格式:alter table 表名 action (更改的选项)

添加字段

# 语法:alter table 表名 add 添加的字段信息
-- 在 users 表中 追加 一个 num 字段
alter table users add num int not null;
-- 在指定字段后面追加字段 在 users 表中 age字段后面 添加一个 email 字段
alter table users add email varchar(50) after age;
-- 在指定字段后面追加字段,在 users 表中 age字段后面 添加一个 phone
alter table users add phone char(11) not null after age;
-- 在表的最前面添加一个字段
alter table users add aa int first;

删除字段

# 删除字段 alter table 表名 drop 被删除的字段名
alter table users drop aa;

修改字段

语法格式: alter table 表名 change|modify 被修改的字段信息
change: 可以修改字段名,
modify: 不能修改字段名。
# 修改表中的 num 字段 类型,使用 modify 不修改表名
alter table users modify num tinyint not null default 12;
# 修改表中的 num 字段 为 int并且字段名为 nn
alter table users change num mm int;
# 注意:一般情况下,无特殊要求,不要轻易修改表结构

3.修改表名

# 语法:alter table 原表名 rename as 新表名

4.更改表中的自增的值

# 在常规情况下,auto_increment 默认从1开始继续递增
alter table users auto_increment = 1000;

5.修改表引擎

# 推荐在定义表时,表引擎为 innodb。
# 通过查看建表语句获取当前的表引擎
mysql> show create table users\G;
*************************** 1. row ***************************
Table: users
Create Table: CREATE TABLE `users` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
# 直接查看当前表状态信息
mysql> show table status from tlxy where name = 'users'\G;
*************************** 1. row ***************************
Name: users
Engine: InnoDB
# 修改表引擎语句
alter table users engine = 'myisam';

6.删除表

drop table 表名

7、Mysql数据库表引擎与字符集

7.1 服务器处理客户端请求

其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送
一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那服务器进程对客户
端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们
这里以比较复杂的查询请求为例来画个图展示一下大致的过程:
 

虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓 存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不 推荐使用查询缓存,并在MySQL 8.0中删除。

7.2 存储引擎

MySQL 服务器把数据的存储和提取操作都封装到了一个叫 存储引擎 的模块里。我们知道 表 是由一行一行的记录 组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存 储器上,这都是 存储引擎 负责的事情。

为了实现不同的功能, MySQL 提供了各式各样的 存储引擎 ,不同 存储引 擎 管理的表具体的存储结构可能不同,采用的存取算法也可能不同。

存储引擎以前叫做 表处理器 ,它的功能就是接收上层传下来的指令,然后对表中的数据进行提取或写入操 作。 为了管理方便,人们把 连接管理 、 查询缓存 、 语法解析 、 查询优化 这些并不涉及真实数据存储的功能划分为 MySQL server 的功能,把真实存取数据的功能划分为 存储引擎 的功能。

各种不同的存储引擎向上边的 MySQL server 层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、"读取 索引下一条内容"、"插入记录"等等。

所以在 MySQL server 完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返 回给客户端就好了。

MySQL 支持非常多种存储引擎:

7.3 MyISAM和InnoDB表引擎的区别

1) 事务支持

  • MyISAM不支持事务,而InnoDB支持。
  • 事物:访问并更新数据库中数据的执行单元。事物操作中,要么都执行要么都不执行

2) 存储结构

MyISAM:每个MyISAM在磁盘上存储成三个文件。

  • .frm文件存储表结构。
  • .MYD文件存储数据。
  • MYI文件存储索引。

InnoDB:主要分为两种文件进行存储

  • .frm 存储表结构
  • .ibd 存储数据和索引 (也可能是多个.ibd文件,或者是独立的表空间文件)

3) 表锁差异

MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如
果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。 InnoDB:支持事务和行级锁,是
innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有
效的,非主键的WHERE都会锁全表的。

4) 表主键

MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。 InnoDB:如果没有设定主键或者非空唯
一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。
InnoDB的主键范围更大,最大是MyISAM的2倍。

5) 表的具体行数

MyISAM:保存有表的总行数,如果select count() from table;会直接取出出该值。 InnoDB:没有保存表的总行数
(只能遍历),如果使用select count() from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,
myisam和innodb处理的方式都一样。

6) CURD操作

MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。 InnoDB:如果你的数据执行大量的INSERT或
UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table
时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用
truncate table这个命令。

7) 外键

MyISAM:不支持 InnoDB:支持

8) 查询效率

MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
推荐考虑使用InnoDB来替代MyISAM引擎,原因是InnoDB自身很多良好的特点,比如事务支持、存储 过程、视
图、行级锁定等等,在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多。
另外,任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优
势。如果不是很复杂的Web应用,非关键应用,还是可以继续考虑MyISAM的,这个具体情况可以自己斟酌。

9)MyISAM和InnoDB两者的应用场景:

MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那
么MyISAM是更好的选择。 InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要
执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。现在默认使用
InnoDB。

7.4 了解一下字符集和乱码

字符集简介

我们知道在计算机中只能存储二进制数据,那该怎么存储字符串呢?当然是建立字符与二进制数据的映射关系了,
建立这个关系最起码要搞清楚两件事儿:
1. 你要把哪些字符映射成二进制数据?

  • 也就是界定清楚字符范围。

2. 怎么映射?

  • 将一个字符映射成一个二进制数据的过程也叫做 编码 ,将一个二进制数据映射到一个字符的过程叫做 解

码 。
人们抽象出一个 字符集 的概念来描述某个字符范围的编码规则
我们看一下一些常用字符集的情况:

  • ASCII 字符集
    • 共收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共才128个字符,所以可以使用1个字节来进行编码,我们看一些字符的编码方式:

'L' -> 01001100(十六进制:0x4C,十进制:76)

'M' -> 01001101(十六进制:0x4D,十进制:77)

  • ISO 8859-1 字符集
    • 共收录256个字符,是在 ASCII 字符集的基础上又扩充了128个西欧常用字符(包括德法两国的字母),也可以使用1个字节来进行编码。这个字符集也有一个别名 latin1 。
  • GB2312 字符集
    • 收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个,其他文字符号682个。同时这种字符集又兼容 ASCII 字符集,所以在编码方式上显得有些奇怪:
      • 如果该字符在 ASCII 字符集中,则采用1字节编码。
      • 否则采用2字节编码。
  • 这种表示一个字符需要的字节数可能不同的编码方式称为 变长编码方式 。比方说字符串 '爱u' ,其中 '爱' 需要用2个字节进行编码,编码后的十六进制表示为 0xCED2 , 'u' 需要用1个字节进行编码,编码后的十六进制表示为 0x75 ,所以拼合起来就是 0xCED275 。

小贴士: 我们怎么区分某个字节代表一个单独的字符还是代表某个字符的一部分呢?别忘了 ASCII 字 符集只收录128个字符,使用0~127就可以表示全部字符,所以如果某个字节是在0~127之内的,就意 味着一个字节代表一个单独的字符,否则就是两个字节代表一个单独的字符。

  • GBK 字符集
    • GBK 字符集只是在收录字符范围上对 GB2312 字符集作了扩充,编码方式上兼容 GB2312 。
  • Unicode字符集
    • 收录地球上能想到的所有字符,而且还在不断扩充。这种字符集兼容 ASCII 字符集,采用变长编码方式,编码一个字符需要使用1~4个字节,比方说这样:

'L' -> 01001100(十六进制:0x4C)

'啊' -> 111001011001010110001010(十六进制:0xE5958A)

 小贴士: 其实准确的说,utf8只是Unicode字符集的一种编码方案,Unicode字符集可以采用utf8、 utf16、utf32这几种编码方案,utf8使用1~4个字节编码一个字符,utf16使用2个或4个字节编码一个 字符,utf32使用4个字节编码一个字符。更详细的Unicode和其编码方案的知识不是本书的重点,大家 上网查查哈~ MySQL中并不区分字符集和编码方案的概念,所以后边唠叨的时候把utf8、utf16、utf32 都当作一种字符集对待。

对于同一个字符,不同字符集也可能有不同的编码方式。比如对于汉字 '我' 来说, ASCII 字符集中根本没有收录 这个字符, utf8 和 gb2312 字符集对汉字 我 的编码方式如下:

utf8编码:111001101000100010010001 (3个字节,十六进制表示是:0xE68891)

gb2312编码:1100111011010010 (2个字节,十六进制表示是:0xCED2)

7.5 MySQL中的utf8和utf8mb4

我们上边说 utf8 字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示 了。而在 MySQL 中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以设计 MySQL 的大叔偷偷的定义了两个概念:

  • utf8mb3 :阉割过的 utf8 字符集,只使用1~3个字节表示字符。
  • utf8mb4 :正宗的 utf8 字符集,使用1~4个字节表示字符。

有一点需要大家十分的注意,在 MySQL 中 utf8 是 utf8mb3 的别名,所以之后在 MySQL 中提到 utf8 就意味着使用 1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使 用 utf8mb4 。

字符集的查看

MySQL 支持好多好多种字符集,查看当前 MySQL 中支持的字符集可以用下边这个语句:

show charset;

8、MySQL 数据操作 DML(增删改)

数据的DML操作:添加数据,修改数据,删除数据

8.1 添加数据 -insert into

格式: insert into 表名[(字段列表)] values(值列表...);

--标准添加(指定所有字段,给定所有的值)
mysql> insert into stu(id,name,age,sex,classid) values(1,'zhangsan',20,'m','lamp138');
Query OK, 1 row affected (0.13 sec)
mysql>
--指定部分字段添加值
mysql> insert into stu(name,classid) value('lisi','lamp138');
Query OK, 1 row affected (0.11 sec)
-- 不指定字段添加值,必须按照表的字段顺序定义给所有字段赋值
mysql> insert into stu value(null,'wangwu',21,'w','lamp138');
Query OK, 1 row affected (0.22 sec)
-- 批量添加值
mysql> insert into stu values
-> (null,'zhaoliu',25,'w','lamp94'),
-> (null,'uu01',26,'m','lamp94'),
-> (null,'uu02',28,'w','lamp92'),
-> (null,'qq02',24,'m','lamp92'),
-> (null,'uu03',32,'m','lamp138'),
-> (null,'qq03',23,'w','lamp94'),
-> (null,'aa',19,'m','lamp138');
Query OK, 7 rows affected (0.27 sec)
Records: 7 Duplicates: 0 Warnings: 0

8.2 修改数据-update

格式:update 表名 set 字段1=值1,字段2=值2,字段n=值n... where 条件

-- 将id为11的age改为35,sex改为m值
mysql> update stu set age=35,sex='m' where id=11;
Query OK, 1 row affected (0.16 sec)
Rows matched: 1 Changed: 1 Warnings: 0
-- 将id值为12和14的数据值sex改为m,classid改为lamp92
mysql> update stu set sex='m',classid='lamp92' where id=12 or id=14 --or  等价于下面
mysql> update stu set sex='m',classid='lamp92' where id in(12,14);--in
Query OK, 2 rows affected (0.09 sec)
Rows matched: 2 Changed: 2 Warnings: 0

8.3 删除数据-delete

格式:delete from 表名 [where 条件]

-- 删除stu表中id值为100的数据
mysql> delete from stu where id=100;
Query OK, 0 rows affected (0.00 sec)
-- 删除stu表中id值为20到30的数据
mysql> delete from stu where id>=20 and id<=30;
Query OK, 0 rows affected (0.00 sec)
-- 删除stu表中id值为20到30的数据(等级于上面写法)
mysql> delete from stu where id between 20 and 30;--between
Query OK, 0 rows affected (0.00 sec)
-- 删除stu表中id值大于200的数据
mysql> delete from stu where id>200;
Query OK, 0 rows affected (0.00 sec)

9、DQL-MySQL数据查询SQL

9.1. MySql查询语句-select

语法格式:

select 字段列表|* from 表名
[where 搜索条件]
[group by 分组字段 [having 分组条件]]
[order by 排序字段 排序规则]
[limit 分页参数]

--创建表
CREATE TABLE 'stu'(
'id' int(10) unsigned NOT NULL AUTO_ INCREMENT,
'name' varchar(10) NOT NULL,
'email' char(50) NOT NULL,
'phone' char(11) NOT NULL, 
'age' tinyint(4) NOT NULL,
'sex' char(1) DEFAULT NULL,
'class_ id' int(10) DEFAULT NULL,
PRIMARY KEY ('id')
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
--添加数据
insert into stu values
(nu1l,'张三' ,'zhangsan@qq. com','13701104321',21,'男',1),
(null, '李四','lisi@qq.com','13701104322',22,'男',1),
(null, '王五','wangwu@qq.com','13701104323',20,'女',1),
(null, '赵六','zhaoliu@qq . com’, '13701104324' ,19,'男',1),
(nu1l, '田七','tianqi@qq.com','13701104325',23,'女',1),
(null,'王五六','wangwuliu@qq.com','13701104326',23,'女',1),
(null, '熊大','xiongda@qq.com','13701104327',25,'男',2),
(null,'熊二',‘xionger@qq.com','13701104328',22,'男' ,2),
(null,'--', 'yiyi@qq.com','13701104329',19,'女',2),
(null, '呀呀','yaya@qq.com','13701104320',22,'男',2);
--查看表数据
select * from stu;

检索数据select(使用DISTINCT、LIMIT)

检索单个列

select name from stu;

检索多个列

select id,name,age,sex from stu;

检索所有列

selecr * from stu;

检索不同的行DISTINCT(去重)

select distince classid from stu;

限制结果LIMIT(分页)

  • limit n 提取n条数据,
  • limit m,n 跳过m跳数据,提取n条数据

select * from stu limit 3,4;

-- 查询users表中的数据,只要3条
select * from users limit 3;
-- 跳过前4条数据,再取3条数据
select * from users limit 4,3;
-- limit一般应用在数据分页上面
-- 例如每页显示10条数据,第三页的 limit应该怎么写? 思考
第一页 limit 0,10
第二页 limit 10,10
第三页 limit 20,10
第四页 limit 30,10
-- 提取 user表中 年龄最大的三个用户数据 怎么查询?
select * from users order by age desc limit 3;

使用完全限定的表名

select name from stu;

select stu.name from stu;

select stu.name from 库名.stu;

9.2. OrderBy 排序

排序数据 ORDER BY(默认ASC 升序,desc降序)

-- 按照年龄对结果进行排序,从大到小
select * from users order by age desc;

按多个列排序

--先按照age进行排序,age相同情况下,按照id进行排序
select * from users order by age,id; 

select * from stu order by classid,age desc;

注意

9.3. 数据检索条件过滤where

过滤数据where

  • 数据库表一般包含大量的数据,很少需要检索表中所有行。
  • 通常只会根据特定操作或报告的需要提取表数据的子集。
  • 只检索所需数据需要指定搜索条件(search criteria),搜索条件 也称为过滤条件(filter condition)。
  • 在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。

select name from stu where age = 22;

在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误

select name from stu where age = 22 order by id;

where子句操作符

Where 条件查询

  • 可以在where子句中指定任何条件
  • 可以使用 and 或者 or 指定一个或多个条件
  • where条件也可以运用在update和delete语句的后面
  • where子句类似程序语言中if条件,根据mysql表中的字段值来进行数据的过滤
-- 查询users表中 age > 22的数据
select * from users where age > 22;
-- 查询 users 表中 name=某个条件值 的数据
select * from users where name = '王五';
-- 查询 users 表中 年龄在22到25之间的数据
select * from users where age >= 22 and age <= 25;
select * from users where age between 22 and 25;
-- 查询 users 表中 年龄不在22到25之间的数据
select * from users where age < 22 or age > 25;
select * from users where age not between 22 and 25;
-- 查询 users 表中 年龄在22到25之间的女生信息
select * from users where age >= 22 and age <= 25 and sex = '女';

and和or 使用时注意

假设要求 查询 users 表中 年龄为22或者25 的女生信息
select * from users where age=22 or age = 25 and sex = '女';
思考上面的语句能否返回符合条件的数据?
实际查询结果并不符合要求?

select * from users where age=22 or age = 25 and sex = '女';
+------+--------+------+-------+-------+------+------+
| id | name | age | phone | email | sex | mm |
+------+--------+------+-------+-------+------+------+
| 1 | 章三 | 22 | | NULL | 男 | 0 |
| 1002 | cc | 25 | 123 | NULL | 女 | NULL |
+------+--------+------+-------+-------+------+------+
2 rows in set (0.00 sec)
-- 上面的查询结果并不符合 查询条件的要求。
-- 问题出在 sql 计算的顺序上,sql会优先处理and条件,所以上面的sql语句就变成了
-- 查询变成了为年龄22的不管性别,或者年龄为 25的女生
-- 如何改造sql符合我们的查询条件呢?
-- 使用小括号来关联相同的条件
select * from users where (age=22 or age = 25) and sex = '女';
+------+------+------+-------+-------+------+------+
| id | name | age | phone | email | sex | mm |
+------+------+------+-------+-------+------+------+
| 1002 | cc | 25 | 123 | NULL | 女 | NULL |
+------+------+------+-------+-------+------+------+
1 row in set (0.00 sec)

因此想要解决就需要提升优先级,使用圆括号明确地分组相应的操作符

IN 与 NOT

IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。

select name from stu where classid in (1,2)

IN WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当

为什么要使用IN操作符?其优点具体如下。

  • 在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
  • 在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
  • IN操作符一般比OR操作符清单执行更快。
  • NOT WHERE子句中用来否定后跟条件的关键字

select name from stu where class_ id not in (18,19)

为什么使用NOT?对于简单的WHERE子句,使用NOT确实没有什么优势。

但在更复杂的子句中,NOT是非常有用的。

例如,在与IN操作符联合使用时,NOT使找出与条件列表不匹配的行非常简单。

9.4. Like与通配符

我们可以在where条件中使用=,<,> 等符合进行条件的过滤,但是当想查询某个字段是否包含时如何过滤?

可以使用like语句进行某个字段的模糊搜索,

例如: 查询 name字段中包含五的数据

-- like 语句 like某个确定的值 和。where name = '王五' 是一样
select * from users where name like '王五';
+----+--------+------+-------+-----------+------+------+
| id | name | age | phone | email | sex | mm |
+----+--------+------+-------+-----------+------+------+
| 5 | 王五 | 24 | 10011 | ww@qq.com | 男 | 0 |
+----+--------+------+-------+-----------+------+------+
1 row in set (0.00 sec)

前面介绍的所有操作符都是针对已知值进行过滤的。

但是,这种过滤方法并不是任何时候都好用。

例如,怎样搜索产品名中包含文本anvil的所有产品?用简单的比较操作符肯定不行,必须使用通配符。

为在搜索子句中使用通配符,必须使用LIKE操作符 。

LIKE指示MySQL,后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。

  • 百分号(%)通配符在搜索串中,%表示任何字符出现任意次数

select name from stu where name like 'a%';--以a开头任意数量字符结尾

select name from stu where name like '%a';--以a结尾任意数量字符开头

select name from stu where name like '%a%';--任意数量字符开头结尾中间有a

  • 下划线(_)通配符下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符

select name from stu where name like 'a_';--以a开头并以单个字符结尾

select name from stu where name like '_ _a';--以a结尾并以两个字符开头

select name from stu where name like '_a_';--一个字符开头一个字符结尾中间为a

select name from stu where name like '_a%';--一个字符开头任意数量字符结尾中间为a

-- 使用 % 模糊搜索。%代表任意个任意字符
-- 查询name字段中包含五的
select * from users where name like '%五%';
-- 查询name字段中最后一个字符 为 五的
select * from users where name like '%五';
-- 查询name字段中第一个字符 为 王 的
select * from users where name like '王%';
-- 使用 _ 单个的下划线。表示一个任意字符,使用和%类似
-- 查询表中 name 字段为两个字符的数据
select * from users where name like '_ _';
-- 查询 name 字段最后为五,的两个字符的数据
select * from users where name like '_五';
  • 使用通配符的技巧

正如所见,MySQL的通配符很有用。

但这种功能是有代价的: 通配符搜索的处理一般要 比前面讨论的其他搜索所花时间更长。

这里给出一些使用通配符要记住的技巧

  • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
  • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。
  • 把通配符置于搜索模式的开始处,搜索起来是最慢的,如果需要使用,也尽可能不要把通配符放在开头处
  • 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据
  • 了解下MySQL的正则REGEXP

所有种类的程序设计语言、文本编辑器、操作系统等都支持正则表达式

  • select name from stu where name regexp '[0-5]abc'

9.5. 字段的拼接和别名

存储在数据库表中的数据一般不是应用程序所需要的格式。 下面举几个例子

  • 如果想在一个字段中既显示用户名,又显示班级号,但这两个信息一般包含在不同的表列中。
  • 同时姓名、手机号和地址存储在不同的列中(应该这样),但快递单打印程序却需要把它们作为一个恰当格式的字段检索出来。
  • 列数据是大小写混合的,但报表程序需要把所有数据按大写表示出来。
  • 物品订单表存储物品的价格和数量,但不需要存储每个物品的总价格(用价格乘以数量即可)。为打印发票,需要物品的总价格。
  • 需要根据表数据进行总数、平均数计算或其他计算

计算字段并不实际存在于数据库表中。计算字段是运行时在SELECT语句内创建的

拼接 Concat

stu表包含用户名和手机号码信息。假如要生成一个学生报表, 需要在学生的名字中按照name(phone)这样的格式列出

解决办法是把两个列拼接起来。在MySQL的SELECT语句中, 可使用Concat0函数来拼接两个列

select concat(name,'(' ,phone')') from stu;


使用别名 AS

SELECT语句拼接字段可以完成。但此新计算列的名字是什么呢?实际上它没有名字,它只是一个值。

如果仅在SQL查询工具中查看- -下结果,这样没有什么不好。

但是,一个未命名的列不能用于客户机应用中,因为客户机没有办法引用它。

为了解决这个问题,SQL支持列别名。别名(alias) 是一个字段或值的替换名。别名用AS关键字赋予

select concat (name,'(',phone')') from stu as name_phone from stu;

计算

有时候还须要进行计算,如计算出某订单中同类物品的总价。

select  属性1,属性2,属性3,属性1*属性3 as  别名 from 表名 where ...;

9.6. 常用函数介绍

函数使用

与其他大多数计算机语言一样,SQL支持利用函数来处理数据。

函数一般是在数据上执行,它给数据的转换和处理提供了方便。

文本处理函数

https://dev.mysql.com/doc/refman/5.7/en/string-functions.html

select left('abcded',2);--返回ab

select left(name,2) from stu;--返回所有name字段的前两个字符

select subString('abcdef',2,3);--bcd

日期和时间处理函数

https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html

select date(now());--查询当前日期年月日

select time(now());--查询当前时间时分秒

select AddTime(now(),'2:2:2');

数值处理函数

https://dev.mysql.com/doc/refman/5.7/en/numeric-functions.html

9.7. 聚集函数与GroupBy分组

聚集函数的使用

我们经常需要汇总数据而不用把它们实际检索出来,为此MySQL提供了 专门的函数。
使用这些函数,MySQL查询可用于检索数据,以便分析和报表生成

  • 确定表中行数(或者满足某个条件或包含某个特定值的行数)。
  • 获得表中行组的和。
  • 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。

上述例子都需要对表中数据(而不是实际数据本身)汇总。

因此,返回实际表数据是对时间和处理资源的一种浪费

注意

在使用count时,如果指定列名,则指定列的值为空的行被忽略,但如果COUNTO函数中用的是星号(*),则不忽略

# 计算 users 表中 最大年龄,最小年龄,年龄和及平均年龄
select max(age),min(age),sum(age),avg(age) from users;
+----------+----------+----------+----------+
| max(age) | min(age) | sum(age) | avg(age) |
+----------+----------+----------+----------+
| 28 | 20 | 202 | 22.4444 |
+----------+----------+----------+----------+
-- 上面数据中的列都是在查询时使用的函数名,不方便阅读和后期的调用,可以通过别名方式 美化
select max(age) as max_age,
min(age) min_age,sum(age) as sum_age,
avg(age) as avg_age
from users;
+---------+---------+---------+---------+
| max_age | min_age | sum_age | avg_age |
+---------+---------+---------+---------+
| 28 | 20 | 202 | 22.4444 |
+---------+---------+---------+---------+
-- 统计 users 表中的数据量
select count(*) from users;
+----------+
| count(*) |
+----------+
| 9 |
+----------+
select count(id) from users;
+-----------+
| count(id) |
+-----------+
| 9 |
+-----------+
-- 上面的两个统计,分别使用了 count(*) 和 count(id),结果目前都一样,有什么区别?
-- count(*) 是按照 users表中所有的列进行数据的统计,只要其中一列上有数据,就可以计算
-- count(id) 是按照指定的 id 字段进行统计,也可以使用别的字段进行统计,
-- 但是注意,如果指定的列上出现了NULL值,那么为NULL的这个数据不会被统计
-- 假设有下面这样的一张表需要统计
+------+-----------+------+--------+-----------+------+------+
| id | name | age | phone | email | sex | mm |
+------+-----------+------+--------+-----------+------+------+
| 1 | 章三 | 22 | | NULL | 男 | 0 |
| 2 | 李四 | 20 | | NULL | 女 | 0 |
| 5 | 王五 | 24 | 10011 | ww@qq.com | 男 | 0 |
| 1000 | aa | 20 | 123 | NULL | 女 | NULL |
| 1001 | bb | 20 | 123456 | NULL | 女 | NULL |
| 1002 | cc | 25 | 123 | NULL | 女 | NULL |
| 1003 | dd | 20 | 456 | NULL | 女 | NULL |
| 1004 | ff | 28 | 789 | NULL | 男 | NULL |
| 1005 | 王五六 | 23 | 890 | NULL | NULL | NULL |
+------+-----------+------+--------+-----------+------+------+
9 rows in set (0.00 sec)
-- 如果按照sex这一列进行统计,结果就是8个而不是9个,因为sex这一列中有NULL值存在
mysql> select count(sex) from users;
+------------+
| count(sex) |
+------------+
| 8 |
+------------+

聚合函数除了以上简单的使用意外,通常情况下都是配合着分组进行数据的统计和计算

 

9.8. 函数分组 GROUP BY 与 HAVING

GROUP BY

SQL聚集函数可用来汇总数据。这使我们能够对行进行计数,计算和与平均数,获得最大和最小值而不用检索所有数据

目前为止的所有计算都是在表的所有数据或匹配特定的WHERE子句的数据上进行的。

例如我们需要获取某个班级的学员人数:

select count(*) as nums from stu where class_id = 2

但如果要返回每个班级的人数怎么办?

此时就需要使用分组了,分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

select class_ id, count(*) as nums from stu group by class_ id

那么如果需要返回人数少于5人的班级怎么办?

或返回班级人数大于5人的班级怎么办?

 使用Group By 进行分组时的注意点

在使用group by分组时,一般除了聚合函数,其它在select后面出现的字段列都需要出现在grouop by 后面

-- 统计 users 表中 男女生人数,
-- 很明显按照上面的需要,可以写出两个语句进行分别统计
select count(*) from users where sex = '女';
select count(*) from users where sex = '男';
-- 可以使用分组进行统计,更方便
select sex,count(*) from users group by sex;
+------+----------+
| sex | count(*) |
+------+----------+
| 男 | 4 |
| 女 | 5 |
+------+----------+
-- 统计1班和2班的人数
select classid,count(*) from users group by classid;
+---------+----------+
| classid | count(*) |
+---------+----------+
| 1 | 5 |
| 2 | 4 |
+---------+----------+
-- 分别统计每个班级的男女生人数
select classid,sex,count(*) as num from users group by classid,sex;
+---------+------+-----+
| classid | sex | num |
+---------+------+-----+
| 1 | 男 | 2 |
| 1 | 女 | 3 |
| 2 | 男 | 2 |
| 2 | 女 | 2 |
+---------+------+-----+
# 注意,在使用。group by分组时,一般除了聚合函数,其它在select后面出现的字段列都需要出现在grouop by 后
面

HAVING 子句

除了能用GROUP BY分组数据外,MySQL还允许过滤分组,规定包括哪些分组,排除哪些分组。

例如,可能想要列出至少有两个订单的所有顾客。为得出这种数据,必须基于完整的分组而不是个别的行进行过滤

事实上,目前为止所学过的所有类型的WHERE子句都可以用HAVING来替代。

唯一的差别是where过滤行,而having过滤分组。

-- 要统计班级人数
select classid,count(*) from users group by classid;
-- 统计班级人数,并且要人数达到5人及以上
select classid,count(*) as num from users group by classid having num >=5;

10、MySQL数据库数据的导入导出和授权

10.1 数据导出

1.数据库数据导出

# 不要进入mysql,然后输入以下命令 导出某个库中的数据

mysqldump -u root -p tlxy > ~/Desktop/code/tlxy.sql

导出一个库中所有数据,会形成一个建表和添加语句组成的sql文件

之后可以用这个sql文件到别的库,或着本机中创建或回复这些数据

2.将数据库中的表导出

# 不要进入mysql,然后输入以下命令 导出某个库中指定的表的数据 

mysqldump -u root -p tlxy tts > ~/Desktop/code/tlxy-tts.sql

10.2 数据导入

把导出的sql文件数据导入到mysql数据库中

# 在新的数据库中 导入备份的数据,导入导出的sql文件
mysql -u root -p ops < ./tlxy.sql
# 把导出的表sql 导入数据库
mysql -u root -p ops < ./tlxy-tts.sql

10.3 权限管理

mysql中的root用户是数据库中权限最高的用户,千万不要用在项目中。

可以给不同的用户,或者项目,创建不同的mysql用户,并适当的授权,完成数据库的相关操作

这样就一定程度上保证了数据库的安全。

创建用户的语法格式:

grant 授权的操作 on 授权的库.授权的表 to 账户@登录地址 identified by ‘密码’;

示例:

# 在mysql中 创建一个 zhangsan 用户,授权可以对tlxy这个库中的所有表 进行 添加和查询 的权限
grant select,insert on tlxy.* to zhangsan@'%' identified by '123456';
# 用户 lisi。密码 123456 可以对tlxy库中的所有表有 所有操作权限
grant all on tlxy.* to lisi@'%' identified by '123456';
# 删除用户
drop user 'lisi'@'%';

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值