是否有一个通用的解决方法来表达Oracle(和MySQL)中的派生列列表?

Luk*_*der 18 mysql sql oracle

许多SQL数据库支持SQL标准所称的内容<derived column list>.此类数据库至少包括CUBRID,Derby,Firebird,HSQLDB,Postgres,SQL Server和Sybase SQL Anywhere.SQL:2008规范中的(简化)摘录

7.6 <table reference>

Format
<table reference> ::=
    <table or query name> [ [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ] ]
  | <derived table> [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ]
Run Code Online (Sandbox Code Playgroud)

这意味着,我可以表达这些内容(例如在Postgres中,这是非常符合标准的)

-- Rename a <table or query name> to u(b)
with t(a) as (select 1)
select * from t as u(b)

-- Rename a <derived table> to u(b)
select * from (select 1) as u(b)
Run Code Online (Sandbox Code Playgroud)

现在,根据Oracle文档,我无法使用<derived column list>规范重命名列.我当然可以单独重命名表和列,如下所示:

-- Rename a <table or query name> to u(b)
with t(a) as (select 1 from dual)
select u.a b from t u;

-- Rename a <derived table> to u(b)
select u.a b from (select 1 a from dual) u;
Run Code Online (Sandbox Code Playgroud)

但是这需要更多关于派生表(实际列名)的知识,而不是以前的语法.此外,重命名的列仅在投影后(例如在ORDER BY子句中)可用,而不在任何其他子句中,包括投影本身.

在Oracle(以及MySQL)中,是否有更通用的方法以SQL标准建议的方式重命名表和列?特别是,这对于诸如数组取消,数据透视/非透视表重命名,内联复杂子查询,重命名表函数结果等内容非常有用.

注意:请不要过多关注上述例子.他们真的只是为了说明这个问题.现实世界的查询要复杂得多,所以我正在寻找一种非常通用的方法来实现重命名u(b)

注意:我仍在寻找适用于像MySQL这样的数据库的解决方案.一个相关的问题:
如何从子选择中选择一个非混淆的数字文字

Bil*_*win 10

对于MySQL解决方案,您可以使用a UNION来设置零行查询字词中所有列的名称,然后查询更复杂的内容:

SELECT null AS a, null AS b, null AS c FROM dual WHERE false
UNION ALL
SELECT <expr>, <expr>, <expr>
FROM <realtable>...
Run Code Online (Sandbox Code Playgroud)

只有UNION的第一个查询词定义了整个查询的列名.后续查询术语中的列名(或缺少列名)不会影响最终列名.

你需要知道的列,但它应该是很容易保持两个查询词分开.据我所知,它适用于Oracle和MySQL(但是,我只在MySQL中测试过,而不是在Oracle中测试过).


tbo*_*one 9

由于您必须知道列数,但不一定知道列名,因此可以使用WITH子句根据需要重命名这些列.例如(WITH在Oracle和SQL Server中工作,没有方便的MySQL实例):

WITH t(x,y,z) as (select * from TABLE(fn_returning_xcols(3)))
select * from t;
Run Code Online (Sandbox Code Playgroud)

这里我们不知道内部select中的列名,但是我们可以在外部WITH子句中重命名它们.

在Oracle中使用PIVOT的另一个例子:

WITH t(a,b,c,d,e) as 
(
 select * from 
 (
  select level as levl from dual connect by level <= 5
 )
 PIVOT(max(levl) as l for levl in (1,2,3,4,5))
)
select * from t;
Run Code Online (Sandbox Code Playgroud)

同样,我们不关心内部选择列名称是什么(内部枢轴创建有些奇怪的列名称),我们只需要知道有多少列,我们可以重命名.