有没有办法为硬编码的值列表构建CTE?例如,我有一个已知ID列表(即101、102、105、200...),如何能够创建一个名为ID的列的CTE,但所有ID值都是在查询中硬编码的?顺便说一下,我需要在Oracle中运行此查询。谢谢!
有没有办法为硬编码的值列表构建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数据库的有效解决方案。
以下是原始答案
我遇到过类似的问题,这是我的解决方案(如评论中所述,这仅适用于MSSQL,而不适用于Oracle DB)
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 ))
)
-- 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,)]
WHERE ... IN
列表也很方便,如最近 cx_Oracle 文档中所示。值得注意的是,gettype()
相对较“昂贵”,需要几次往返,因此在同一连接中需要多次执行此操作时,请保留OdciNumberList
,不要重复调用 'gettype()'. - Christopher Jones