2011-02-03 21 views
1

私の会社では、自動化された操作を実行するための大きなデータベースがあります。私たちがそのデータの小さなサンプルを得たことをテストするために、約10MBサイズのcsvファイルが6個あります。私たちは、H2を使ってプログラムの結果をテストしたいと思っています。 H2彼らは、せいぜい1000エントリの長さでしたが、私たちの以前のCVでうまく動作していたようです。それが私たちの10メガバイトのいずれかになるとレジストリの一つは、おそらく複製され、私たちの主キー制約を傷つけるされているので、コマンド大きなデータセットをh2データベースにロードできません

insert into myschema.mytable (select * from csvread('mycsvfile.csv')); 

は失敗を報告したファイル。問題は、(数がどのデータIが使用さによって異なるが)挿入約10000行の後に現れ始めることを私が見ることができた小さな部分にmycsvfile.csvを破る

Unique index or primary key violation: "PRIMARY_KEY_6 ON MYSCHEMA.MYTABLE(DATETIME, LARGENUMBER, KIND)"; SQL statement: 
insert into myschema.mytable (select * from csvread('src/test/resources/h2/data/mycsvfile.csv')) [23001-148] 23001/23001 

。ただし、ファイルを分割して個別にコマンドを実行すると、10000行以上を挿入することができます。しかし、私が手動ですべてのデータを挿入することができたとしても、データベースを埋めるための自動化された方法が必要です。

このコマンドを実行しても、問題を引き起こしていた行が表示されないため、問題はcsvreadルーチンのキャッシュになる可能性があります。

次に、H2データベースにデータを手動で挿入できる小さなJavaプログラムを作成しました。私がコマンドをバッチするかどうかにかかわらず、1000行の接続をクローズしてオープンしました。h2は、データベースのエントリを複製しようとしていると報告しました。

私はdatetime型の列がデータセット全体で一意であるとして、レジストリが重複していないことを見つけることができるのemacsを使用してそのレジストリのための通常の検索を行う
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_6 ON MYSCHEMA.MYTABLE(DATETIME, LARGENUMBER, KIND)"; SQL statement: 
INSERT INTO myschema.mytable VALUES ('1997-10-06 01:00:00.0',25485116,1.600,0,18) [23001-148] 

私は、会社がその情報を販売しているので、あなたにテスト用のデータを与えることはできません。しかし、ここで私のテーブル定義はどのようになっています。

create table myschema.mytable (
    datetime timestamp, 
    largenumber numeric(8,0) references myschema.largenumber(largecode), 
    value numeric(8,3) not null, 
    flag numeric(1,0) references myschema.flag(flagcode), 
    kind smallint references myschema.kind(kindcode), 
    primary key (datetime, largenumber, kind) 
); 

これが私たちのCSVファイルをどのように見えるかです:

datetime,largenumber,value,flag,kind 
1997-06-11 16:45:00.0,25485116,0.710,0,18 
1997-06-11 17:00:00.0,25485116,0.000,0,18 
1997-06-11 17:15:00.0,25485116,0.000,0,18 
1997-06-11 17:30:00.0,25485116,0.000,0,18 

そして、我々のテストデータベースは、(私の醜いコードを許して埋めるだろうJavaコード、私は絶望的だ:)

private static void insertFile(MyFile file) throws SQLException { 
    int updateCount = 0; 
    ResultSet rs = Csv.getInstance().read(file.toString(), null, null); 
    ResultSetMetaData meta = rs.getMetaData(); 
    Connection conn = DriverManager.getConnection(
      "jdbc:h2:tcp://localhost/mytestdatabase", "sa", "pass"); 
    rs.next(); 
    while (rs.next()) { 
     Statement stmt = conn.createStatement(); 
     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < meta.getColumnCount(); i++) { 
      if (i == 0) 
       sb.append("'" + rs.getString(i + 1) + "'"); 
      else 
       sb.append(rs.getString(i + 1)); 
      sb.append(','); 
     } 
     updateCount++; 
     if (sb.length() > 0) 
      sb.deleteCharAt(sb.length() - 1); 

     stmt.execute(String.format(
       "INSERT INTO myschema.mydatabase VALUES (%s) ", 
       sb.toString())); 
     if (updateCount == 1000) { 
      conn.close(); 
      conn = DriverManager.getConnection(
        "jdbc:h2:tcp://localhost/mytestdatabase", "sa", "pass"); 
      updateCount = 0; 
     } 
    } 
    if (!conn.isClosed()) { 
     conn.close(); 
    } 
    rs.close(); 
} 

リクエストされた場合、より多くの情報を提供できることをうれしく思います。

EDIT私が挿入されることに失敗したファイルからすべてのデータを削除するルーチンを持っているコマンドを実行する前に、私のJavaプログラムでデータベースがクリーンであるならば、私は常にチェック@Randy

+1

Javaコードにデバッグプリントアウトを追加して、エラーの原因となっている行を正確に指定できます。次に、既存のレコードのためにデータベース(ソースファイルではない)をチャックします。たぶんあなたは日付の切り捨てを取得していますか? – Randy

+1

プライマリキー制約なしでテーブルを作成して、それを実行してください: '日時、大番号、種別がcount(*)> 1のmytableグループからdatetime、largeenumber、kind、count(*)を選択してください。問題の根本的な原因を簡単に見つけて、それらの行を分析します。ところで、 'create table ... as select ...'という文を使うと、 'create table'と' insert'の2つの文よりも速くなります。 –

答えて

0

私が考えることができるのは、タイムスタンプを「今」に設定するトリガーがテーブルにあることだけです。なぜそれがあなたがなぜいくつかの行で成功した理由を説明していないが、それは主キーが違反されている理由を説明します。

関連する問題