0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

最经典的数据库之一MySQL的语法

dyquk4xk2p3d 来源:良许Linux 2023-01-04 14:55 次阅读

前言

大家好,我是良许。

数据库和 SQL 语句几乎是所有程序员的必修课,但是据我观察下来,学校教的数据库和 SQL 都比较基础和 “机械”,以至于很多同学对数据库的印象就是增删改查,自己写 SQL 的能力也很差。

像我在从事了一段时间数据开发后,接触到了更多的 SQL 语法,也才意识到之前学的、用的 SQL 还是太少了。

今天就给大家分享一些非常有用的 SQL 语句,并不复杂,希望大家要用到的时候能想起来有这么一些东西。

下面以最经典的数据库之一 MySQL 的语法为例,其实很多语法和函数其他的数据库也是支持的。

1.group_concat

在我们平常的工作中,使用group by进行分组的场景,是非常多的。

比如想统计出用户表中,名称不同的用户的具体名称有哪些?

具体sql如下:

selectnamefrom`user`
groupbyname;

但如果想把name相同的code拼接在一起,放到另外一列中该怎么办呢?

答:使用group_concat函数。

例如:

selectname,group_concat(code)from`user`
groupbyname;

执行结果:ed8c852a-8bf1-11ed-bfe3-dac502259ad0.png使用group_concat函数,可以轻松的把分组后,name相同的数据拼接到一起,组成一个字符串,用逗号分隔。

2.char_length

有时候我们需要获取字符的长度,然后根据字符的长度进行排序

MYSQL给我们提供了一些有用的函数,比如:char_length

通过该函数就能获取字符长度。

获取字符长度并且排序的sql如下:

select*frombrandwherenamelike'%苏三%'
orderbychar_length(name)asclimit5;

执行效果如图所示:ed9e98f0-8bf1-11ed-bfe3-dac502259ad0.pngname字段使用关键字模糊查询之后,再使用char_length函数获取name字段的字符长度,然后按长度升序

3.locate

有时候我们在查找某个关键字,比如:良许,需要明确知道它在某个字符串中的位置时,该怎么办呢?

答:使用locate函数。

使用locate函数改造之后sql如下:

select*frombrandwherenamelike'%苏三%'
orderbychar_length(name)asc,locate('苏三',name)asclimit5,5;

先按长度排序,小的排在前面。如果长度相同,则按关键字从左到右进行排序,越靠左的越排在前面。

除此之外,我们还可以使用:instrposition函数,它们的功能跟locate函数类似,在这里就不一一介绍了。

4.replace

我们经常会有替换字符串中部分内容的需求,比如:将字符串中的字符A替换成B。

这种情况就能使用replace函数。

例如:

updatebrandsetname=REPLACE(name,'A','B')
whereid=1;

这样就能轻松实现字符替换功能。

也能用该函数去掉前后空格

updatebrandsetname=REPLACE(name,'','')wherenamelike'%';
updatebrandsetname=REPLACE(name,'','')wherenamelike'%';

使用该函数还能替换json格式的数据内容,真的非常有用。

5.now

时间是个好东西,用它可以快速缩小数据范围,我们经常有获取当前时间的需求。

在MYSQL中获取当前时间,可以使用now()函数,例如:

selectnow()frombrandlimit1;

返回结果为下面这样的:edaa6c84-8bf1-11ed-bfe3-dac502259ad0.png它会包含年月日时分秒

如果你还想返回毫秒,可以使用now(3),例如:

selectnow(3)frombrandlimit1;

返回结果为下面这样的:edb6fe2c-8bf1-11ed-bfe3-dac502259ad0.png使用起来非常方便好记。

6.insert into ... select

在工作中很多时候需要插入数据

传统的插入数据的sql是这样的:

INSERTINTO`brand`(`id`,`code`,`name`,`edit_date`)
VALUES(5,'108','苏三','2022-09-021921');

它主要是用于插入少量并且已经确定的数据。但如果有大批量的数据需要插入,特别是是需要插入的数据来源于,另外一张表或者多张表的结果集中。

这种情况下,使用传统的插入数据的方式,就有点束手无策了。

这时候就能使用MYSQL提供的:insert into ... select语法。

例如:

INSERTINTO`brand`(`id`,`code`,`name`,`edit_date`)
selectnull,code,name,now(3)from`order`wherecodein('004','005');

这样就能将order表中的部分数据,非常轻松插入到brand表中。

7.insert into ... ignore

不知道你有没有遇到过这样的场景:在插入1000个品牌之前,需要先根据name,判断一下是否存在。如果存在,则不插入数据。如果不存在,才需要插入数据。

如果直接这样插入数据:

INSERTINTO`brand`(`id`,`code`,`name`,`edit_date`)
VALUES(123,'108','苏三',now(3));

肯定不行,因为brand表的name字段创建了唯一索引,同时该表中已经有一条name等于苏三的数据了。

执行之后直接报错了:edbf1c24-8bf1-11ed-bfe3-dac502259ad0.png这就需要在插入之前加一下判断。

当然很多人通过在sql语句后面拼接not exists语句,也能达到防止出现重复数据的目的,比如:

INSERTINTO`brand`(`id`,`code`,`name`,`edit_date`)
selectnull,'108','苏三',now(3)
fromdualwherenotexists(select*from`brand`wherename='苏三');

这条sql确实能够满足要求,但是总觉得有些麻烦。那么,有没有更简单的做法呢?

答:可以使用insert into ... ignore语法。

例如:

INSERTignoreINTO`brand`(`id`,`code`,`name`,`edit_date`)
VALUES(123,'108','苏三',now(3));

这样改造之后,如果brand表中没有name为苏三的数据,则可以直接插入成功。

但如果brand表中已经存在name为苏三的数据了,则该sql语句也能正常执行,并不会报错。因为它会忽略异常,返回的执行结果影响行数为0,它不会重复插入数据。

8.select ... for update

MYSQL数据库自带了悲观锁,它是一种排它锁,根据锁的粒度从大到小分为:表锁间隙锁行锁

在我们的实际业务场景中,有些情况并发量不太高,为了保证数据的正确性,使用悲观锁也可以。

比如:用户扣减积分,用户的操作并不集中。但也要考虑系统自动赠送积分的并发情况,所以有必要加悲观锁限制一下,防止出现积分加错的情况发生。

这时候就可以使用MYSQL中的select ... for update语法了。

例如:

begin;
select*from`user`whereid=1
forupdate;

//业务逻辑处理

update`user`setscore=score-1whereid=1;
commit;

这样在一个事务中使用for update锁住一行记录,其他事务就不能在该事务提交之前,去更新那一行的数据。

需要注意的是for update前的id条件,必须是表的主键或者唯一索引,不然行锁可能会失效,有可能变成表锁

9.on duplicate key update

通常情况下,我们在插入数据之前,一般会先查询一下,该数据是否存在。如果不存在,则插入数据。如果已存在,则不插入数据,而直接返回结果。

在没啥并发量的场景中,这种做法是没有什么问题的。但如果插入数据的请求,有一定的并发量,这种做法就可能会产生重复的数据。

当然防止重复数据的做法很多,比如:加唯一索引加分布式锁等。

但这些方案,都没法做到让第二次请求也更新数据,它们一般会判断已经存在就直接返回了。

这种情况可以使用on duplicate key update语法。

该语法会在插入数据之前判断,如果主键或唯一索引不存在,则插入数据。如果主键或唯一索引存在,则执行更新操作。

具体需要更新的字段可以指定,例如:

INSERTINTO`brand`(`id`,`code`,`name`,`edit_date`)
VALUES(123,'108','苏三',now(3))
onduplicatekeyupdatename='苏三',edit_date=now(3);

这样一条语句就能轻松搞定需求,既不会产生重复数据,也能更新最新的数据。

但需要注意的是,在高并发的场景下使用on duplicate key update语法,可能会存在死锁的问题,所以要根据实际情况酌情使用。

10.show create table

有时候,我们想快速查看某张表的字段情况,通常会使用desc命令,比如:

desc`order`;

结果如图所示:edcd4fb0-8bf1-11ed-bfe3-dac502259ad0.png确实能够看到order表中的字段名称、字段类型、字段长度、是否允许为空,是否主键、默认值等信息

但看不到该表的索引信息,如果想看创建了哪些索引,该怎么办呢?

答:使用show index命令。

比如:

showindexfrom`order`;

也能查出该表所有的索引:edd9cab0-8bf1-11ed-bfe3-dac502259ad0.png但查看字段和索引数据呈现方式,总觉得有点怪怪的,有没有一种更直观的方式?

答:这就需要使用show create table命令了。

例如:

showcreatetable`order`;

执行结果如图所示:eded6872-8bf1-11ed-bfe3-dac502259ad0.png其中Table表示表名Create Table就是我们需要看的建表信息,将数据展开:edf49502-8bf1-11ed-bfe3-dac502259ad0.png我们能够看到非常完整的建表语句,表名、字段名、字段类型、字段长度、字符集、主键、索引、执行引擎等都能看到。

非常直接明了。

11.create table ... select

有时候,我们需要快速备份表。

通常情况下,可以分两步走:

  1. 创建一张临时表
  2. 将数据插入临时表

创建临时表可以使用命令:

createtableorder_2022121819like`order`;

创建成功之后,就会生成一张名称叫:order_2022121819,表结构跟order一模一样的新表,只是该表的数据为空而已。

接下来使用命令:

insertintoorder_2022121819select*from`order`;

执行之后就会将order表的数据插入到order_2022121819表中,也就是实现数据备份的功能。

但有没有命令,一个命令就能实现上面这两步的功能呢?

答:用create table ... select命令。

例如:

createtableorder_2022121820
select*from`order`;

执行完之后,就会将order_2022121820表创建好,并且将order表中的数据自动插入到新创建的order_2022121820中。

一个命令就能轻松搞定表备份

12.explain

很多时候,我们优化一条sql语句的性能,需要查看索引执行情况。

答:可以使用explain命令,查看mysql的执行计划,它会显示索引的使用情况

例如:

explainselect*from`order`wherecode='002';

结果:ee131b4e-8bf1-11ed-bfe3-dac502259ad0.png

通过这几列可以判断索引使用情况,执行计划包含列的含义如下图所示:ee1cfa6a-8bf1-11ed-bfe3-dac502259ad0.png

说实话,sql语句没有走索引,排除没有建索引之外,最大的可能性是索引失效了。

下面说说索引失效的常见原因:

ee3f462e-8bf1-11ed-bfe3-dac502259ad0.png如果不是上面的这些原因,则需要再进一步排查一下其他原因。

13.show processlist

有些时候我们线上sql或者数据库出现了问题。比如出现了数据库连接过多问题,或者发现有一条sql语句的执行时间特别长。

这时候该怎么办呢?

答:我们可以使用show processlist命令查看当前线程执行情况

如图所示:eea09474-8bf1-11ed-bfe3-dac502259ad0.png从执行结果中,我们可以查看当前的连接状态,帮助识别出有问题的查询语句。

  • id 线程id
  • User 执行sql的账号
  • Host 执行sql的数据库的ip和端号
  • db 数据库名称
  • Command 执行命令,包括:Daemon、Query、Sleep等。
  • Time 执行sql所消耗的时间
  • State 执行状态
  • info 执行信息,里面可能包含sql信息。

如果发现了异常的sql语句,可以直接kill掉,确保数据库不会出现严重的问题。

14.mysqldump

有时候我们需要导出 MYSQL 表中的数据。

这种情况就可以使用mysqldump工具,该工具会将数据查出来,转换成insert语句,写入到某个文件中,相当于数据备份

我们获取到该文件,然后执行相应的insert语句,就能创建相关的表,并且写入数据了,这就相当于数据还原

mysqldump命令的语法为:mysqldump -h主机名 -P端口 -u用户名 -p密码 参数1,参数2.... > 文件名称.sql

备份远程数据库中的数据库:

mysqldump-h192.22.25.226-uroot-p123456dbname>backup.sql

审核编辑 :李倩



声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3793

    浏览量

    64340
  • 函数
    +关注

    关注

    3

    文章

    4326

    浏览量

    62557
  • MySQL
    +关注

    关注

    1

    文章

    804

    浏览量

    26519

原文标题:有哪些简单好用,但学校不教的 SQL 语法?

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    数据库数据恢复—Mysql数据库表记录丢失的数据恢复流程

    Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、
    的头像 发表于 12-16 11:05 75次阅读
    <b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复—<b class='flag-5'>Mysql</b><b class='flag-5'>数据库</b>表记录丢失的<b class='flag-5'>数据</b>恢复流程

    数据库数据恢复—MYSQL数据库ibdata1文件损坏的数据恢复案例

    mysql数据库故障: mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用my
    的头像 发表于 12-09 11:05 107次阅读

    香港云服务器怎么部署MySQL数据库

    在香港云服务器上部署MySQL数据库的步骤如下: 步骤 1: 更新软件包列表 首先,确保软件包列表是最新的。在终端中执行以下命令: sudo apt update 步骤 2: 安装 MySQL
    的头像 发表于 11-14 16:15 152次阅读

    数据库数据恢复—通过拼接数据库碎片恢复SQLserver数据库

    个运行在存储上的SQLServer数据库,有1000多个文件,大小几十TB。数据库每10天生成个NDF文件,每个NDF几百GB大小。数据库
    的头像 发表于 10-31 13:21 192次阅读
    <b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复—通过拼接<b class='flag-5'>数据库</b>碎片恢复SQLserver<b class='flag-5'>数据库</b>

    适用于MySQL的dbForge架构比较

    dbForge Schema Compare for MySQL种工具,用于轻松有效地比较和部署 MySQL 数据库结构和脚本文件夹差异。该工具提供了
    的头像 发表于 10-28 09:41 188次阅读
    适用于<b class='flag-5'>MySQL</b>的dbForge架构比较

    恒讯科技分析:云数据库mysql有何优缺点?

    的基础。下面,小编就详细给大家分析下云数据库mysql有何优缺点?、云数据库mysql的优点:1、总成本采用云
    的头像 发表于 10-23 15:08 144次阅读
    恒讯科技分析:云<b class='flag-5'>数据库</b><b class='flag-5'>mysql</b>有何优缺点?

    数据库数据恢复—SQL Server数据库出现823错误的数据恢复案例

    SQL Server数据库故障: SQL Server附加数据库出现错误823,附加数据库失败。数据库没有备份,无法通过备份恢复数据库
    的头像 发表于 09-20 11:46 334次阅读
    <b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复—SQL Server<b class='flag-5'>数据库</b>出现823错误的<b class='flag-5'>数据</b>恢复案例

    华纳云:MySQL初始化操作如何创建新的数据库

    要在MySQL中创建个新的数据库,可以按照以下步骤进行操作: 登录到MySQL数据库管理系统中。可以使用
    的头像 发表于 09-04 14:30 250次阅读

    恒讯科技分析:跨境电商网站有哪些数据库系统是推荐使用的?

    对于跨境电商网站,数据库系统的选择非常关键,以下是些推荐使用的数据库系统: 1、MySQLMySQL
    的头像 发表于 08-12 15:01 326次阅读

    恒讯科技分析:sql数据库怎么用?

    SQL数据库的使用通常包括以下几个基本步骤: 1、选择数据库系统: 选择适合您需求的SQL数据库系统,如MySQL、PostgreSQL、Microsoft SQL Server、SQ
    的头像 发表于 07-15 14:40 342次阅读

    数据库数据恢复—raid5阵列上层Sql Server数据库数据恢复案例

    数据库数据恢复环境: 5块硬盘组建组RAID5阵列,划分LUN供windows系统服务器使用。windows系统服务器内运行了Sql Server数据库,存储空间在操作系统层面划分
    的头像 发表于 05-08 11:43 502次阅读
    <b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复—raid5阵列上层Sql Server<b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复案例

    数据库数据恢复】Oracle数据库ASM实例无法挂载的数据恢复案例

    oracle数据库ASM磁盘组掉线,ASM实例不能挂载。数据库管理员尝试修复数据库,但是没有成功。
    的头像 发表于 02-01 17:39 511次阅读
    【<b class='flag-5'>数据库</b><b class='flag-5'>数据</b>恢复】Oracle<b class='flag-5'>数据库</b>ASM实例无法挂载的<b class='flag-5'>数据</b>恢复案例

    怎么简单实现由Labview读取的串口数据自增写入mysql5.7数据库中?

    怎么简单实现由Labview读取的串口数据自增写入mysql5.7数据库中? 已实现:串口数据的接收处理 mysql5.7的安装(已测试
    发表于 01-11 22:05

    MySQL数据库中通用表空间详解

    MySQL 数据库中有效管理存储和性能至关重要,通用表空间为实现这目标提供了灵活性。本文讨论通用表空间并探讨其功能、优点和实际用法,并附有说明性示例。
    的头像 发表于 01-10 09:33 2223次阅读

    mysql怎么新建数据库

    mysql怎么新建数据库 如何新建数据库MySQL中 创建
    的头像 发表于 12-28 10:01 882次阅读