有没有办法为硬编码值列表构建 CTE?例如,我有一个已知 ID 的列表(即 101,102,105,200...),我如何能够创建一个包含名为 ID 的列的 CTE,但所有 ID 值都硬编码在查询中?顺便说一句,我需要在 Oracle 中运行这个查询。谢谢!
编辑:之前建议的解决方案仅适用于 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 ...
希望这有帮助:)
你可以做类似的事情
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 ))
)
您可以为此使用集合类型,将它们作为绑定参数提交或在查询中创建它们。
正如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 中即可。
对贾斯汀·凯夫(Justin Cave)的流行答案略有改进:
WITH cte (num) AS
(
SELECT 101 UNION SELECT 102 UNION SELECT 105 UNION SELECT 200
)
select num from cte