MySql数据库系列 数据库基础操作

数据库操作

显示当前的数据库

show databases;

sql语句命令结尾 一定要是 ;(英文分号),如果输入 ;(中文分号)则会出现以下现象.

如果后续再输入英文分号,则会报错.

初学时,大概率会出现许多问题,还请各位初学者仔细阅读报错提示,以便于找到出错位置,更正错误.

创建数据库

create database 数据库名;

如果数据库创建成功,则会出现以下结果显示

此时也可以使用 show databases 语句 来检查 刚才的数据库是否创建成功.

如果 创建的数据库已存在则会出现

因此数据库名称 在数据库服务器 上要保持唯一.

注意事项:

1.创建数据库时,数据库的名字,不能和SQL中的"关键字"重复

2.创建数据库的名字,不能和已有的数据库名字重复

创建数据库时,往往还需要指定数据库的"字符集"

create database 数据库名 charset utf8;

如果不能正确指定字符集,后续保存中文字符时,可能会出现错误

选中数据库

use 数据库名;

删除数据库

drop database 数据库名;

删除数据库之后,数据无法恢复,因此是一个非常危险的行为.

数据类型

数据表的操作

前提:已使用use选中数据库

1.查看当前数据库中,有那哪些表

show tables;

2.创建表

create table 表名(列名 类型,列名 类型,.......);

常用类型

int

bigint

double

decimal

varchar(最大字符长度)

datetime

3.查看指定表的详细情况

desc 表名;

4.删除表

drop table 表名;

删表操作,也是一个非常危险的操作

表内容的操作(增删改查)

新增

insert into 表名 values (值,值,值...);

SQL中,表示字符串 可以使用 ' 也可以使用 '' ;

c/c++/Java,,' 表示字符。" 表示字符串

SQL/python/Js,没有字符类型,只有字符串

指定列插入

insert into 表名 (列名,列名) values (值,值,值...);

注意:这里的列的个数和类型,要与表结构匹配

一次插入多行

insert into 表名 values (值,值...),(值,值...),(值,值...);

客户端-服务器 交互过程中,交互的次数越多,整体的开销就越大,花的时间越长

插入时间

例: insert into test into values ("2024-10-03 20:20:20");

插入当前时间 也可以使用SQL的库函数 now();

例: insert into test into values (now());'

查询

所有select 查询操作 都是只针对临时表进行 计算/调整 ,并不影响整个硬盘上的数据

注:以下中 列名 的含义 也包括 * .

全列查询

查询出这个表中的所有的行和所有的列

select * from 表名

* 可以指代 所有的列

注意:select * 是一个很危险的操作

指定列查询

select 列名,列名... from 表名

查询时 指定表达式(列之间进行运算)

这样产生的结果,只是数据库查询过程中,生成的"临时表",数据库本体数据没有任何改变.

起别名

select 表达式 as 别名 from 表名;

去重查询

select distinct 列名 from 表名;

如果有两个或以上的列名,那么其中对应列中都有一一对应的重复,才能触发去重.

排序查询(默认升序)

select 列名 from 表名 order by 列名;

注意:数据库中如果不写order by,那么查询得到的结果顺序是随机的。

降序排序查询

在order by中对应的列名,加上desc 关键字.

select 列名 from 表名 order by 列名 desc;

条件查询

查询过程中,指定筛选条件,满足条件的记录就保留,不满足条件的就跳过

select 列名 from 表名 where 条件;

条件:

范围查询

between a and b

在编程中,大部分谈到的"区间"都是"前闭后开"区间[a,b).

但 SQL 的 between... and... 则是 闭区间 [a,b].

in(a,b,c,.....)

模糊查询

like

模糊匹配,%表示匹配任意数量字符,_表示匹配一个特点字符.

一般条件

and

or

注:and 和 or 同时出现时 有需要优先执行的表达式要加 ( ) .

not

is null

is not null

>,>=

<,<=

=

注:不要使用null 和 = 直接使用

而是 <=> null 的方式,因此 只要含有null 的 列 要进行 = 比较的话 只能使用<=> 进行比较

SQL中 使用 = 表示比较相等.

null = null 的结果是null.

分页查询

select 列名 from 表名 limit N; (限制查询N条记录)

select 列名 from 表名 limit N offset M; (从M开始查N条数据)

修改

update 表名 set 列名 = 值, 列名 = 值, ... where 条件/order by/limit;

删除

delate from 表名 where 条件/order by/limit;

数据库进阶

约束

not null (非空)指示某列不能存储 null 值

unique (唯一)保证某列的每行必须有唯一的值

先看不加unique时的情况

加入unique之后,相同操作语句,产生的结果

default (指定默认值)规定没有给列赋值时的默认值

最初的默认值都是null.

定义了默认值之后的结果

primary key (主键)

not null 和 unique 的结合,确保某列(或两个列多个列的结合)有唯一标识,有助于更容易快速地找到表中的一个特定的记录

当赋null值和重复赋值时,都报出了错误

一个表中不允许同时出现多个主键

主键需要分配一个唯一的值,如何进行分配呢?

mysql 提供了一个 自动分配 主键值 的方式,"自增主键".

插入数据时,可以不指定id列的值,让数据库自动分配,就会按1,2,3,4.....的顺序自动分配.

也可以手动指定其他数值

在mysql中,给每个表都记录了一个"自增主键的最大值",后续继续插入数据时,无论之前的最大值是否存在,都是根据之前保存的最大值,继续往后分配的.

注:自增主键只能针对 像 int/bigint 的整数

foreign key (外键)保证一个表中的数据匹配另一个表中的值的参照完整性

涉及到两张表

但如果没有 foreign key 约束,可以会出现意外

即以下情况:在第一张class表中的classId并没有100,但第二张student表却能插入classId为100的数据.

加入foreign key 之后,不属于 class 表中 classid 中的数据,不能被插入 student 表中.

check (检查)保证列中的值符合指定的条件

查询

聚合查询

聚合函数

count()

sum()

sum 函数 不可以用来求和字符串.

sum 函数 遇到 null 会直接跳过.

注:在之前的表达式计算中,如果有null参与,结果就会为null

avg()

avg 函数 遇到 null 会直接跳过.

max()

max 函数 遇到 null 会直接跳过.

min()

min 函数 遇到 null 会直接跳过.

gourp by

在查询时,group by 大多数 是和 聚合函数 一起使用.

可以针对结果进行排序查询

group by 和 条件 一起使用

分组之前的条件 用 where 关键字.

分组之后的条件 用 having 关键字.

也可以同时使用

多表查询

笛卡尔积

实际上就是把几张表中的数据,进行排列组合

student.classId 中的 . 是 成员访问运算符,翻译为"的".

多表查询的另一种写法

join on 写法

上一种 写法 可以简写为 " , where 写法".

合并查询

union 把多个select 查询结果 合并成一个

union 还可以 将 不同的表 的 查询结果整合到一起,前提是 两个表的列数相同

索引

查看索引

show index from 表名

注:primary key、unique、foreign key 都会自动创建索引

创建索引

create index 索引名 on 表名(列名)

删除索引

drop index 索引名 on 表名

注:只能删除自己创建的索引,不能删除自动生成的索引

事务

事务是用来解决,一些特定场景的问题

这些特定场景需要进行完成的操作,需要多个sql配合完成.

列如:账户转账操作

(补一张图)

假设,账户A向账户B进行转账,而在同一时刻,发生改变的有两个地方,一个是账户A的账户金额数据,另一个是账户B的账户金额数据.

如果此处的操作是sql一句一句进行执行的,当执行A账户数据减少时完成过后,突然发生了电脑死机,或者停电的情况,那么A的账户数据改变了,但B的账户却没有发生改变,这里产生的损失是不可忽视的.

因此所谓事务,就相等于把多个要执行的sql,打包成一个"整体",这个"整体"在执行过程中,要么全部都执行,要么就执行了一部分,再使用回滚机制进行还原.

事务的ACID特点

可靠数据库所具有的四个特性:原子性,一致性,持久性,隔离性.

事务最核心的特性,就是原子性。

原子性

指事务是一个不可再分割的工作单位.事务中的操作要么全部执行,要么都不执行.

一致性

事务执行前和执行后,数据库中的数据,都是"合法状态",不会出现非法的临时结果.

持久性

事务执行完毕之后,就会修改硬盘上的数据,事务都是持久生效的.

隔离性

在并发执行时,当不同的事务同时操作时,每个事务各自都是独立的.

如果这些同时执行的事务,恰好是针对同一张表,进行一些增删改查操作,此时可能会引入一些问题.

脏读(读取未提交的数据)

有两个事务A和B并发执行,其中事务A在针对某个表的数据进行修改,A执行过程中,B也去读取这个表的数据,当B读完之后,A把表中的数据修改了.

这就导致,B读到的数据,就不是最终的"正确数据",而是读到了临时性的数据(脏数据).

不可重复读(前后多次读取,数据内容不一致)

此时,有三个事务,ABC

首先,事务A执行一个修改操作,A执行完毕时,提交数据,接下来事务B执行,事务B读取刚才A提交的数据,在B读取的过程中,事务C对刚才A修改的数据进行了修改

此时对应B来说,再读取数据时,读到的结果就和第一次读到的结果时不同的

此过程就叫"不可重复读"

幻读

有一个事务A在读取数据,读的过程中,另一个事务B,修改了一些其他数据,此时站在A的角度,多次读取的数据内容虽然一样,但"结果集"不同

这三个问题"脏读","不可重复读","幻读"和隔离性的关系

mysql中提供了四个隔离级别,可以通过配置文件来设置当前服务器的隔离级别是哪个级别

设置不同的隔离级别,就会使事务之间的并发执行的影响产生不同的差别,从而影响上述三个问题的情况

1)read uncommitted 读未提交

这种情况下,一个事务可以读取另一个事务未提交的数据,此时,就可能产生 脏读,不可重复读,幻读 三种问题.

此时,多种事务并发执行程度是最高的,执行速度也是最快的.

2)read committed 读已提交

这种情况下,一个事务只能读取另一个事务提交之后的数据,此时,可能会产生 不可重复读,幻读问题(脏读问题已解决~~)

此时,并发程度会降低,执行速度变慢,同时,事务之间的隔离性提高(事务之间的相互影响变小了,得到的数据更准确了~~)

3)repeatable read 可重复读(mysql默认)

这种情况下,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务的影响

此时,可能产生幻读问题,解决了脏读和不可重复读问题

并发程度进一步降低,执行速度进一步变慢,事务之间的隔离性,进一步提高

4)serializable 串行化

此时,所有的事务都是在服务器上一个接一个执行的

此时,解决了脏读,不可重复读,幻读问题

并发程度最低,执行速度最慢,隔离性最高,数据最准确.

看到此处,我们可能会发出疑问,我们为什么不一直用最后一个串行化,这样所有数据都是最准确的?

对此,我们需要看具体情况,有时我们需要更快的场景,那么准确性需要稍微牺牲一下(比如说短视频的点赞数),但有时我们需要更准确的场景(账户转账).

相关推荐
周末吃鱼16 小时前
mysql8.0支持CURRENT_DATE如何写
数据库·sql·mysql
kaico201816 小时前
MySQL的窗口函数
数据库·mysql
MM_MS16 小时前
Halcon控制语句
java·大数据·前端·数据库·人工智能·算法·视觉检测
薛定谔的猫198216 小时前
LlamaIndex(三) LlamaHub工具集
数据库·mysql·llamahub
小画家~16 小时前
第四十六: channel 高级使用
java·前端·数据库
晴天¥16 小时前
了解Oracle中的体系结构
数据库
DemonAvenger17 小时前
Redis慢查询分析与优化:性能瓶颈排查实战指南
数据库·redis·性能优化
Li_yizYa17 小时前
Redis-常见数据类型及应用场景
java·数据库·redis
尽兴-17 小时前
SQL 执行失败如何回滚?事务已提交还能恢复吗?——MySQL 误操作数据恢复全指南
sql·mysql·binlog·undolog·redolog