Oracle-创建一个临时结果集以供查询使用

时间:2012-08-29 01:46:12

标签: sql oracle

如何创建临时结果集以便在SQL中使用而无需创建表并插入数据?

示例:我有一个列表,例如10个代码。我想将它放入查询中,然后查询数据库以查看表中不存在此临时列表中的哪些代码。

如果它已经在表格中,我可以做类似的事情:

SELECT
  ITEM_CODE
FROM
  TEMP_ITEMS
MINUS
SELECT
   ITEM_CODE
FROM
   M_ITEMS

他们是不是使用PL / SQL和纯SQL在查询之前创建临时行集的方法? 请不要回答:

SELECT 1 FROM DUAL
UNION ALL
SELECT 2 FROM DUAL

我想到了一些我可以在IN语句中提供代码的东西,然后将其转换为行以便在以后的查询中使用。

编辑:所以每个人都知道我的目标,基本上我有时会得到一个产品代码列表,我需要找到列表中的哪些产品代码未在我们的系统中设置。我想快速将其抛入SQL语句,这样我就可以看到哪些不在系统中(而不是导入数据等)。我通常将这些放入excel,然后做一个公式,如:

="'"&A1&"',"

这样我就可以创建逗号分隔列表了。

5 个答案:

答案 0 :(得分:25)

如果您使用的是oracle 11g,则可以执行此操作

with t as 
(
 select (column_value).getnumberval() Codes from xmltable('1,2,3,4,5')
)
SELECT * FROM t
WHERE NOT EXISTS (SELECT 1 FROM M_ITEMS M WHERE codes = M.ITEM_CODE);

with t as 
(
 select (column_value).getstringval() Codes from xmltable('"A","B","C"')
)
SELECT * FROM t
WHERE NOT EXISTS (SELECT 1 FROM M_ITEMS M WHERE codes = M.ITEM_CODE);

答案 1 :(得分:4)

我会选择:

with t as (
    select 1 as val from dual union all
    select 2 as val from dual
)
select . . .

然后在随后的查询块中使用“t”或其他任何名称。

我不确定使用select方法的异议是什么。 。 。只需在Excel中的列中弹出所需的值,然后通过复制公式为每个值生成代码。然后将结果粘贴回查询界面。

如果要使用临时表,可以使用values子句。或者,如果您只想要IN功能,则可以使用字符串函数。将值放在以逗号分隔的列表中,并检查它是否与特定值匹配:

where ','||<list>||',' like '%,'||col||',%'

答案 2 :(得分:3)

我倾向于采用两种方法:

<强> 1。全球临时表

虽然您说您不想创建表格,但它取决于为什么您不想要表格。如果您选择创建全局临时表,则行只对插入它们的会话可见,因此它就像拥有一个私有的内存表,但为您提供了真实表的所有好处 - 即能够查询和加入它。

<强> 2。流水线功能

您可以创建一个函数,该函数以可以使用TABLE()运算符查询的形式返回结果。更多信息:http://www.oracle-base.com/articles/misc/pipelined-table-functions.php

答案 3 :(得分:3)

这个很有意思,因为它不是一个联合并且适合单个选择。你必须输入带分隔符的字符串('a / b / c / def')两次:

SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var,
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2
FROM dual
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1;

var var2
=== ====
a   2
b   432
c   sd
def fsd

注意:积分转到:https://stackoverflow.com/a/1381495/463056

因此,使用with子句会产生类似的结果:

with tempo as (
SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var,
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2
FROM dual
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1
)
select ...

或者您可以在from子句中使用它:

select ...
from (
SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var,
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2
FROM dual
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1
) tempo

答案 4 :(得分:2)

看起来有点好看。但是,假设您使用的是10g或更高版本,则可以使用正则表达式将字符串解析为单独的行。例如

SQL> ed
Wrote file afiedt.buf

  1   SELECT REGEXP_SUBSTR('a,b,c,def,g', '[^ |,]+', 1, LEVEL) parsed_str
  2     FROM dual
  3* CONNECT BY LEVEL <= REGEXP_COUNT('a,b,c,def,g', '[^ |,]+')
SQL> /

PARSED_STR
--------------------------------------------
a
b
c
def
g

就个人而言,我会找到一个流水线表函数或PL / SQL块来生成一个更容易理解的集合,但如果你必须在SQL中这样做,你可以。

根据您的编辑,如果您要获取已存在于某种文件中的产品代码列表,那么使用外部表将文件公开为表或使用SQL *似乎更有意义将数据加载到可以查询的表(临时或永久)中的加载器。除了这些选项之外,如果您真的想首先在Excel中操作列表,那么在Excel中生成IN列表并将其复制并传递到查询中会更有意义。在Excel中生成以逗号分隔的代码列表,只是为了将该列表解析为SQL中的组成元素,这似乎是太多的步骤。