Sono molto nuovo a SQLAlchemy e sto cercando di capirlo.Come aggiungere correttamente i vincoli di chiave esterna a SQLite DB utilizzando SQLAlchemy
Si prega di avere in mente la seguente configurazione di prova:
class Nine(Base):
__tablename__ = 'nine'
__table_args__ = (sqlalchemy.sql.schema.UniqueConstraint('nine_b', name='uq_nine_b'),)
nine_a = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), primary_key=True, autoincrement=False, nullable=False)
nine_b = sqlalchemy.Column(sqlalchemy.String(20), nullable=False)
class Seven(Base):
__tablename__ = 'seven'
__table_args__ = (sqlalchemy.sql.schema.PrimaryKeyConstraint('seven_a', 'seven_b'),
sqlalchemy.sql.schema.Index('fk_seven_c_nine_a_idx', 'seven_c'),)
seven_a = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), nullable=False)
seven_b = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), nullable=False)
seven_c = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), sqlalchemy.ForeignKey('nine.nine_a'), nullable=False)
seven_d = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), nullable=False)
nine = sqlalchemy.orm.relationship(Nine, backref=sqlalchemy.orm.backref('seven'), uselist=False)
class Three(Base):
__tablename__ = 'three'
__table_args__ = (sqlalchemy.sql.schema.UniqueConstraint('three_b', 'three_c', name='uq_three_b_c'),
sqlalchemy.sql.schema.Index('fk_three_c_seven_a_idx', 'three_c'),)
three_a = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), primary_key=True, autoincrement=True, nullable=False)
three_b = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), nullable=False)
three_c = sqlalchemy.Column(sqlalchemy.dialects.sqlite.INTEGER(), sqlalchemy.ForeignKey('seven.seven_a'), nullable=False)
seven = sqlalchemy.orm.relationship(Seven, backref=sqlalchemy.orm.backref('three'), uselist=False)
che si traduce nei seguenti DDL:
CREATE TABLE nine (
nine_a INTEGER NOT NULL,
nine_b VARCHAR(20) NOT NULL,
PRIMARY KEY (nine_a),
CONSTRAINT uq_nine_b UNIQUE (nine_b)
);
CREATE TABLE seven (
seven_a INTEGER NOT NULL,
seven_b INTEGER NOT NULL,
seven_c INTEGER NOT NULL,
seven_d INTEGER NOT NULL,
PRIMARY KEY (seven_a, seven_b),
FOREIGN KEY(seven_c) REFERENCES nine (nine_a)
);
CREATE INDEX fk_seven_c_nine_a_idx ON seven (seven_c);
CREATE TABLE three (
three_a INTEGER NOT NULL,
three_b INTEGER NOT NULL,
three_c INTEGER NOT NULL,
PRIMARY KEY (three_a),
CONSTRAINT uq_three_b_c UNIQUE (three_b, three_c),
FOREIGN KEY(three_c) REFERENCES seven (seven_a)
);
CREATE INDEX fk_three_c_seven_a_idx ON three (three_c);
Tutti i tavoli sono vuoti. Quindi, le seguenti dichiarazioni di codice:
session.add(Nine(nine_a=1, nine_b='something'))
session.add(Nine(nine_a=2, nine_b='something else'))
session.commit()
session.add(Seven(seven_a=7, seven_b=7, seven_c=7, seven_d=7))
session.commit()
session.add(Three(three_a=3, three_b=3, three_c=3))
sessionDB.commit()
Qualcuno può spiegare perché il frammento di codice sopra riportato viene eseguito senza errori? I vincoli FK non dovrebbero interrompere l'inserimento di una nuova riga in seven
o three
? Presumo che ci sia qualcosa di sbagliato nel modo in cui gli FK sono descritti nelle classi stesse, ma non so dove sia il problema (e come risolverlo).
[Modifica 1]
Aggiunta __table_args__
per tutte le classi (dimenticato di includerli).
[Modifica 2]
Aggiunta DDL per ulteriore riferimento.
sto emissione 'PRAGMA FOREIGN_KEYS = ON' prima di eseguire gli inserti (il comando' PRAGMA foreign_keys' restituisce '1 'Purtroppo gli stessi risultati – Yeseanul
Ho testato il vincolo FK su ON a livello di DB, ma sembra che questo debba essere attivato per ogni connessione ([http://stackoverflow.com/a/9835781/1237714] (http://stackoverflow.com/a/9835781/1237714)). Le cose stanno iniziando a diventare ** normali **. (Si prega di includere snippet di codice (ad esempio, utilizzando eventi) in risposta.) – Yeseanul
Mentre questo può teoricamente rispondere alle domanda, [sarebbe preferibile] (// meta.stackoverflow.com/q/8259) per includere le parti essenziali della risposta a lei e, e fornire il link per riferimento. – SuperBiasedMan