3

我试图为这个问题找到解决方案一段时间但没有成功,所以任何帮助将不胜感激。需要将 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。

4

3 回答 3

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 元素)。只需设置为一个合理准确的数字。

于 2013-02-14T10:26:26.600 回答
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 
于 2013-02-14T10:21:06.117 回答
0

解决此问题的一种方法是动态创建一个公共表表达式,然后可以将其包含在查询中。您的最终目标是:

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)

它不是很优雅,尤其是对于大量值集,但是与您可能没有多少权限的数据库的兼容性非常好。

于 2013-02-14T10:23:29.413 回答