Skip to content

在多表连接查询的结果上直接更改,自动映射到对应的数据表,执行更新。(解决 DataGrip 的不足之一)

License

Notifications You must be signed in to change notification settings

Huaguang-XinZhe/JointQueryUpdater

Repository files navigation

joint-query-updater

「联查直更」项目前端

后端地址:https://github.com/Huaguang-XinZhe/JointQueryUpdaterBackend?tab=readme-ov-file

简介

image-20240227100444592

这是一个非常简单的 “项目”(或许算不上项目),前端用 Vue2 + 原始的前端三件套构建(用了少许的 Element UI),后端用 Spring Boot + MyBatis 构建。目前已经部署上线,可通过此域名❓访问。

背景

为什么我要做这个 “项目” ?

我有一个记录的习惯,平时会不自觉的收集一些想法、疑问、待办、需求等等,这些东西都在同一个入口(Typora)进行记录,日渐累积。

image-20240227103410043

等到终于有空了,我对这些记录进行整理,集中打标,然后通过程序扫描,分列,入库。这样方便我通过 SQL 语句进行查询分析,也能快速、批量修改一些数据。

根据记录数据的结构,我创建了以下两张表:

-- 创建一张输入表(主表)
create table myinput(
    id int primary key auto_increment,
    content text not null -- TEXT 类型理论上可以存储 65535 个字符的数据(实际会小于这个数),够用了
);

-- 创建一张标签表
create table mytag(
    id int primary key auto_increment,
    input_id int not null,
    c1 varchar(20) not null,
    c2 varchar(50),
    c3 varchar(50),

    foreign key (input_id) references myinput(id) -- 外键在多的一方
);

呈现如下结构:

image-20240227103615540

image-20240227103700647

很好,现在就可以自由分析、修改了。

我执行了这条联查 SQL:

select i.content, t.c1, t.c2
from myinput i
left join mytag t on i.id = t.input_id
where t.c1 = '待办';

但当我试图修改时,却提示说结果是只读的:

image-20240227105502298

在 GPT 的帮助下,我在以上 SQL 的上方加了一句,创建了一个视图:

create view v_c1 as

这次允许修改了,但提交后还是报错了:

image-20240227110221556

仔细查看其更新 SQL:

ling_guang> UPDATE ling_guang.v_c1 t SET t.c1 = 'Typora' WHERE t.content LIKE '在暗黑模式下需要修改一下滚动条的颜色,增强对比度。' ESCAPE '#' AND t.c1 LIKE '待办' ESCAPE '#' AND t.c2 LIKE 'Typora 样式' ESCAPE '#'

t 表(mytag 表)中是没有 content 字段的,t.content 不管怎样模糊匹配,都找不到对应的可更新条目。

我又反复测试了几次,也试了试单表查询,发现单表查询的结果是可以修改的,对单表查询创建的视图也是,而多表联查就不行!

那怎么办呢?我只能通过联查才能在看到内容的同时看到其标签呀,而且我是有可能对数据进行修改的。

如果我能自己掌控更新语句就好了,这样我就能根据修改的位置判断它要更新那张表的哪个字段、哪一行了。

“哪个字段” 好办,“哪一行” 的话,就还需要一点数据。

我得把两张表的 id 在联查的时候暴露出来,这样就能知道是哪一行了。

于是,我创建了这样的视图:

create view v_c2 as
select i.id as myinput_id, t.id as mytag_id, i.content, t.c1, t.c2
from myinput i
left join mytag t on i.id = t.input_id
where t.c1 = '待办';

但结果依然不理想:

image-20240227113655584

DataGrip 的更新语句让我觉得有点 “傻”,我都给了更新位置所在行的 id 了,它判断一下更新的是哪张表,然后选择那张表的 id 去定点更新不就行了,为啥老是要用模糊匹配呢?

随后,我让 GPT 帮我找找有没有能满足我需求的插件或工具啥的,但没找到,这符合我的预期,毕竟这个需求太小、太细了。

看来,我只能自己造了。

彼时我正在学习 Vue2,也正好有这个能力,那就干吧。

使用

我管这个 “应用” 叫「联查直更」,取 “能在多表联查的结果上直接修改更新” 之意。目前该功能确已实现。

用的时候,只需要将联查 SQL 复制粘贴到输入框中,然后点击确定或按下 Ctrl + Enter,即可将该 SQL 语句发至服务器远程执行,并返回数据,过滤无关列(默认)后展示。

然后便可在查询结果上直接修改了,修改过的单元格会高亮显示,全部修改完成后可点击 “全部提交”(仿 DataGrip 设计),而后程序会根据所有修改的位置自动生成相应的更新语句,完成更新并返回结果。

image-20240227163226312

原理

每一个修改单元格都是一个更新对象,多个更新对象形成一个列表,一同发送到服务器。

@Data
public class UpdateObj {
//    String originalValue;
    @JsonProperty("changedValue")
    String value;
    @JsonProperty("fieldName")
    String column;
    @JsonProperty("rowId")
    int id;
    @JsonProperty("tableName")
    String table;
}

为优化性能,同一张表同一行的不同列将会放在一起更新:

// 对 updateObjs 进行分组
Map<UpdateKey, Map<String, Object>> groupedUpdates = new HashMap<>();

for (UpdateObj updateObj : updateObjs) {
    UpdateKey key = new UpdateKey(updateObj.getTable(), updateObj.getId());
    // computeIfAbsent() 方法的作用是:如果 key 不存在,则创建一个新的 value,否则返回已存在的 value
    groupedUpdates.computeIfAbsent(key, k -> new HashMap<>())
            .put(updateObj.getColumn(), updateObj.getValue());
}
System.out.println("groupedUpdates = " + groupedUpdates);

而 MyBatis 负责动态生成更新语句:

<!-- 这里的 column 代表 updates(Map) 中的键,而 value 代表其中的值 -->
<update id="updateTable">
    UPDATE ${table}
    SET
    <foreach item="value" index="column" collection="updates" separator=",">
        ${column} = #{value}
    </foreach>
    WHERE id = #{id}
</update>

回顾

这个 “项目” 我花了近一周时间,核心功能已经实现,但还有一些已测试的交互没能应用。

因为我突然发现自己的需求有点简单,稍微忍一忍(交互),把自己的核心诉求解决后好像就没它什么事儿了,感觉再做下去意义不大。

也确实,它并不是必须的,把两个表合为一个表,这不就避免了 “在多表联查结果上直接修改” 的问题了吗?当时怎么没想到呢?还是前期准备工作做的不够,轻易投入了!

颇有点后悔,毕竟又是一个星期。不过,一想到这是对 Vue2 的一次顶好的实践,心情就好多了,我并没有失去太多。

发展

这个 “项目” 还可以继续发展,至少可以把目前写死的部分(表数据)盘活来,可以加上一点 SQL 注入的安全性检测。

这样下次遇到类似情境的时候就可以快速上手,而无需手动修改数据源和表头相关代码了。

有时间的时候再做吧。

About

在多表连接查询的结果上直接更改,自动映射到对应的数据表,执行更新。(解决 DataGrip 的不足之一)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published