血缘解析<三>:如何解析DML语句?

本文案例只针对Mysql中的语句,其它数据库的DML语句可自行扩展

一、insert…select…on duplicate update…

eg:

insert into test (id,name,age)
select id,name,age from test1 t
    on duplicate key 
update id = t.id,
       name = t.name,
       age = t.age;

上述sql是Mysql的一段upsert逻辑

  • 获取目标表
SQLInsertStatement sqlInsertStatement = (SQLInsertStatement) statement;
String target_tab = sqlInsertStatement.getTableName().getSimpleName();
  • 获取源表、源字段、目标字段

上述insert语句的加工过程实际上是select部分,可单独获取select部分传入之前写好的解析select语句模块,详情可看血缘解析思路

  • 获取select部分
String sql_text = sqlInsertStatement.getQuery().toString();
if (sql_text != null) {
    Analyze.analyzSelect(sql_text, target_schema, target_tab);
}

二、update…join…on…set…

eg1:

update test a
  join test1 t
    on a.id = t.id 
   set a.name = t.name
       a.age = t.age

上述sql是Mysql中最简单的用一张表更新另一种表字段的语句

  • 获取目标表
SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement) statement;
String target_tab = sqlUpdateStatement.getTableName().getSimpleName();
  • 获取源表
SQLTableSource tablesource = sqlUpdateStatement.getTableSource();
if (tablesource instanceof SQLJoinTableSource) {
	tablesource = ((SQLJoinTableSource) tablesource).getRight();
}
  • 获取源字段、目标字段
List<SQLUpdateSetItem> col_lists = sqlUpdateStatement.getItems();
for (SQLUpdateSetItem col_list : col_lists) {
    target_col = col_list.getColumn().toString();
    if (target_col != null) {
        if (target_col.contains(".")) {
            target_col = target_col.substring(target_col.indexOf(".") + 1);
        }
    } else {
        target_col = "-";
    }
    source_col = col_list.getValue().toString();
    if (source_col != null) {
        if (source_col.contains(".")) {
            source_col = source_col.substring(source_col.indexOf(".") + 1);
        }
    } else {
        source_col = "-";
    }
}

上述代码可以获取到简单update语句的字段血缘关系,针对一些较复杂的语句,比如下述语句,应该如何处理呢?

update test2 a
  join (select a.id,a.name,b.age from test a join test1 b on a.id = b.id) t
    on a.id = t.id 
   set a.name = t.name
       a.age = t.age

获取目标表、源表、源字段的方式和上述简单update语句的获取方式一样,区别是获取源表,这里的处理方式和上篇文章处理with cte语句的方式差不多;
join后面跟的是一段子查询,这个子查询可以当做一个临时表的加工过程,临时表我们可以自定义一个,比如target_tab + ‘join’,然后把子查询传入select解析模块,这时候获取到的血缘关系如下述表格:

target_tabtarget_colsource_tabsource_col
test2joinidtestid
test2joinnametestname
test2joinagetest1age

然后上述语句可以理解为解析:

update test2 a
  join test2join t
    on a.id = t.id 
   set a.name = t.name
       a.age = t.age

这段语句和我们最开始分析最简单update语句结构是一样的,就可以按照上述方式处理,解析出来对应血缘关系为:

target_tabtarget_colsource_tabsource_col
test2idtest2joinid
test2nametest2joinname
test2agetest2joinage

最后可以通过递归获取最原始的血缘关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱夜来香A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值