bash环境下MySQL批量执行多个文件里的sql语句

目录

 

前言

方法一

方法二

一行命令解决标题需求

命令分段解释


前言

今天想把SQLite里的数据转储到MySQL中,SQLite数据在本地,MySQL在远程服务器的Docker环境中。当时没想着纯靠GUI完成转储操作,结果就按照以下步骤折腾了老久。

  1. 本地使用DataGrip把SQLite数据库里的每个表数据分别导出到一个sql文件
  2. 使用scp把本地导出的几十个sql文件上传到远程服务器
  3. 远程服务器上使用docker cp命令把sql文件传输到MySQL容器里
  4. docker exec命令进入MySQL容器,使用MySQL命令行工具登录到数据库里,使用source执行sql文件里的语句

到最后一步就犯难了。因为有几十个sql文件,source命令也不支持直接执行某目录下的所有sql文件,或者通配符执行多个sql文件,只能接受一个文件路径参数。source帮助原文就是这么说的:

source    (\.) Execute an SQL script file. Takes a file name as an argument.

本来吧,老老实实一个个文件路径输入,把几十个表的数据导入到数据库里也不是多麻烦的事情,但是我呢就是单纯觉得这样做好繁琐,就想着网上有没有什么好的解决方案。

方法一

结果翻了几个博文,都是这么一种思路,写一个shell,建立一个for循环,遍历sql文件存放目录,拿到文件名后,使用echo拼接“source xxx.sql”输出到all.sql文件里,最后mysql命令行里执行all.sql文件就ok了。如下图所示:

#!/bin/bash
dir=`ls ~/tmp/` #定义遍历的目录,这个是你sql的存放路径echo "" > all.sql  #创建一个总的sql文件,注意别跟你现有的重名即可!
for i in $dir
do
    echo "source ~/tmp/$i;" >> all.sql
done
mysql > source ~/tmp/all.sql;

还有个加强版的直接调用mysql命令行工具执行拼接好的命令,那一脚本就完成所有事情了。 

这其实就很省事了,但是我就非得自找麻烦。当时就想着以前使用过很多次,仅仅使用一行shell解决了很多事情,感觉无所不能的awk命令,也许能写一行解决现在的需求。

但是awk对我来说实在过于复杂,不看教程实例,很多用法都记不住。不过awk能把其他命令的多行标准输出,作为输入,做一些转换再输出,甚至里面还能执行子命令这我还是能记住的,所以我就想折腾一下。

然而,想起以往子命令嵌套转移那写法实在过于复杂缺乏简洁易懂的关系,于是又想了一下,结合xargs命令,也许就能做到了。xargs在我印象里作用也是跟awk类似,可以把一条命令的标准输出,作为参数传递给另外的命令。结果经过我的不懈努力,总算是把命令给写出来了,这就是我这个小菜鸡苦恼已久的方法二。

方法二

一行命令解决标题需求

 cd /root/sql && ls *.sql|awk '{print "'\''source " $0 "'\''"}'|xargs -L 1 -t mysql -u gogs gogs -e

命令分段解释

 命令看起来有点长,但还是挺好懂的,以管道符“|”分开几段结合来说。

第一段这是先进入/root/sql目录,这个目录就是我存放sql文件的目录,然后呢通过ls列出所有文件名后缀为sql的文件。为方便理解直接贴出 cd /root/sql && ls *.sql输出结果:

第二段是通过管道符把第一段输出的每一行文件名作为awk的输入数据,接着通过内置的print函数打印拼接myql的source命令的语句块。为方便理解直接贴出cd /root/sql && ls *.sql|awk '{print "'\''source " $0 "'\''"}'部分输出结果:

bash环境下MySQL批量执行多个文件里的sql语句_第1张图片

其实可以看到这效果就类似于上面,使用for循环遍历目录再拼接soruce语句块的效果了。

接着最后是第三段使用了xargs命令,这里拆解两部分来看。先看后半部分mysql后面跟着一串参数,这一整串mysql -u gogs gogs -e命令是以用户gogs连接到gogs数据库,并执行一行命令的意思,但是可以看到-e后面缺少了本来应该有的sql命令参数。其实这就是第三段作用,也就是通过xargs命令,动态把第二段输出的每一行source语句库拼接到mysql -u gogs gogs -e后面,达到导入每个表数据的目的。看前半部分xargs -L 1 -t,-L 1作用是处理第二段的多行输出,把每行输出作为参数输入到mysql -e后面并执行,不然会把第二段的所有标准输出,当成参数拼接到mysql -u gogs gogs -e后面,这语法就错了。接着-t是方便查看最终每次执行的命令是什么样的。最后啰嗦了这么多看看输出结果:

bash环境下MySQL批量执行多个文件里的sql语句_第2张图片

这里已经能看到正在批量执行sql文件,之所以有报错是因为之前导入过一份数据,导致主键重复了。反正虽然走了很多弯路,但是总算是完成想要的效果。

本来也不是多么复杂的命令,可能对于实际业务而言,也不是很实用的命令,但是这毕竟也是提供了一种方法思路嘛,也许就有些特殊情况用得着,所以我希望分享出来可以帮到遇到类似问题的朋友。

最后非常感谢能看到最后的读者,如果我的思路能帮你解决到业务问题的话,就给我点个赞吧,你的一个赞可能就是我写(水)下一篇博文的动力。哈哈,说真的,原创不易,感谢支持,下篇博文再见。

 

你可能感兴趣的:(shell,awk,linux,mysql)