20

如何在不创建表和插入数据的情况下创建用于 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&"',"

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

4

5 回答 5

33

如果您使用的是 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);
于 2012-08-29T01:58:15.880 回答
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||',%'
于 2012-08-29T01:48:38.603 回答
4

这个很有趣,因为它不是一个联合并且适合单个选择。您必须输入带有分隔符的字符串 ('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
于 2013-05-01T14:07:46.713 回答
3

我倾向于两种方法:

1. 全局临时表

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

2.流水线功能

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

于 2012-08-29T01:59:23.683 回答
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*Loader 加载似乎更有意义将数据放入您可以查询的表(临时或永久)中。IN除了这些选项中的任何一个,如果您真的想首先在 Excel 中操作列表,那么在 Excel 中生成一个列表并将其复制并粘贴到您的查询中会更有意义。在 Excel 中生成以逗号分隔的代码列表只是为了将该列表解析为 SQL 中的组成元素,这似乎步骤太多。

于 2012-08-29T02:23:39.083 回答