sql - 单个查询以返回不存在的值

时间:2011-11-04 10:24:15

标签: sql database oracle plsql

例如,您有一个只有一列的简单表。 即

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”尖叫')?

显然这个查询错了,但你明白了:

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

所需结果是“WHERE TITLE IN”子句中每个值的记录,其中记录不存在于表中。 即

'Exorcist'
'Dracula'
'Saw'

3 个答案:

答案 0 :(得分:3)

如果您使用的是10g或更高版本,则可以构建一个将CSV字符串转换为动态表格的函数。在this other response中查看字符串标记生成器的代码。

您可以这样使用它:

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> 

这类似于the Table Value Constructor,但它仅适用于单列“表格”。

答案 1 :(得分:2)

您想要的是 “表值构建器” 功能。我认为Oracle不支持这一点。

请参阅Joe Celko的文章: Table Value Constructors in SQL Server 2008 以及从中获取的示例:

SELECT *
FROM
  ( VALUES
      (101, 'Bikes'),
      (102, 'Accessories'),
      (103, 'Clothes')
  ) AS Category(CategoryID, CategoryName);

答案 2 :(得分:1)

您可以使用表类型和函数表()将列表强制转换为表。

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'。

编辑:查询中的拼写错误^ _ ^“