将定义值列表构建到 CTE 中

问题描述 投票:0回答:4

有没有办法为硬编码值列表构建 CTE?例如,我有一个已知 ID 的列表(即 101,102,105,200...),我如何能够创建一个包含名为 ID 的列的 CTE,但所有 ID 值都硬编码在查询中?顺便说一句,我需要在 Oracle 中运行这个查询。谢谢!

sql oracle common-table-expression
4个回答
48
投票

编辑:之前建议的解决方案仅适用于 MSSQL。因此我添加了 Oracle 解决方案。我将原来的答案保留在下面。

我想到了另一种解决方案(尽管 Justin Cave 提供的方案看起来还是好一点)——使用临时表。

它可能是这样的

CREATE GLOBAL TEMPORARY TABLE temp_ids
   (id INT)
   ON COMMIT PRESERVE ROWS;

INSERT INTO ids (id) VALUES (101);
INSERT INTO ids (id) VALUES (102);
INSERT INTO ids (id) VALUES (103);

这应该是 Oracle 数据库的有效解决方案。

原答案如下


我遇到过类似的问题,这是我的解决方案(这不适用于注释中提到的 Oracle DB,但仅适用于 MSSQL)

WITH cte AS (
    SELECT * FROM (
        VALUES
            (1, 2, 3, ...),
            (2, 3, 4, ...)
        ) AS a (col1, col2, col3, ...)
    )
INSERT INTO ...

希望这有帮助:)


22
投票

你可以做类似的事情

WITH cte AS (
  SELECT 101 id FROM dual UNION ALL
  SELECT 102 FROM dual UNION ALL
  SELECT 105 FROM dual UNION ALL
  SELECT 200 FROM dual UNION ALL
  ...
)

但是,根据您真正想要完成的任务,您可能想要声明一个集合并使用它(带或不带解析逗号分隔字符串的函数)

CREATE TYPE num_tbl
    AS TABLE OF NUMBER;

WITH cte AS (
  SELECT column_value
    FROM TABLE( num_tbl( 101, 102, 105, 200 ))
)

1
投票

您可以为此使用集合类型,将它们作为绑定参数提交或在查询中创建它们。

正如Justin Cave所建议的,您可以创建自己的集合类型,但是

SYS
包含一些默认定义的基本类型,例如
SYS.ODCIDATELIST
(对于
DATE
),
SYS.ODCINUMBERLIST
(对于
NUMBER
) /
NUMERIC
)、
SYS.ODCIVARCHAR2LIST
VARCHAR2
最多 4000 个字符),其中一些似乎不是专门为内部使用而设计的。

由于您使用的是整数 ID,因此内置数字集合应该可以正常工作:

-- column_value and table() work similarily to UNNEST() in Postgres
SELECT column_value as selected_id FROM TABLE(
    SYS.ODCINUMBERLIST(101, 102, 105, 200)
)

根据您的主机语言支持的语言,您也可以将列表作为参数发送。例如,在 Python 中,直接使用 cx_Oracle:

import cx_Oracle

query = 'select column_value as selected_id FROM TABLE(:id_list)'

conn = cx_Oracle.connect('user', 'hunter2', '//192.0.2.5:1521/mydb')

OdciNumberList = conn.gettype("SYS.ODCINUMBERLIST")
id_list = OdciNumberList.newobject()

id_list.extend([101, 102, 105, 200])

cur = conn.cursor()
res = cur.execute(query, id_list=id_list )
res.fetchall() # [(101,), (102,), (105,), (200,)]

然后您只需将其包裹在 CTE 中即可。


0
投票

对贾斯汀·凯夫(Justin Cave)的流行答案略有改进:

WITH cte (num) AS 
(
  SELECT 101 UNION SELECT 102 UNION SELECT 105 UNION SELECT 200
)

select num from cte
© www.soinside.com 2019 - 2024. All rights reserved.