前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >87-with as写法的5种用途

87-with as写法的5种用途

作者头像
老虎刘
发布2022-06-22 18:29:28
6810
发布2022-06-22 18:29:28
举报
文章被收录于专栏:老虎刘谈oracle性能优化

with as的写法, 有一个专有名词, 叫common table expression, 简称CTE,很多开发人员把使用这种写法当成一个提高SQL执行效率的方法, 事实究竟如何, 请往下看.

oracle优化培训之<SQL写法与改写>第二期 的课程中, 我给学员讲了with as的几个用途,下面逐一介绍:

1. 通过materilize生成临时表, 达到优化SQL目的.

比如一个大表(或一段查询块), 在SQL中被多次使用, 每次访问表, 都有一些共同的过滤条件, 过滤之后, 结果集变小, 这种情况就比较适合使用with as的写法. 注意, 不要以为使用了with as, 就能提高性能, 使用不当反而会降低性能. 只在特定情况下才能提升效率.

我的另一篇公众号文章 记一个Enq: ss - contention性能问题处理 , 就是这样一个案例, 不过这个案例的最佳解决方案是进一步改写, 表只需要被访问一次.

相关知识点:

如果with as 查询块被使用2次或两次以上, 会自动做materialize, 如果不想被物化, 可以使用/*+ inline */的hint ;

如果查询块只被调用一次, 默认不会做materialize, 可以用/*+ materialize*/的hint来使其物化生成临时表.

注意:如果返回列中含有lob字段, 不能被materialize.

在12.2及以上版本中, materialize 有个新特性, 叫CURSOR DURATION MEMORY, 可以把结果集保存在内存中, 而不是写到temp表空间, 可以提升效率.

2.提高代码可读性

使代码有层次感, 增强可读性, 下面是对连续编号进行分组的一个写法:

with t as

( select rownum+1 as id from xmltable('1 to 5')

union

select rownum+10 from xmltable('1 to 4')

union

select rownum+20 from xmltable('1 to 2')

union

select rownum+30 from xmltable('1 to 3')

)

,mid1 as (select id,nvl(id-1-lag(id) over (order by id),0) as cal_id from t)

,mid2 as (select id,sum(cal_id) over (order by id) as sum1 from mid1)

select id,dense_rank() over (order by sum1) as group_no

from mid2

order by id;

对复杂的SQL, 都可以考虑使用这种写法, 增强代码的可读性.

3.实现递归算法

下面是计算9以内阶乘的写法

WITH temp (n, fact) AS

(SELECT 0, 1 from dual

UNION ALL

SELECT n+1, (n+1)*fact FROM temp

WHERE n < 9

)

SELECT * FROM temp;

connect by层级查询语法,很多都可以使用with as的递归写法替代实现.

4. 12c新特性 inline function, SQL里面可以内嵌函数

如下面示例(这个with , 没有as):

WITH

function cal_new_sal(p_sal number, p_hiredate date)

return number

is

begin

return p_sal*(1+ceil((sysdate-p_hiredate)/365)*0.05);

end;

select empno,ename,sal,hiredate

,cal_new_sal(sal,hiredate) as new_sal

,1+ceil((sysdate-hiredate)/365)*0.05 as factor

from emp;

/

function代码没有保存在数据库中.

5.构造测试用例用临时数据

前面提高代码可读性的示例已经用到了, 下面示例是在19c之前, 使用listagg并去重的一种写法, with as的作用是生成了几行测试记录, 避免了建表和插入记录的麻烦:

with test_data(col1,col2,created_by) as

(

select 1, 2, 'Smith' from dual

union all select 1, 2, 'John' from dual

union all select 1, 3, 'Ajay' from dual

union all select 1, 4, 'Ram' from dual

union all select 1, 5, 'Jack' from dual

union all select 2, 5, 'Smith' from dual

union all select 2, 6, 'John' from dual

union all select 2, 6, 'Ajay' from dual

union all select 2, 6, 'Ram' from dual

union all select 2, 7, 'Jack' from dual

)

SELECT col1 ,

listagg(col2 , ',') within group (order by col2 ASC) AS orig_value,

listagg(CASE WHEN rn=1 THEN col2 END , ',') within group (order by col2 ASC) AS distinct_value

from

(

select a.*,row_number() over (partition by col1,col2 order by 1) as rn from test_data a

) a

GROUP BY col1;

总结:

用的最多的功能应该是提高代码可读性; 利用 materialize 特性优化SQL, 也是开发人员需要考虑的.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老虎刘谈oracle性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档