将定义值列表构建到 CTE 中
Posted
技术标签:
【中文标题】将定义值列表构建到 CTE 中【英文标题】:Build a list of defined values into CTE 【发布时间】:2014-05-16 00:49:16 【问题描述】:有没有办法为硬编码值列表构建 CTE?例如,我有一个已知 ID 的列表(即 101,102,105,200...),我如何能够创建一个 CTE,其中有一列名为 ID 但所有 ID 值都在查询中硬编码?顺便说一句,我需要在 Oracle 中运行这个查询。谢谢!
【问题讨论】:
【参考方案1】:编辑:以前建议的解决方案仅适用于 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 数据库的有效解决方案。
原答案如下
我遇到了类似的问题,这是我的解决方案(这在 cmets 中提到的 Oracle DB 上不起作用,但只有 MSSQL)
WITH cte AS (
SELECT * FROM (
VALUES
(1, 2, 3, ...),
(2, 3, 4, ...)
) AS a (col1, col2, col3, ...)
)
INSERT INTO ...
希望这会有所帮助:)
【讨论】:
此语法在 Oracle 中无效。 因此,我很抱歉造成混乱,并感谢您提供的信息。希望这会帮助其他人在 MSSQL 中寻找相同的东西。 好的,我编辑了之前的答案,并添加了我认为对 Oracle 也应该是有效的解决方案。 注意:VALUES 仅适用于 SQL Server 2008 (v10) 及更高版本。 “希望这将帮助其他人在 MSSQL 中寻找相同的东西”是的,我!【参考方案2】:你可以做类似的事情
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 ))
)
【讨论】:
只是补充一点,最近的版本允许单独定义子查询分解子句的列别名,可能会使查询子句更整洁: WITH cte (id) as (SELECT 101 from dual ... @ 987654321@【参考方案3】:您可以为此使用集合类型,将它们作为绑定参数提交或在查询中创建它们。
正如 Justin Cave 所建议的,您可以创建自己的集合类型,但SYS
包含一些默认定义的基本类型,例如SYS.ODCIDATELIST
(用于DATE
)、SYS.ODCINUMBERLIST
(用于@ 987654325@/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 中。
【讨论】:
此解决方案也适用于非常大的WHERE ... IN
列表,如最近的 cx_Oracle 文档所示。值得注意的是,gettype()
相对“昂贵”并且需要多次往返,因此请保留OdciNumberList
,如果您需要在同一连接中多次执行此操作,请不要重复调用“gettype()”。 以上是关于将定义值列表构建到 CTE 中的主要内容,如果未能解决你的问题,请参考以下文章
如何将一个自定义列表的选定数据显示到同一活动的另一个自定义列表视图
如何将列表中的值分配给熊猫数据框并控制每个列表元素在数据框中的分布/频率