2012-08-29 66 views
12

如何在不創建表並插入數據的情況下創建在SQL中使用的臨時結果集?Oracle-創建用於查詢的臨時結果集

例如:我有一個例如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 

我有點想的東西,我可以提供在陳述我的代碼,它原來是成排在後面的查詢中使用。

編輯:所以大家都知道我的目標在這裏,基本上我有時會得到一個產品代碼列表,我需要找到列表中的哪些代碼沒有在我們的系統中設置。我想要一個快速的方法把它放到SQL語句中,以便我可以看到哪些不在系統中(而不是導入數據等)。我通常把這些變成excel,然後做一個公式如:

="'"&A1&"'," 

這樣我就可以創建我的逗號分隔列表。

+0

你是什麼意思時,你說你有你 一個列表?我假設你不是指PL/SQL集合。你是否說明你有一個像逗號分隔的字符串來表示一個列表?你想在SQL中解析該字符串以獲得單獨的代碼單獨的行嗎? –

+0

是的,這是正確的。像(「A」,「B」,「C」) – Lock

回答

22

如果您使用的是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); 
+0

這看起來很有前途。我會試一試。 – Lock

+0

Thankyou,這將爲我想要的工作! – Lock

3

我會去的:

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||',%' 
+0

感謝您的答覆,但我的問題狀態的東西,我不想thsese答案。當您處理大約100條記錄時,以這種方式進行並不是真的可行。我希望有更好的辦法比這樣做 – Lock

3

我會傾向於兩種方法:

1. Global Temporary Table

雖然你說你不想創建表,但它取決於爲什麼你不想要一個表。如果你選擇創建一個全局臨時表,這些行只對插入它們的會話可見,所以它就像擁有一個私有的內存表一樣,但是可以給你一個真正的表的所有好處 - 即能夠查詢和連接到它。

2。流水線功能

您可以創建一個函數,以一種可以使用TABLE()運算符查詢的形式返回結果。這裏更多的信息:http://www.oracle-base.com/articles/misc/pipelined-table-functions.php

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中的組成元素,這似乎是太多步驟。因爲它不是在一個單一的選擇工會,配合

+0

不錯,但只有11g:http://docs.oracle.com/cd/B28359_01/server.111/b28286/functions135.htm –

2

這一個是有趣。你必須用分隔符輸入字符串(「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 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 ... 

,或者您可以在使用它的子句:

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 
相關問題