实际上, Oracle可以利用with子句为子查询的数据集作为1个内存临时表. 在内存中解析,提高了执行效率. 而且提高了SQL语句的可读性.
语法很简单:
下面是1个简单的例子:
with
A as (select id, name from student)
select * from A ;
ID NAME
---------- --------------
1 张三
2 李四
3 王五
4 赵六
5 田七
可以见到, 上面的A为括号的子查询的别名, 相当于在内存里建立了1张临时表. 下面的select 语句就直接检索这张临时表.
例如下面的例子
with
Q1 as (select id, name from student)
delete from student where 1 =2 ;
select * from student where 1 =2;
在行 2 上开始执行命令时出错:
错误报告:
SQL 错误: ORA-00928: 缺失 SELECT 关键字
00928. 00000 - "missing SELECT keyword"
如下面的经典例子:
WITH
Q1 AS (SELECT 3 + 5 S FROM DUAL),
Q2 AS (SELECT 3 * 5 M FROM DUAL),
Q3 AS (SELECT S, M, S + M, S * M FROM Q1, Q2)
SELECT * FROM Q3;
S M S+M S*M
---------- ---------- ---------- ----------
8 15 23 120
可以简单上面定义了3个那次临时表Q1, Q2, Q3, 其中Q3 使用了临时表Q1 和 Q2
如上面的例子增加一句select * from Q2.
WITH
Q1 AS (SELECT 3 + 5 S FROM DUAL),
Q2 AS (SELECT 3 * 5 M FROM DUAL),
Q3 AS (SELECT S, M, S + M, S * M FROM Q1, Q2)
SELECT * FROM Q3;
select * from Q2;
ORA-00942: 表或视图不存在
00942. 00000 - "table or view does not exist"
*Cause:
*Action:
行 42 列 15 出错
出错了, 因为Q2 已经被with里的Q3检索过一次, 被删掉了. 实际上再select 一次 Q3也是会出错的.
可能内存空间珍贵的原因, oracle为with语句设定这个机制
例子
with
student as (select id, name from student)
select * from student;
在行 21 上开始执行命令时出错:
with
products as (select product_id, product_name from products where rownum <= 10)
select * from products
命令出错, 行: 22 列: 54
错误报告:
SQL 错误: ORA-32039: 递归 WITH 子句必须具有列别名列表