一、概述
作为开发的一部分,MySQL语句的应用很重要,可以简化很多代码上的处理逻辑,从而简化开发。本文本人在实际使用中的总结,主要是一些非简单的增删改查、注意事项等内容,并且会不断更新。
二、检索
2.1 树形结构递归语句
一般是涉及到树形结构的库表结构,比如:菜单、部门等,存在上下级关系。检索时,获取当前以及子集的情况下使用,但是要是树形展示需要自己处理,一下会将java的处理代码一并奉上。
表结构:(后续使用相关表不再展示)
SQL语句:
WITH RECURSIVE children AS (
SELECT d.* FROM depart d WHERE d.depart_name = '教务处'
UNION ALL
SELECT d.* FROM children c, depart d WHERE d.parent_id = c.id
) SELECT * FROM children;
==注:==
- 检索条件不同展示效果也不一样,精确到具体条件时比较明确,如果条件下多数据时,如并列部门、并列菜单等;
- 上面SQL只有 > depart <一个表,children是用来收集子集的;
- 表内必须包含你检索所需条件以及上下级关联字段,如parent_id等。
效果:
Java递归树形
自己编写递归方法:
private List<Menu> recursiveTree(Integer pId,List<Menu> newList) {
List<Menu> treeNodes = newList.stream().filter(permissionMenu-> permissionMenu.getParentId()==pId).collect(Collectors.toList());
treeNodes.forEach(sysPerMenu->{
List<Menu> treeNodes1 = recursiveTree(sysPerMenu.getId(),newList);
sysPerMenu.setChildren((!treeNodes1.isEmpty())?treeNodes1:new ArrayList<>());
});
return treeNodes;
}
==注:==
- 用到了java8的流库,不难,都系较多,多用用就好;
- 方法条件很明显,与SQL语句类似,条件2 的集合就是检索出来的全部数据,需要注意的是关联条件。菜单表就不展示了,和部门一个意思。
hutool工具提供的树形工具类:
官方树结构工具说明
// 构建node列表
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
nodeList.add(new TreeNode<>("1", "0", "系统管理", 5));
nodeList.add(new TreeNode<>("11", "1", "用户管理", 222222));
nodeList.add(new TreeNode<>("111", "11", "用户添加", 0));
nodeList.add(new TreeNode<>("2", "0", "店铺管理", 1));
nodeList.add(new TreeNode<>("21", "2", "商品管理", 44));
nodeList.add(new TreeNode<>("221", "2", "商品管理2", 2));
List<Tree<String>> treeList = TreeUtil.build(nodeList, "0");
局限性:此工具类要求使用明确的几个字段比较方便,如若自定义有两种方式处理,都很简单:
List<Depart> list//为自己数据库内的结构表数据集合
- 工具提供的树形配置:
treeNodeConfig 配置set的括号内是自己的表字段
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定义属性名 都要默认值的
treeNodeConfig.setWeightKey("level");
treeNodeConfig.setIdKey("id");
treeNodeConfig.setNameKey("departName");
// 最大递归深度
treeNodeConfig.setDeep(5);
List<Tree<Integer>> treeList = TreeUtil.build(list,0);
- Java8提供的流库map方法转换:
List<TreeNode<Integer>> nodeList = list.stream().map(depart -> new TreeNode<Integer>(depart.getId(),depart.getParentId(),depart.getDepartName(),depart.getLevel())) .collect(Collectors.toList());
List<Tree<Integer>> treeList = TreeUtil.build(nodeList,0);
2.2 多字段字典匹配语句
一般在有字典的系统内,检索时,也会按照字典表内容进行处理操作。此处涉及到了多字段拼接在一个,再与输入的内容进行匹配。
表结构:
SQL语句:
用到:匹配:find_in_set、拼接:CONCAT、替换:replace
left join dict d on find_in_set(#{organizer,jdbcType=VARCHAR}, CONCAT(d.name,",",replace(d.other_name, ",", ",")))
==注:==
- 限制于用英文逗号分隔,出现其他的需要进行替换,这样只要知道使用的符号就可以了。
三、批量修改
3.1 同字段同值下的多条数据
场景:一个用户拥有多个角色,登录后需要以某一角色为主要显示。当然并不是所有的系统都需要,看情况。并且不局限于此场景,只要是在同字段同值情况下拥有多条数据,即可满足。
表结构:
SQL语句:
UPDATE
user_role ur, sys_user su
SET
ur.plan_id =
CASE
WHEN ur.rid = #{roleId} THEN 0
WHEN ur.rid != #{roleId THEN 1
ELSE ur.plan_id
END
WHERE
ur.user_id = su.user_id
AND su.user_name = #{userName}
==注:==
- 可以多表也可以单表,主要看where后边的条件需要。表内满足时没必要,实际情况感觉都是多表。
- 关键部分在CASE与END之间:WHEN后边为条件,用于区分同一字段获取不同值的条件;THEN后边为需要set的值,与when条件对应;ELSE在对应上字段即可。
- 写法较多,CASE也可直接接上对应字段,ELSE便不用再写。
效果:将rid=2的数据配置为0(默认主角色),其他为1(一般角色)
{roleId}=1
四、分组统计
4.1根据分组条件统计对应内容
这个知识点相对简单,用于记录,免得以后忘了,也可温习。
在重写springsecurity的访问url校验时使用的,因为粒度较细,到了按钮级别,因此针对每一个访问进行权限校验。
SQL语句:
SELECT
m.url, GROUP_CONCAT(distinct r.name) as roleName
FROM
menu m, menu_role mr, role r
WHERE
m.id = mr.mid AND mr.rid = r.id
GROUP
BY m.url
将每一个url的对应的角色进行统计在一个字段里,并去重。指定url更简单,就不说了。
五、总结
SQL语法的使用很多,我也是初出茅庐,用的就总结一下。