Motivation
Nehmen Sie ein triviales Beispiel, wo eine Spalte von Daten durch einen Aufzählungstyp in SQL dargestellt werden muss:Wie werden in SQLAlchemy Lookup-Tabellendaten deklariert und initialisiert?
+------------------------------------------+
| user |
+----+------+-----+------------------------+
| id | name | age | relationship_status_id |
+----+------+-----+------------------------+
| 1 | John | 27 | 3 |
| 2 | Mary | 77 | 1 |
| 3 | Jack | 40 | 4 |
+----+------+-----+------------------------+
+---------------------+
| relationship_status |
+----+----------------+
| id | name |
+----+----------------+
| 1 | married |
| 2 | widowed |
| 3 | single |
| 4 | divorced |
+----+----------------+
definieren (erklärt) die Tabellen selbst in SQLAlchemy ist relativ einfach:
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
relationship_status_id = Column(Integer, ForeignKey('relationship_status.id'))
class RelationshipStatus(Base):
__tablename__ = 'relationship_status'
id = Column(Integer, primary_key=True)
name = Column(String)
Bei der Initialisierung der Datenbank können Tabellen mit einer Anweisung Base.metadata.create_all(engine)
erstellt werden. Die Tabelle user
würde während der Laufzeit der Anwendung gefüllt werden. Die Daten der Lookup-Tabelle relationship_status
bleiben jedoch konstant, und es scheint angezeigt, diese Daten zusammen mit der Tabellendefinition zu "deklarieren".
Noch persistente Daten zu einer Tabelle erfordert natürlich eine session
, und im Gegensatz zu den Tabellendefinitionen selbst, SQLAlchemy scheint kein deklaratives Konstrukt für "erwartete Zeilen" in einer bestimmten Tabelle (natürlich, da die Mehrheit der Tabellen in jedem Anwendung sind wie user
mit dynamischen Daten).
Problem
Mit SQLAlchemy, wie kann man sowohl das Schema und die Daten einer Lookup-Tabelle vor der Anwendung Laufzeit erklären? Idealerweise würde die Lösung die Erstellung eines Enum-ähnlichen Konstrukts beinhalten, das die Daten enthält, auf die sich andere Teile der Anwendung beziehen können.
Forschung
Der Schöpfer von SQLAlchemy vorgeschlagen the enum recipe. Der einzige offensichtliche Nachteil einer solchen Lösung ist, dass man sich innerhalb des verwendeten DBMS auf den enum
Datentyp verlassen muss. Für den Umfang dieser Frage wird eine DBMS-unabhängige Lookup-Table-Lösung bevorzugt.
Eine verwandte Alternative, die ebenfalls von SQLAlchemy's Creator vorgeschlagen wird, ist the unique object recipe. Eine solche Implementierung stellt sicher, dass die von Nachschlagetabellenabfragen zurückgegebenen Zeilen ohne Duplikate bleiben, aber ein Objekt session
immer noch benötigt wird, um irgendwelche Deklarationen oder Anforderungen zu machen - was die Trennung von Belangen zwischen Datenbankdefinition und Implementierung verwischt. Außerdem müssten die Kunden einfach nur "wissen", nach welchen Zeilen sie fragen sollen, anstatt irgendeine Art von Enumeration (in Python) als Referenz zu haben.
Die Ursache des Problems kann konzeptionell sein und nicht an SQLAlchemy oder Python gebunden sein. In jedem Fall würde jeder Rat sehr geschätzt werden.
Sie könnten String-Formatierung mit ['table()'] vermeiden (http: //docs.sqlalchemy.org/de/latest/core/selectable.html # sqlalchemy.sql.expression.table): 'connection.execute (table (target.name) .insert(). values ([{'name': 'single'}, ...])) ', was es auch erlauben würde, die Anfangswerte als Python-Strukturen zu definieren, anstatt sie in die SQL-Abfrage einzufügen. –
Vielen Dank für den Verweis auf den 'after_create' Trigger; es scheint die am besten geeignete Lösung zu sein. Ich bin fasziniert von Ihrer Notiz, dass solche Daten nicht für die Speicherung in einer Datenbank geeignet sind, und ich würde dem eher zustimmen. Aber mit DBMS-basierten Aufzählungen, die systemübergreifend inkonsistent sind, welche Alternativen gibt es für Situationen wie die oben beschriebene? Ich hatte den Eindruck, dass Nachschlagetabellen die akzeptierte Best Practice waren. Wie würden Überprüfungsbedingungen mit einer Python-Enumeration implementiert? – RNanoware