sqlalchemy unico su più colonne


174

Diciamo che ho una classe che rappresenta i luoghi. Le posizioni "appartengono" ai clienti. Le posizioni sono identificate da un codice unicode di 10 caratteri. Il "codice di posizione" dovrebbe essere univoco tra le posizioni per un cliente specifico.

The two below fields in combination should be unique
customer_id = Column(Integer,ForeignKey('customers.customer_id')
location_code = Column(Unicode(10))

Quindi, se ho due clienti, il cliente "123" e il cliente "456". Entrambi possono avere una posizione chiamata "principale", ma nessuno dei due potrebbe avere due posizioni chiamate principale.

Posso gestirlo nella logica aziendale ma voglio assicurarmi che non ci sia modo di aggiungere facilmente il requisito in sqlalchemy. L'opzione unique = True sembra funzionare solo se applicata a un campo specifico e farebbe sì che l'intera tabella avesse solo un codice univoco per tutte le posizioni.

Risposte:


298

Estratto dalla documentazione di Column:

univoco : se True, indica che questa colonna contiene un vincolo univoco, o se anche l' indice è True, indica che l'indice deve essere creato con il flag univoco. Per specificare più colonne nel vincolo / indice o per specificare un nome esplicito, utilizzare i costrutti UniqueConstraint o Index in modo esplicito.

Poiché questi appartengono a una tabella e non a una classe mappata, si dichiarano quelli nella definizione della tabella o se si utilizza dichiarativo come nel __table_args__:

# version1: table definition
mytable = Table('mytable', meta,
    # ...
    Column('customer_id', Integer, ForeignKey('customers.customer_id')),
    Column('location_code', Unicode(10)),

    UniqueConstraint('customer_id', 'location_code', name='uix_1')
    )
# or the index, which will ensure uniqueness as well
Index('myindex', mytable.c.customer_id, mytable.c.location_code, unique=True)


# version2: declarative
class Location(Base):
    __tablename__ = 'locations'
    id = Column(Integer, primary_key = True)
    customer_id = Column(Integer, ForeignKey('customers.customer_id'), nullable=False)
    location_code = Column(Unicode(10), nullable=False)
    __table_args__ = (UniqueConstraint('customer_id', 'location_code', name='_customer_location_uc'),
                     )

Devo affrontare anche lo stesso problema, ma l'utilizzo di UniqueConstraint non mi ha aiutato. Dopo aver provato con Index ('...'), ho un vincolo unico. C'è qualche spiegazione con questo comportamento?
swdev,

1
@swdev: quale RDBMS usi?
van

3
Grazie, ma la mia domanda era: hai usato SA (e Flask) per creare uno schema DB o l'hai creato separatamente?
van,

1
Perché è il .c. Usato?
Faccina

1
@Smiley .c.è una scorciatoia per.columns.
van

7
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class Location(Base):
      __table_args__ = (
        # this can be db.PrimaryKeyConstraint if you want it to be a primary key
        db.UniqueConstraint('customer_id', 'location_code'))
      customer_id = Column(Integer,ForeignKey('customers.customer_id')
      location_code = Column(Unicode(10))

1
Deve essere __table_args__ = (db.UniqueConstraint('customer_id', 'location_code'),), non dimenticare la virgola alla fine.
Bertdida,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.