sql - одиночный запрос для возврата значений, которых нет - PullRequest
2 голосов
/ 04 ноября 2011

Например, у вас есть простая таблица с одним столбцом. то есть.

CREATE TABLE movies   (title VARCHAR2(255 BYTE))

настроено со следующими данными:

INSERT INTO movies   (title) VALUES ('Scream');
INSERT INTO movies   (title) VALUES ('Blair Witch');
INSERT INTO movies   (title) VALUES ('Friday the 13th');
INSERT INTO movies   (title) VALUES ('Scary Movie');
INSERT INTO movies   (title) VALUES ('Hide and Seek');
INSERT INTO movies   (title) VALUES ('Alien vs Predator');

Существует ли один запрос или PL / SQL, который будет динамически выполнять следующие действия (т. Е. Не нужно вручную делать "UNION select 'scream' from dual ..." для каждого значения)?

Очевидно, что этот запрос неправильный, но вы поняли:

Select * from movies
where title in (
'Scream',
'Scary Movie',
'Exorcist',
'Dracula',
'Saw',
'Hide and Seek'
)

Желаемый результат - запись для каждого значения в предложении «WHERE TITLE IN», где запись отсутствует в таблице. то есть.

'Exorcist'
'Dracula'
'Saw'

Ответы [ 3 ]

3 голосов
/ 04 ноября 2011

Если вы используете 10g или выше, вы можете создать функцию, которая преобразует строку CSV в динамическую таблицу. Проверьте код для строкового токенизатора в этот другой ответ .

Вы бы использовали это так:

select * from movies
where title NOT in (
         select * 
          from table (string_tokenizer
                      (
                          'Scream, Scary Movie,Exorcist,Dracula,Saw,Hide and Seek'
                        )

                  )
     )
/

Вот немного более простая реализация, которая не требует дополнительной инфраструктуры:

SQL> select * from table(sys.dbms_debug_vc2coll('Scream',
'Scary Movie',
'Exorcist',
'Dracula',
'Saw',
'Hide and Seek'
 ))
/
  2    3    4    5    6    7    8  
COLUMN_VALUE
--------------------------------------------------------------------------------
Scream
Scary Movie
Exorcist
Dracula
Saw
Hide and Seek

6 rows selected.

SQL> 

Это похоже на конструктор табличных значений , но он работает только для "столбцов" таблиц с одним столбцом.

2 голосов
/ 04 ноября 2011

То, что вы хотите, это «Конструкторы табличных значений» . Я не думаю, что Oracle поддерживает это.

См. Статью Джо Селко о: Конструкторах табличных значений в SQL Server 2008 и взятом оттуда примере:

SELECT *
FROM
  ( VALUES
      (101, 'Bikes'),
      (102, 'Accessories'),
      (103, 'Clothes')
  ) AS Category(CategoryID, CategoryName);
1 голос
/ 04 ноября 2011

Вы можете использовать тип таблицы и функцию table () для приведения списка к таблице.

CREATE OR REPLACE TYPE varchar_list_type as table of varchar2(100);

CREATE OR REPLACE function in_varchar_list ( p_string in varchar2 ) return varchar_list_type
as
    l_data             varchar_list_type := varchar_list_type();
    l_string           long default p_string || ',';
    l_n                number;
begin

    loop
        exit when l_string is null;

        l_data.extend;
        l_n := instr( l_string, ',' );
        l_data( l_data.count ) := substr( l_string, 1, l_n-1 );
        l_string := substr( l_string, l_n+1 );

    end loop;
    return l_data;
end;

Тогда используйте вот так:

select * from TABLE(select cast(in_varchar_list('foo,bar,baz') as varchar_list_type) from dual)

Конечно, вы можете использовать переменную связывания или обычную переменную вместо жестко закодированной строки 'foo, bar, baz'.

edit: опечатка в запросе ^ _ ^ "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...