如何动态创建包含手动数据的表
Posted
技术标签:
【中文标题】如何动态创建包含手动数据的表【英文标题】:How to create a table with manual data on the fly 【发布时间】:2021-12-31 13:58:06 【问题描述】:假设我想动态定义一些表格数据以在查询中使用,而不创建物理表:
+------------+------------+
|COLUMN_VALUE|COLUMN_VALUE|
+------------+------------+
|1 |a |
|2 |b |
|5 |e |
|4 |d |
|3 |c |
+------------+------------+
(注意顺序)
我怎样才能尽可能简洁明了地做到这一点?
我能想出什么(不那么漂亮):
with
x as (
select
column_value
from
table (sys.odcinumberlist(1, 2, 5, 4, 3))),
y as (
select
column_value
from
table (sys.odcivarchar2list('a', 'b', 'e', 'd', 'c')))
select
x.column_value,
y.column_value
from
x
inner join y on x.rownum = y.rownum;
但这不起作用,因为它会出现ORA-01747: invalid user.table.column, table.column, or column specification
错误。显然使用内置的table()
函数时不支持rownum
伪列。
在 CTE 中使用 row_number() over (order by column_value asc)
似乎可行,但会强制对列值进行排序。这是不可取的,因为值应该按照它们在表函数中定义的顺序出现。
【问题讨论】:
select 1,'a' from dual union all ..
有什么问题?
使用内置 table() 运算符时确实支持 rownum 伪列。不支持对任何子查询x
引用x.rownum
。 x.columnname
只能引用 x
的显式命名列。 rownum
需要别名或双引号,因为它是关键字。
@Serg 不简洁的事实。
【参考方案1】:
Oracle Database Ideas 论坛上有一个社区向add an ordinality
pseudocolumn to scalar collections 提出建议,但我认为这在我们有生之年不太可能实现。还有一个语法建议,允许使用类似于Postgres Values lists 的values
子句动态声明集合,尽管我现在找不到它。
目前您的选择是:
将多个select from dual
查询与union all
一起使用以显式定义所有必需的行。
定义自定义对象和集合类型以使用table()
和对象声明语法。
我同意两者都不理想。
select from dual
方法的示例:
with test_data (id, somevalue) as
(
select 1, 'a' from dual union all
select 2, 'b' from dual union all
select 5, 'e' from dual union all
select 4, 'd' from dual union all
select 3, 'c' from dual
)
select id, somevalue
from test_data
关于生成的行号,可以使用
row_number() over(order by null)
从技术上讲,这并不能保证保留顺序,但从 Oracle 21c 开始,它似乎在实践中这样做了。
select column_value
, row_number() over (order by null) as rn
from table (sys.odcivarchar2list('a', 'b', 'e', 'd', 'c'));
COLUMN_VALUE RN
------------ ----------
a 1
b 2
e 3
d 4
c 5
关于 x.rownum
的 ORA-01747 错误,这不是因为 table()
运算符的任何限制。这样的结构有两个问题(您的查询的简化版本):
with demo as
( select dummy from dual )
select x.rownum from demo x
-
CTE
demo
没有名为“rownum”的列。它只有一列 (dummy
),因此这是您可以参考的唯一 x.column。
即使将rownum
添加到查询中,也不能将其称为x.rownum
之类的列,因为它是关键字。解决方案是在 CTE 中将其别名为“seq”或“rn”,然后可以参考:
with demo as
( select dummy, rownum as rn from dual )
select x.rn from demo x
【讨论】:
我不知道你可以按null订购,知道有用!您的回答提供了丰富的信息,但它略微忽略了一点,因为它没有显示如何创建多个数据列/元组。为此,我的解决方案(见下文)在行号上使用了内部联接。如果您可以包含此内容(或其他方式),我会将您的帖子标记为解决方案。 那是关于使用“联合所有”或定义自定义对象的多个“从双重选择”查询的一点。在其行号上加入多个标量集合会起作用,但我认为它变得太复杂而无法成为通用解决方案。 添加了select from dual
方法的示例。【参考方案2】:
解决方案是为 rownum 列设置别名(也整理了查询):
select
x.column_value,
y.column_value
from
(select column_value, rownum as rn from table (sys.odcinumberlist(1, 2, 5, 4, 3))) x
inner join
(select column_value, rownum as rn from table (sys.odcivarchar2list('a', 'b', 'e', 'd', 'c'))) y on x.rn = y.rn;
【讨论】:
以上是关于如何动态创建包含手动数据的表的主要内容,如果未能解决你的问题,请参考以下文章