10

REF 整合性ルールを使用して、データベースに 10,000 レコードをいくつか挿入しています。残念ながら、一部のデータ行は重複しています (データベースに既に存在するため)。挿入する前にデータベース内のすべての行の存在をチェックするのはコストがかかりすぎるため、SQLAlchemy によってスローされた IntegrityError 例外を処理し、エラーをログに記録してから続行するつもりです。

私のコードは次のようになります。

# establish connection to db etc.

tbl = obtain_binding_to_sqlalchemy_orm()
datarows = load_rows_to_import()

try:
    conn.execute(tbl.insert(), datarows)
except IntegrityError as ie:
    # eat error and keep going
except Exception as e:
    # do something else

上記で行っている (暗黙の) 仮定は、SQLAlchemy が複数の挿入を 1 つのトランザクションにまとめていないということです。私の仮定が間違っている場合、IntegrityError が発生すると、残りの挿入が中止されることを意味します。上記の疑似コード「パターン」が期待どおりに機能するかどうかを誰かが確認できますか?または、 IntegrityError 例外がスローされた結果、データが失われるのでしょうか?

また、誰かがこれを行うためのより良いアイデアを持っている場合は、私はそれを聞くことに興味があります.

4

3 に答える 3

2

この場合、sqlalchemy の自動コミット機能が有効になるため、以前にトランザクションを開始していない場合は、このように機能する可能性がありますが、リンクに記載されているように明示的に設定する必要があります。

于 2012-05-14T15:46:38.063 に答える
0

アクションを実行するよう SQL エンジンに指示する方法はほとんどありませんbulk insert on duplicate ignore。ただし、Python 側でフォールバック ソリューションを試すことができます。複製が非常に悪い方法で配布されていない場合*、これは両方の世界の利点をほぼ享受します.

try:
    # by very bad, I mean what if each batch of the items contains one duplicate
    session.bulk_insert_mappings(mapper, items)
    session.commit()
except IntegrityError:
    logger.info("bulk inserting rows failed, fallback to one by one")
    for item in items:
        try:
            session.execute(insert(mapper).values(**item))
            session.commit()
        except SQLAlchemyError:
            logger.exception("Error inserting item: %s", item)
于 2021-08-08T03:09:51.113 に答える