本文案例只针对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_tab | target_col | source_tab | source_col |
---|---|---|---|
test2join | id | test | id |
test2join | name | test | name |
test2join | age | test1 | age |
然后上述语句可以理解为解析:
update test2 a
join test2join t
on a.id = t.id
set a.name = t.name
a.age = t.age
这段语句和我们最开始分析最简单update语句结构是一样的,就可以按照上述方式处理,解析出来对应血缘关系为:
target_tab | target_col | source_tab | source_col |
---|---|---|---|
test2 | id | test2join | id |
test2 | name | test2join | name |
test2 | age | test2join | age |
最后可以通过递归获取最原始的血缘关系