Postgre 树状表结构增删改查 递归查询 WITH RECURSIVE
作者:互联网
一、简介
当存在层级关系时,通常在设计表结构的时候添加字段parent_id,表示父节点。
树状表的查询不同于常规表,多数情况下查询父节点的数据也要递归查询其子节点,删除父节点也要递归删除子节点。
由于SQL语句的限制,没法直接写递归语句,除非是用函数或存储过程。
POSTGRE数据库引擎提供了WITH RECURSIVE解决上面的问题。
具体请参考官方资料:https://www.postgresql.org/docs/current/queries-with.html
比如下面的树状结构:
二、WITH
WITH提供了一种编写辅助语句的方法,以便在较大的查询中使用。
这些语句通常被称为公共表表达式(commontableexpression)或cte,
可以被认为是定义仅为一个查询而存在的临时表。
WITH子句中的每个辅助语句都可以是SELECT、INSERT、UPDATE或DELETE;
WITH子句本身附加到主语句,主语句也可以是SELECT、INSERT、UPDATE或DELETE。
比如下面的SQL语句:
with T as ( select * from template_info where parent_id=-1 ) select * from T
查询出所有一级节点,括号中的语句查出的内容保存在了临时表T中,然后在从T中查询所有。
可以定义多个WITH子句,用逗号分隔开,这样就可以查询多个表,并行查询,然后对临时表集合进行查询统计。
三、RECURSIVE
可选的RECURSIVE递归修饰符从一个简单的语法改变为一个特性,它可以完成标准SQL中不可能完成的事情。
使用递归,WITH查询可以引用自己的输出。
with RECURSIVE t as (select * from template_info where id =18 union all (select d.* from t inner join template_info d on t.id=d.parent_id) ) select * from t
查询的逻辑是:
1、计算非递归项,也就是 select * from template_info where id =18,这一行查出的是根节点,将结果存在临时表B中;
2、计算递归项,也就是 select d.* from t inner join template_info d on t.id=d.parent_id,将临时表B与 template_info进行连接查询得到C,将BC合并得到D;
3、一直计算递归项,并合并结果集,直到所有C为空,结束迭代过程;
4、查询结果集得到最终结果。
注:严格地说,这个过程是迭代而不是递归,但是递归是SQL标准委员会选择的术语。
步骤进一步拆解:
1、查询一个
select * from template_info where id =18
2、合并
with RECURSIVE t as (select * from template_info where id =18 union (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=18) ) select * from t
3、再合并
with RECURSIVE t as (select * from template_info where id =18 union (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=18) ) select * from t union ( with RECURSIVE t2 as ( (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=19) ) select * from t2 )
4、再合并,没有了,结束查询。
with RECURSIVE t as (select * from template_info where id =18 union (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=18) ) select * from t union ( with RECURSIVE t2 as ( (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=20) ) select * from t2 )
四、WITH
中UPDATE
WITH t AS ( UPDATE products SET price = price * 1.05 RETURNING * ) SELECT * FROM t;
五、WITH中DELETE和INSERT
这个查询实际上从products
把行移动到products_log
。WITH
中的DELETE
删除来自products
的指定行,
以它的RETURNING
子句返回它们的内容,并且接着主查询读该输出并将它插入到products_log
。
WITH moved_rows AS ( DELETE FROM products WHERE "date" >= '2010-10-01' AND "date" < '2010-11-01' RETURNING * ) INSERT INTO products_log SELECT * FROM moved_rows;
标签:info,RECURSIVE,改查,Postgre,查询,template,where,id,select 来源: https://www.cnblogs.com/dog2016/p/14187099.html