一次MySQL数据导出复盘

1,336 阅读2分钟

前言

最近工作中处理了一次客户的数据导出临时需求,因该功能产品中尚未实现,采用直接从数据库导出的方式救急。过程中有两点心得,本文聊作记录。

需求背景

设有如下的答题记录表:

question_answer_record_tbl.png

需要补充说明的是,这里的id是自增的。由于每道题同一学生可能有多次提交,所以数据记录可能是这样的:

图片.png

现在需要导出每个人每道题最后一次答题记录相关信息。

曲线救国SQL

上面表里用数据库存储问题和答案,可能是不太合理的,这里暂且不论。容易想到,要解决这个问题,必然要对question_idstudent_id分组,再取最大创建时间,然而这样操作后只能取到最大时间,无法指定其所在记录。当然,我们可以先把这些数据查出来,在内存中利用其它语言分组统计获取相关数据,这里暂且不论。

仅使用SQL完成这个需求似乎较为困难,幸运的是,id字段是自增的,因此最大创建时间的记录同时也是最大id取值的记录。于是我们有如下查询:

select student_id , question_id , question_content , answer_content
from question_answer_record_tbl qart
where id in (
    select max(id)
    from question_answer_record_tbl qart
    group by student_id , question_id
);

结果如下:

图片.png

Base64的价值

上面我们查到了需要的数据,接下来需要导出成Excel表格或CSV文件形式。由于生产环境Mysql不支持Dbeaver之类的可视化工具,因此只能借助Mysql自带的一些工具。容易找到如下的导出语句:

select student_id , question_id , question_content , answer_content
INTO OUTFILE '/tmp/result.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
from question_answer_record_tbl qart
where id in (
    select max(id)
    from question_answer_record_tbl qart
    group by student_id , question_id
);

然而新的问题出现了,由于question_contentanswer_content字段可能是大段的文本内容,这些内容很可能含有导出语句中的字段分隔符,造成导出文件格式混乱。实践中构造更复杂的分隔符也未能解决格式混乱问题。

有没有办法能保证导出字段内容不含有字段分隔符呢?容易想到,将容易造成格式混乱的字段Base64编码即可。项目中使用的Mysql版本正好也支持TO_BASE64()函数,最终的导出语句如下:

select student_id , question_id , to_base64(question_content) , to_base64(answer_content)
INTO OUTFILE '/tmp/result.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
from question_answer_record_tbl qart
where id in (
    select max(id)
    from question_answer_record_tbl qart
    group by student_id , question_id
);

当然,这样导出的数据需要再进行Base64解码,这里从略。

我最初接触Base64编码就有疑惑,既不能对数据进行加密,还会增加编码内容的长度,这一过程在实践中有何意义?经过此次使用,我对这一问题有了些微体会。