sqlalchemy unikalne w wielu kolumnach


174

Powiedzmy, że mam klasę reprezentującą lokalizacje. Lokalizacje „należą” do klientów. Lokalizacje są identyfikowane za pomocą 10-znakowego kodu Unicode. „Kod lokalizacji” powinien być niepowtarzalny wśród lokalizacji dla określonego klienta.

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

Więc jeśli mam dwóch klientów, klienta „123” i klienta „456”. Oba mogą mieć lokalizację zwaną „główną”, ale żadna z nich nie może mieć dwóch lokalizacji zwanych główną.

Potrafię sobie z tym poradzić w logice biznesowej, ale chcę się upewnić, że nie ma możliwości łatwego dodania wymagania w sqlalchemy. Opcja unique = True działa tylko wtedy, gdy zostanie zastosowana do określonego pola i spowodowałaby, że cała tabela miałaby tylko unikalny kod dla wszystkich lokalizacji.

Odpowiedzi:


298

Wyciąg z dokumentacji z Column:

unique - Gdy True, wskazuje, że ta kolumna zawiera unikalne ograniczenie lub jeśli indeks ma również wartość True, wskazuje, że indeks powinien zostać utworzony z unikalną flagą. Aby określić wiele kolumn w ograniczeniu / indeksie lub określić jawną nazwę, należy jawnie użyć konstrukcji UniqueConstraint lub Index .

Ponieważ należą one do tabeli, a nie do zamapowanej klasy, deklaruje się je w definicji tabeli lub w przypadku użycia deklaratywnego, jak w __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'),
                     )

Mam ten sam problem, ale użycie UniqueConstraint mi nie pomogło. Po wypróbowaniu indeksu („...”) otrzymuję unikalne ograniczenie. Czy jest jakieś wyjaśnienie tego zachowania?
swdev

1
@swdev: którego RDBMS używasz?
van

3
Dzięki, ale moje pytanie brzmiało: czy użyłeś SA (i Flask) do stworzenia schematu bazy danych, czy też stworzyłeś go osobno?
van

1
Dlaczego .c. używany?
Smiley

1
@Smiley .c.to skrót do.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
Musi być __table_args__ = (db.UniqueConstraint('customer_id', 'location_code'),), nie zapomnij o przecinku na końcu.
bertdida
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.