1

何百万ものレコードを含むデータベースを調べなければならないというタスクに直面しています。約 1500 のセットのコードには対応するレコードがあり、そのうちの 1 つがデータベースに存在します。たとえば、csv ファイルに 1500 個の ID があります。これらの ID のどれがデータベースに存在し、したがって正しいか、どれが正しくないかを知りたいです。

「...」なしでこれを行うより良い方法はありWHERE id IN (1, 2, 3, ..., 1500);ますか? 問題の DB/言語は 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 内のデータが変更される頻度と、それを照会する必要がある頻度によって異なります。ファイルが 1 日に 1 回生成され、配信後に値を確認するだけでよい場合は、外部テーブルが最も効率的なソリューションです。しかし、このデータ セットが頻繁にクエリを実行する必要がある永続的なリポジトリである場合、ヒープ テーブルへの書き込みのオーバーヘッドは明らかに正当化されます。

私には、多数の ID と他に何もない CSV ファイルは、一時的なデータのように聞こえるため、外部テーブルの使用例に適しています。ただし、OPには、言及されていない追加の要件がある場合があります。


これは、永続的なデータベース オブジェクトを作成する必要のない別の方法です。その結果、エレガントではなくなり、パフォーマンスが低下する可能性があります。

UTL_FILE を使用して CSV ファイルを苦労して読み取り、SYSTEM.NUMBER_TBL_TYPE に基づいてコレクションを作成します。これは、Oracle データベースで使用できる事前定義されたコレクション (NUMBER のネストされたテーブル) です。

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 に答える