2012-04-07 14 views
97

Diciamo che ho una classe che rappresenta le posizioni. Le posizioni "appartengono" ai clienti. Le posizioni sono identificate da un codice unicode di 10 caratteri. Il "codice località" dovrebbe essere unico tra le località per un cliente specifico.sqlalchemy unico su più colonne

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, cliente "123" e cliente "456". Entrambi possono avere una posizione chiamata "main" ma nessuno dei due potrebbe avere due posizioni chiamate main.

Sono in grado di gestirlo nella logica di business ma voglio essere sicuro 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 in modo che l'intera tabella abbia solo un codice univoco per tutte le posizioni.

risposta

174

Estratto dalla documentation del Column:

unica - in cui i veri, indica che questa colonna contiene un unico vincolo, o se indice è vero anche, indica che l'indice dovrebbe essere creato con la bandiera unica. Per specificare più colonne in il vincolo/indice o per specificare un nome esplicito, utilizzare i costrutti UniqueConstraint o Index in modo esplicito.

Poiché queste appartengono ad un tavolo e non a una classe mappata, si dichiara quelli nella definizione della tabella, o se si utilizza dichiarativa 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'), 
        ) 
+0

io faccia lo stesso problema anche, ma l'utilizzo di UniqueConstraint non mi ha aiutato. Dopo aver provato con Index ('...'), ottengo un vincolo univoco. C'è qualche spiegazione con questo comportamento? – swdev

+1

@swdev: quale RDBMS usi? – van

+0

Sto usando PostgreSQL. C'è un problema con questo? – swdev