1

私はそのようなテーブルを持っています:

class Tag(Base):
    __tablename__ = 'tag'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(50), nullable=False)

    def __init__(self, name):
        self.name = name

テーブルが空であるとします。そのような方法でいくつかのデータを挿入するよりも:

t = Tag('first tag')
t.id = 2
dbsession.add(t)
dbsession.commit()

大丈夫です。postgresql テーブルに id = 2 の行が 1 つあります。次に:

t = Tag('second tag')
dbsession.add(t)
dbsession.commit()

{id: 1, name: 'second tag'} と {id: 2, name: 'first_tag'} の 2 行があります。

次へ (最終ステップ):

t = Tag('third tag')
dbsession.add(t)
dbsession.commit()

IntegrityError : (IntegrityError) 重複するキー値が一意の制約 "tag_pkey" に違反しています

(id = 2 の行を作成したいのですが、既に最初のタグに関与しています)

どういうわけかpostgresに言うことは可能ですか:そのようなpkeyが存在する場合は、それが利用可能になるまで次を試してください?

ダンプを使用する場合に非常に便利です。

前もって感謝します!

4

1 に答える 1

4

私はあなたが望むことをするための安全で効率的な方法を知りません。キーを自分で定義するか、生成されたキーを使用してどちらかの戦略に固執するかを実際に選択する必要があります。

ひどい同時実行性を気にしない場合はLOCK TABLE thetable、作業を行いsetval、テーブルの識別子シーケンスを挿入した後の次の空き値にcommit移動し、ロックを解除できます。ただし、それでも、列リストnextvalから値を省略したり、明示的に名前を付けたりして値をデータベースに定義させるのではなく、(多くのORMのように)明示的に呼び出すアプリで問題が発生します。?INSERTDEFAULT

それ以外の場合は、コード(またはPL / PgSQLヘルパー関数)に再試行ループで挿入を実行させて、キーをインクリメントし、整合性エラーが発生したときに再試行することができます。この戦略は、トランザクションごとに1つ以上の挿入を行う必要がある場合は機能しません。さらに、SERIALIZABLE分離モードでは、PL / PgSQLでそれを行うことはできないと思います。シリアル化の失敗を処理するには、クライアント側の再試行ループを使用する必要があります。

それはひどい考えです。アプリケーション定義のキーを一貫して使用するか、データベース定義のキーを一貫して使用してください。2つを混ぜないでください。

于 2012-09-10T07:23:18.380 に答える