如何即时创建带有手动数据的 table
How to create a table with manual data on the fly
假设我想动态定义一些表格数据以在查询中使用,而不创建物理 [=29=]:
+------------+------------+
|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)
似乎可行,但会强制对列值进行排序。这是不可取的,因为值应该按照它们在 table 函数中定义的顺序出现。
解决方案是为 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;
Oracle 数据库创意论坛上有一个社区建议 add an ordinality
pseudocolumn to scalar collections, but I'd say it's unlikely to be implemented in our lifetimes. There is also a suggestion for syntax to allow sets to be declared on the fly using a values
clause similar to Postgres Values lists,但我现在找不到。
目前您的选择是:
使用多个 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
假设我想动态定义一些表格数据以在查询中使用,而不创建物理 [=29=]:
+------------+------------+
|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)
似乎可行,但会强制对列值进行排序。这是不可取的,因为值应该按照它们在 table 函数中定义的顺序出现。
解决方案是为 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;
Oracle 数据库创意论坛上有一个社区建议 add an ordinality
pseudocolumn to scalar collections, but I'd say it's unlikely to be implemented in our lifetimes. There is also a suggestion for syntax to allow sets to be declared on the fly using a values
clause similar to Postgres Values lists,但我现在找不到。
目前您的选择是:
使用多个
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