SQLalchemie einzigartig über mehrere Spalten

174

Angenommen, ich habe eine Klasse, die Standorte darstellt. Standorte "gehören" zu Kunden. Standorte werden durch einen 10-stelligen Unicode-Code identifiziert. Der "Standortcode" sollte unter den Standorten für einen bestimmten Kunden eindeutig sein.

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

Wenn ich also zwei Kunden habe, Kunde "123" und Kunde "456". Beide können einen Standort namens "main" haben, aber keiner kann zwei Standorte namens main haben.

Ich kann dies in der Geschäftslogik behandeln, aber ich möchte sicherstellen, dass es keine Möglichkeit gibt, die Anforderung in sqlalchemy einfach hinzuzufügen. Die Option unique = True scheint nur zu funktionieren, wenn sie auf ein bestimmtes Feld angewendet wird, und würde dazu führen, dass die gesamte Tabelle nur einen eindeutigen Code für alle Speicherorte enthält.

Ominus
quelle

Antworten:

298

Auszug aus der Dokumentation des Column:

unique - Wenn True, gibt dies an, dass diese Spalte eine eindeutige Einschränkung enthält, oder wenn index ebenfalls True ist, gibt dies an, dass der Index mit dem eindeutigen Flag erstellt werden soll. Verwenden Sie die Konstrukte UniqueConstraint oder Index explizit, um mehrere Spalten in der Einschränkung / dem Index anzugeben oder einen expliziten Namen anzugeben .

Da diese zu einer Tabelle und nicht zu einer zugeordneten Klasse gehören, deklariert man diese in der Tabellendefinition oder bei Verwendung von Deklarativ wie in __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'),
                     )
van
quelle
Ich habe auch das gleiche Problem, aber die Verwendung von UniqueConstraint hat mir nicht geholfen. Nachdem ich es mit Index ('...') versucht habe, erhalte ich eine eindeutige Einschränkung. Gibt es eine Erklärung für dieses Verhalten?
Swdev
1
@swdev: Welches RDBMS verwenden Sie?
van
3
Danke, aber meine Frage war: Haben Sie SA (und Flask) verwendet, um ein DB-Schema zu erstellen, oder haben Sie es separat erstellt?
van
1
Warum ist die .c. gebraucht?
Smiley
1
@ Smiley .c.ist eine Abkürzung zu.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))
Joash
quelle
1
Muss sein __table_args__ = (db.UniqueConstraint('customer_id', 'location_code'),), vergiss das Komma am Ende nicht.
Bertdida