2012-04-03 60 views
7

拿這個表字的Oracle SQL - 找到一個表中沒有的值

WORD 
Hello 
Aardvark 
Potato 
Dog 
Cat 

而且這個名單:

('Hello', 'Goodbye', 'Greetings', 'Dog') 

如何返回的不是單詞的列表單詞表,但在我的名單?

如果我有一個表,「包含所有可能的話」,我可以這樣做:

SELECT * from ALL_WORDS_TABLE 
where word in ('Hello', 'Goodbye', 'Greetings', 'Dog') 
and word not in 
(SELECT word from WORDS 
where word in ('Hello', 'Goodbye', 'Greetings', 'Dog') 
); 

但是我沒有這樣的表。這還能做什麼?

此外,構建新表不是一種選擇,因爲我沒有該級別的訪問權限。

回答

25

而不是硬編碼列表值代入行,請使用DBMS_DEBUG_VC2COLL您分隔列表動態地轉換成排,然後用MINUS運營商消除是第二個查詢行不在第一個查詢中:

select column_value 
from table(sys.dbms_debug_vc2coll('Hello', 'Goodbye', 'Greetings', 'Dog')) 
minus 
select word 
from words; 
+0

不錯的技術)但是如果訪問sys。*函數會被拒絕呢? – denied 2012-04-03 16:16:36

+0

@denied那真是太尷尬了。可能還有其他方法可以將分隔字符串列表轉換爲比sys.dbms_debug_vc2coll更優雅的列。也許有一個使用純SQL的解決方案? – Wolf 2012-04-03 16:33:43

+0

@Denied在這種情況下,'sys'不是一件壞事。理論上有人可能會拒絕您訪問該類型,但可能不是您需要擔心的事情。這與刪除對「sys.dbms_output」的訪問權限的可能性大致相同。 – 2012-04-03 23:20:31

5

你可以把你的名單分成這樣的觀點:

select 'Hello' as word from dual 
union all 
select 'Goodbye' from dual 
union all 
select 'Greetings' from dual 
union all 
select 'Dog' from dual 

然後你可以從選擇:

select * from 
(
    select 'Hello' as word from dual 
    union all 
    select 'Goodbye' from dual 
    union all 
    select 'Greetings' from dual 
    union all 
    select 'Dog' from dual 
) 
where word not in (select word from words); 

可能還不如利落的解決方案,你可能希望..

你說你沒有足夠的權限來創建表,所以大概你不能創建類型 - 但是如果你可以在數據庫中找到一個合適的類型「躺在」你可以做這樣的:

select * from table (table_of_varchar2_type('Hello','Goodbye','Greetings','Dog')) 
where column_value not in (select word from words); 

這裏table_of_varchar2_type是想象中的要被像定義的一個類型的名稱:

create type table_of_varchar2_type as table of varchar2(100); 

一個這樣的類型,你可能能夠找到爲SYS.KU$_VCNT這是一個表VARCHAR2(4000)。

4

嘗試這種解決方案:

SELECT 
a.word 
FROM 
(
SELECT 'Hello' word FROM DUAL UNION 
SELECT 'Goodbye' word FROM DUAL UNION 
SELECT 'Greetings' word FROM DUAL UNION 
SELECT 'Dog' word FROM DUAL 
) a 
LEFT JOIN ALL_WORDS_TABLE t ON t.word = a.word 
WHERE 
t.word IS NULL 
相關問題