比较表的值列表

时间:2013-02-14 10:08:36

标签: sql database oracle oracle10g

我试图找到这个问题的解决方案已经有一段时间但没有成功,所以任何帮助都会非常感激。需要将ID列表与表进行比较,并找出存在哪些记录(及其中一个值)以及哪些记录不存在。
有一个ID列表,采用文本格式:

100,
200,
300 

数据库表:

ID(PK)   value01 value02 value03 .....
--------------------------------------
100       Ann
102       Bob
300       John
304       Marry
400       Jane

我需要的输出是:

100 Ann
200 missing or empty or whatever indication
300 John

明显的解决方案是创建表和连接,但我只有读访问权限(数据库是封闭的供应商产品,我只是一个用户)。编写PL / SQL函数似乎也很复杂,因为表有200多列和100k +记录,我没有运气创建动态数组记录。此外,要检查的ID列表包含数百个ID,我需要定期执行此操作,因此任何必须在单独的代码行中更改每个ID的解决方案都不会非常有用。 数据库是Oracle 10g。

3 个答案:

答案 0 :(得分:1)

有许多内置的公共集合类型。你可以像这样利用其中一个:

with ids as (select /*+ cardinality(a, 1) */ column_value id
               from table(UTL_NLA_ARRAY_INT(100, 200, 300)) a
            )
select ids.id, case when m.id is null then '**NO MATCH**' else m.value end value
  from ids
         left outer join my_table m
                     on m.id = ids.id;

要查看数据库中的公共类型列表,请运行:

select owner, type_name, coll_type, elem_type_name, upper_bound, precision, scale from all_coll_types
 where elem_type_name in ('FLOAT', 'INTEGER', 'NUMBER', 'DOUBLE PRECISION')

提示

/*+ cardinality(a, 1) */

只是用于告诉oracle我们的数组中有多少个元素(如果没有指定,默认将是8k元素的假设)。只需设置一个相当准确的数字。

答案 1 :(得分:0)

您可以使用CONNECT BY将变量转换为查询(在11g上测试,应该在10g +上工作):

SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
  2  SELECT regexp_substr(txt, '[^,]+', 1, LEVEL) item FROM DATA
  3  CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1;

ITEM
--------------------------------------------
100
200
300

然后,您可以将此结果加入表格,就像它是标准视图一样:

SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
  2  SELECT v.id, dbt.value01
  3    FROM dbt
  4    RIGHT JOIN
  5      (SELECT to_number(regexp_substr(txt, '[^,]+', 1, LEVEL)) ID
  6         FROM DATA
  7       CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1) v
  8       ON dbt.id = v.id;

        ID VALUE01
---------- ----------
       100 Ann
       300 John
       200 

答案 2 :(得分:0)

解决此问题的一种方法是动态创建一个公用表表达式,然后可以将其包含在查询中。你要瞄准的最终synatx是:

with list_of_values as (
  select 100 val from dual union all
  select 200 val from dual union all
  select 300 val from dual union all
  ...)
select
  lov.val,
  ...
from
  list_of_values lov left outer join 
  other_data     t   on (lov.val = t.val)

它不是很优雅,特别是对于大型值集,但与您可能没有特权的数据库的兼容性非常好。