1

我面临着必须查看具有数百万条记录的数据库的任务,一组大约 1500 条记录中的哪些代码具有相应的记录,其中哪些存在于数据库中。例如,我在 csv 文件中有 1500 个 ID。我想知道数据库中存在哪些 ID,因此是正确的,哪些不存在。

没有“...”有没有更好的方法WHERE id IN (1, 2, 3, ..., 1500);?有问题的数据库/语言是 ORACLE PL/SQL。

提前感谢您的帮助。

4

1 回答 1

3

在您的 CSV 文件上构建一个外部表。这些都是非常简洁的东西,允许我们在 SQL 中查询 OS 文件的内容。 了解更多

然后发出一个查询就很简单了:

select csv.id
       , case ( when tgt.id is null then 'invalid' else 'valid') end as valid_id
from your_external_tab csv
       left join target_table tgt on (csv.id = tgt.id)

“从性能的角度来看,CSV 表并不理想”

性能是一个上下文问题。在这种情况下,这取决于 CSV 中数据的更改频率以及我们需要查询它的频率。如果文件每天生成一次,并且我们只需要在交付后检查值,那么外部表是最有效的解决方案。但是如果这个数据集是一个需要经常查询的永久存储库,那么写入堆表的开销显然是合理的。

对我来说,一个由一堆 ID 组成的 CSV 文件听起来像瞬态数据,因此适合外部表的用例。但是 OP 可能有他们没有提到的其他要求。


这是一种不需要创建任何永久数据库对象的替代方法。因此,它不太优雅,并且可能会表现得更差。

它使用 UTL_FILE 费力地读取 CSV 文件并填充基于 SYSTEM.NUMBER_TBL_TYPE 的集合,这是一个预定义的集合(NUMBER 的嵌套表),应该在您的 Oracle 数据库中可用。

declare
    ids system.number_tbl_type;
    fh utl_file.file_handle;
    idx pls_integer := 0;
    n pls_integer;
 begin
    fh := utl_file.fopen('your_data_directory', 'your_data.csv', 'r');
    begin
        utl_file.get_line(fh, n);
        loop  
            idx := idx + 1;
            ids.extend();
            ids(idx) := n;
            utl_file.get_line(fh, n);
        end loop;
   exception
      when no_data_found then
          if utl_file.is_open(fh) then
             utl_file.fclose(fh);
          end if;
     when others then
          raise;
  end;
  for id_recs in  in  ( select csv.column_value 
              , case ( when tgt.id is null then 'invalid' else 'valid') end as valid_id
                from (select * from table(ids)) csv
            left join target_table tgt on (csv.column_value = tgt.id)
  ) loop
  dbms_output.put_line '(ID '||id_recs.column_value || ' is '||id_recs.valid_id);
  end loop;
end;

注意:我没有测试过这段代码。原理是合理的,但细节可能需要调试;)

于 2012-07-30T11:56:10.443 回答