1

ここに問題があります。私の会社には、自動化された操作を実行したい大規模なデータベースがあります。6 つの 10MB サイズの csv ファイルについて、そのデータの小さなサンプルを取得したことをテストします。H2 を使用して、プログラムの結果をテストしたいと考えています。H2 以前の cv は、せいぜい 1000 エントリの長さでしたが、問題なく動作したようです。10MBのファイルのいずれかになると、コマンド

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

レジストリの 1 つが重複していると思われ、主キーの制約に違反しているため、エラーが報告されます。

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

mycsvfile.csv を小さな断片に分割すると、約 10000 行が挿入された後に問題が発生し始めることがわかりました (ただし、使用したデータによって数は異なります)。ただし、ファイルを分割してコマンドを個別に実行すると、10000 行を超える行を挿入できました。しかし、すべてのデータを手動で挿入できたとしても、データベースを埋めるための自動化された方法が必要です。

コマンドを実行しても問題の原因となっている行が表示されないため、問題は csvread ルーチンのキャッシュにある可能性があると推測しました。

次に、データを H2 データベースに手動で挿入できる小さな Java プログラムを作成しました。コマンドをバッチ処理したかどうかに関係なく、1000 行の接続を閉じてから開き、データベース内のエントリを複製しようとしていると報告されました。

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]

emacs を使用してそのレジストリを通常の検索を行うと、datetime 列がデータセット全体で一意であるため、レジストリが重複していないことがわかります。

会社がその情報を販売しているため、テスト用にそのデータを提供することはできません. しかし、これが私のテーブル定義のようなものです。

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();
}

リクエストがあれば、さらに情報を提供させていただきます。

編集

@Randyコマンドを実行する前にデータベースがクリーンであるかどうかを常に確認します.Javaプログラムには、挿入に失敗したファイルからすべてのデータを削除するルーチンがあります。

 select * from myschema.mytable where largenumber  = 25485116;
 DATETIME   LARGENUMBER     VALUE   FLAG    KIND  
 (no rows, 8 ms)
4

1 に答える 1

0

私が考えることができる唯一のことは、タイムスタンプを「今」に設定するトリガーがテーブルにあるということです。数行で成功する理由は説明できませんが、主キーに違反している理由は説明できます。

于 2011-02-03T20:17:31.170 に答える