2017-01-05 18 views
0

これは簡単な質問です。 私はSQLAlchemyで遊んでいましたが、私は今、テーブルの一意の制約を扱う時点にいます。 したがって、一意制約に違反すると、IntegrityError例外が発生します。テーブルに対して複数の一意制約が定義されている場合、発生した例外を使用してそれらを区別するにはどうすればよいですか?整合性エラーが発生した場合の異なる一意制約の区別方法

編集: 私は下にsqlite3を使用しています。

最終編集: AVC回答は、制約に違反した列のメッセージエラーをチェックすることで、代替の解決方法を提供します。それは優雅な解決策ではありませんが、それは仕事を完了します。

+0

参照してください。 [android.database.SQLExceptionからエラーの詳細を取得する方法?](http://stackoverflow.com/questions/35637570/how-to-get-errors-details-from-android-database-sqlexception) –

+0

役に立たなかった私はAndroidやJavaを使用していません。 – Claymore

答えて

1

整合性エラーは、どの列が制約に違反しているかを示します。 exampleについて:

IntegrityError: (IntegrityError) insert or update on table "my_table" 
      violates foreign key constraint "my_table_some_column_fkey" 

あなたのケースでは、このようなあなたの制約を宣言している:あなたがここでやっていることは、複数の一意性制約を宣言ないです

UniqueConstraint('datapath_port_id', 'datapath_id', 
    'controller_id', name='unique_registration') 

Column('datapath_port_id', unique=True) 
Column('datapath_id', unique=True) 
Column('controller_id', unique=True) 

代わりにあなたはすべての3つの列の組み合わせは一意でなければならないことを意味し、マルチカラムまたは複合一意性制約を作成している:それは次のようになります。

複数行の一意性制約を使用してデータベース行A, B, Cを作成した場合は、最初にAという値が既に存在していても、まだA, A, Aを挿入できます。同様に、B, B, BおよびC, C, Cも有効な挿入物です。何が失敗するかは、A, B, Cを再度挿入しようとしています。これは、すべての列が既存の行と一致するために失敗します。これは、表示される一意性エラーがすべての列をリストしている理由です。ここで

は、コードと例です。

from sqlalchemy import create_engine 
from sqlalchemy import Column, Integer 
from sqlalchemy import UniqueConstraint 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 

engine = create_engine('sqlite:///:memory:', echo=True) 
Base = declarative_base() 


class Test(Base): 
    __tablename__ = 'test' 
    __table_args__ = (
     UniqueConstraint('a', 'b', name='ab_constraint'), 
     UniqueConstraint('b', 'c', name='bc_constraint')) 
    id = Column(Integer, primary_key=True) 
    a = Column(Integer) 
    b = Column(Integer) 
    c = Column(Integer) 


Base.metadata.create_all(engine) 
Session = sessionmaker(bind=engine) 
session = Session() 

session.add(Test(a=1, b=1, c=1)) 
session.add(Test(a=2, b=2, c=2)) 

そこから私たちは何が起こるかを見るために別の一意性制約に違反しようとすることができます。このコマンドを実行しようとすると:

sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.a, test.b u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 1, 2) 

を我々は第2の制約に違反しようとした場合、その後:

session.add(Test(a=1, b=1, c=2)) 
session.commit() 

を我々が得る

session.add(Test(a=1, b=2, c=2)) 
session.commit() 

を私たちは、代わりに取得:

sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.b, test.c u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 2, 2) 

最初のケースではtest.atest.bは制約に違反し、2番目はtest.btest.cを指定しています。

私はこれらの制約(ab_constraintbc_constraint)のために選んだ名は、しかし、応答に含まれませんされています。それらはですが、データベースレベルではです。私たちは、データベース作成コマンドをエコーすることで、これを見ることができます:

CREATE TABLE test (
    id INTEGER NOT NULL, 
    a INTEGER, 
    b INTEGER, 
    c INTEGER, 
    PRIMARY KEY (id), 
    CONSTRAINT ab_constraint UNIQUE (a, b), 
    CONSTRAINT bc_constraint UNIQUE (b, c) 
) 

しかし、制約名がエラーメッセージに使用されていなくても(私はSQLiteのを使用しています)データベースレベルで:

sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 1); 
sqlite> INSERT INTO test (a, b, c) VALUES (2, 2, 2); 
sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 2); 
Error: UNIQUE constraint failed: test.a, test.b 
+0

私の制約のために結果が返ってこなかったので、これは奇妙です。 私は下にsqlite3を使用していることを忘れています。 これは、ユニーク制約の結果です。 (sqlite3.IntegrityError)UNIQUE制約に失敗しました:hosts.datapath_port_id、hosts.datapath_id、hosts.controller_id [SQL: 'INSERT INTO hosts(host_mac、datapath_port_id、datapath_id、controller_id、registration_date)VALUES(?、?、?、? 、 '?')] [パラメータ:( 'AA-BB-CC-DD-EE-FF'、1,1,1 '2017-01-06 15:06:38.429267')] – Claymore

+0

constaintが宣言されています 'UniqueConstraint( 'datapath_port_id'、 'datapath_id'、 'controller_id'、name = 'unique_registration')、 ' – Claymore

+0

私はあなたの混乱の原因を理解していると思います。私の答えが更新されました。 – ACV

関連する問題