2012-04-03 10 views
7

Tome esta tabla PALABRASOracle SQL - encontrar los valores de NO en una tabla

WORD 
Hello 
Aardvark 
Potato 
Dog 
Cat 

y esta lista:

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

¿Cómo puedo devolver una lista de palabras que no están en el tabla de palabras, pero están en mi lista?

Si tengo una tabla que "contiene todas las palabras posibles", que puedo hacer:

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') 
); 

Sin embargo no tengo una tabla de este tipo. ¿De qué otra manera se puede hacer esto?

Además, construir una nueva tabla no es una opción porque no tengo ese nivel de acceso.

Respuesta

25

En lugar de codificar duro la lista de valores en filas, utilice DBMS_DEBUG_VC2COLL para convertir dinámicamente su lista delimitada en filas, a continuación, utilizar el operador MINUS para eliminar filas de la segunda consulta que son no en la primera consulta:

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

Técnica de Niza) Pero, ¿qué sucede si se deniega el acceso a las funciones de sys. *? – denied

+0

@denied Bueno, eso sería incómodo de hecho. Puede haber otras maneras de convertir una lista delimitada de cadenas en una columna que sea más elegante que sys.dbms_debug_vc2coll. Tal vez hay una solución usando SQL puro? – Wolf

+0

@Denied En este contexto, 'sys' no es algo malo. En teoría, alguien podría negarle el acceso a ese tipo, pero probablemente no sea algo de lo que deba preocuparse. Es tan probable como que alguien elimine el acceso a 'sys.dbms_output'. –

5

Usted puede convertir su lista en una vista como esta:

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

continuación, puede seleccionar a partir de que:

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); 

Posiblemente no es una solución tan limpio como se podría haber esperado ..

Dice que no tiene los privilegios suficientes para crear tablas, por lo que presumiblemente tampoco puede crear tipos, pero si puede encontrar un tipo adecuado "deambulando" en su base de datos, puede hacerlo esto:

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

Aquí table_of_varchar2_type se imaginó ser el nombre de un tipo que se define como:

create type table_of_varchar2_type as table of varchar2(100); 

Uno de estos tipos es probable que sea capaz de encontrar es SYS.KU$_VCNT que es una tabla de VARCHAR2 (4000).

4

Pruebe esta solución:

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 
Cuestiones relacionadas