Oracle Database 23c新特性之无表查询

Oracle 23c 开始支持无表查询,也就是没有 FROM 子句的 SELECT 语句。

无表查询语句

在之前的版本中,我们需要使用 DUAL 表快速查询表达式或者函数的值。Oracle 23c 开始可以省略 FROM 子句和 DUAL 表,以下两种查询语句作用相同:

select sysdate;

SYSDATE
---------
2023-05-28


select sysdate from dual;

SYSDATE
---------
2023-05-28

PL/SQL 支持

Oracle 23c 开始,PL/SQL 程序中也可以省略 FROM 子句,例如:

set serveroutput on

declare
  v_date date;
begin
  select sysdate
  into v_date;

  dbms_output.put_line(v_date);
end;
/

2023-05-28

PL/SQL procedure successfully completed.

一般来说,我们可以通过直接赋值的方式给变量赋值。示例中为了演示无表查询使用了 SELECT … INTO 语句。

隐式查询结果

在其他数据库中,我们经常可以看到直接将存储过程中的数据作为结果输出,不过 Oracle 不支持这种方式:

create or replace procedure get_date as
begin
  select sysdate;
end;
/

Warning: Procedure created with compilation errors.

SQL>show errors
Errors for PROCEDURE GET_DATE:

LINE/COL ERROR
-------- -----------------------------------------------------------------
3/3      PLS-00428: an INTO clause is expected in this SELECT statement
SQL>

我们可以利用 Oracle 12c 中引入的隐式查询结果实现这一功能,例如:

create or replace procedure get_date as
  l_cursor sys_refcursor;
begin
  open l_cursor for
    select sysdate;
  dbms_sql.return_result(l_cursor);
end;
/


exec get_date;

PL/SQL procedure successfully completed.

ResultSet #1

SYSDATE
---------
2023-05-28

这种方式可以模拟其他数据库中的行为,但是实现要麻烦一些。

实现原理

接下来我们看看新的无表查询语法是如何实现的,本质上它是一个查询转换。

首先,我们刷新一下共享池,并且找出会话的跟踪文件。

conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba
alter system flush shared_pool;


conn testuser1/testuser1@//localhost:1521/freepdb1

set linesize 100
column value format a65

select value
from   v$diag_info
where  name = 'Default Trace File';

VALUE
-----------------------------------------------------------------
/opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_17498.trc

然后使用 10053 事件跟踪查看语句的执行情况:

alter session set events '10053 trace name context forever';

select sysdate; 

alter session set events '10053 trace name context off';

检查跟踪文件,搜索“Final query after transformations”部分的内容,可以看到以下信息:

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT SYSDATE@! "SYSDATE" FROM "SYS"."DUAL" "DUAL"

查询语句被转换之后包含了 FROM DUAL,因此这就是一个语法糖。无表查询可以更加方便用户使用,而且移植性更好。

猜你喜欢

转载自blog.csdn.net/horses/article/details/130815639