angle-up arrow-clockwise arrow-counterclockwise arrow-down-up arrow-left at calendar card-list chat check envelope folder house info-circle pencil people person person-plus phone plus question-circle search tag trash x

Konvertieren einer SQLAlchemy MariaDb / MySQL Datenbank mit Integer Primary Keys in UUID Primary Keys für eine Flask Website

26 April 2020 durch Peter

Erstellen Sie Skripte, um die Konvertierung zu automatisieren. Sie ersparen Ihnen Zeit und verhindern unnötige Fehler.

post main image
https://unsplash.com/@enginakyurt

Diese Website verwendet Flask, (einfach) SQLAlchemy mit Alembic für Migrationen und MariaDb. Wenn Sie diese nicht verwenden, ist dieser Beitrag wahrscheinlich nicht das, was Sie suchen.

In einem früheren Beitrag habe ich geschrieben, warum viele Websites UUID Primary Keys anstelle von Integer Primary Keys verwenden sollten. Selbst wenn Sie eine hochleistungsfähige Website haben, sind wahrscheinlich nur wenige Tabellen für diese Leistung verantwortlich. Hochleistungs-Websites verwenden Caching, was bedeutet, dass (in den meisten Fällen) SELECT Leistungsunterschiede nicht zu Unterschieden in der Seitenreaktionszeit führen.

Das Hauptproblem bei der Verwendung von UUID Primary Keys ist die Leistung von INSERT bei Tabellen mit vielen Datensätzen. Die Neuberechnung der Schlüssel nach einem INSERT ist weitaus zeitaufwändiger als bei Verwendung von Integer Primary Keys. Für diese Website zeichne ich jede Anfrage in einer Datenbanktabelle page_request auf, auch eine Ansicht eines Blog-Posts wird in einer Tabelle content_item_view aufgezeichnet. Beide Tabellen müssen die maximale Leistung von INSERT aufweisen. Die anderen Tabellen haben nicht so viele Datensätze. Diese beiden Tabellen und einige Demo-Tabellen sind die einzigen Tabellen, die ich nicht konvertiert habe. Die Gesamtzahl der Tabellen in der Datenbank beträgt 80. Alle haben die Id-Spalte, die umgesetzt werden muß, vielleicht die Hälfte (?) verwendet nicht Foreign Keys.

Sollten Sie die Datenbank Ihrer Website konvertieren? Wahrscheinlich nicht, wenn sie gut läuft und Sie zufrieden sind. Ich wollte zu UUIDs konvertieren, also lesen Sie diesen Beitrag weiter, wenn Sie das auch wollen. Funktioniert die beschriebene Methode? Ja. Dieser Beitrag wurde auf der neuen (konvertierten) Datenbank geschrieben.

Automatisieren der Konvertierung der bestehenden Datenbank

Es gibt zwei wichtige Gründe, die Konvertierung zu automatisieren:

  • Minimale Ausfallzeit der produktiven Website
  • Vermeiden von Fehlern

Der Prozess zur Überführung der konvertierten Datenbank in die Produktion sieht in etwa so aus:

  • Website abbauen
  • Erstellen Sie eine Kopie der vorhandenen Datenbank
  • Datenbank in ein anderes (lokales) System kopieren
  • Datenbank konvertieren
  • Kopieren der konvertierten Datenbank in das Produktivsystem
  • Neue Software-Version aktivieren
  • Website aufrufen

Die Zeit für die Konvertierung der Datenbank sollte so kurz wie möglich gehalten werden, ja, sie muss sogar automatisiert werden, weil wir auch Fehler vermeiden wollen. Ein Skript, das die Konvertierung durchführt, kann dies für Sie erledigen. Sie können dieses Skript so lange vorbereiten und testen, wie Sie wollen. Sobald Sie wissen, dass es einwandfrei funktioniert, sind Sie bereit für die Konvertierung der Produktionsdatenbank.

Ich habe auch zwei weitere Skripte entwickelt, siehe auch unten:

  • Tabellen und Spalten vergleichen
  • Kopieren von Daten von einer Datenbank in eine andere

Die Konvertierung der Datenbank erfolgt in vier Schritten

Machen Sie vor allem Sicherungen Ihrer Datenbank und überprüfen Sie durch Wiederherstellen und Testen, ob diese Sicherungsdatenbank korrekt ist! Sie wollen keine Daten verlieren. Die vier Schritte sind:

  1. Konvertieren Sie die vorhandene Datenbank in eine neue Datenbank DB_DATA mit UUIDs
    Diese Datenbank enthält die Daten. Wir kümmern uns nicht um Einschränkungen, wir entfernen sie sogar alle. Das bedeutet, dass in der neuen Datenbank Foreign Keys nur Werte sind. Die wichtigsten Dinge, die wir hier tun, sind: Integer Primary Keys in UUID Primary Keys umwandeln und Integer Foreign Keys in UUID Foreign Keys umwandeln.
  2. Generieren Sie eine Datenbank DB_FINAL mit Alembic mit UUIDs
    . Diese Datenbank hat die UUID Primary Keys, UUID Foreign Keys und Beziehungen. Aber sie hat noch keine Daten ... noch nicht. Ich habe einen neuen Baum oder eine neue Version der Software erstellt. Hier nehme ich alle Änderungen vor, um UUID Primary Keys anstelle von Integer Primary Keys zu behandeln. In dieser neuen Version habe ich Änderungen an der Datei models.py vorgenommen: Integer Primary Keys bis UUID Primary Keys, Integer Foreign Keys bis UUID Foreign Keys
  3. Vergleichen Sie die Datenbanktabellen und Spalten der Datenbank DB_DATA mit den Datenbanktabellen und Spalten der Datenbank DB_FINAL
    Wir vergleichen keine Constraints. Sie MÜSSEN identisch sein, sonst können wir die Daten im nächsten Schritt nicht kopieren!
  4. Kopieren Sie die Datenbanktabellendaten von DB_DATA in die Datenbanktabellen von DB_FINAL
    . Ich mache dies mit SELECT INTO OUTFILE und LOAD DATA INFILE.

Einige Worte über den Code

Der zeitaufwendigste Teil, den ich entwickeln musste, war die Datenbankklasse. Diese enthält hauptsächlich MariaDb / MySQL administrative Methoden. Ich werde nicht meinen gesamten Code zeigen, aber um Ihnen einen Eindruck zu vermitteln, hier ist die Datenbankklasse mit einigen Methoden:

import pymysql.cursors
import uuid


class Database:

    def __init__(self,  user=None, passwd=None, host=None, db=None, charset=None, autocommit=None, connect_timeout=None):
        ...

    def set_foreign_key_checks(self, off_on):
        
    def table_get_constraints(self, table_name):

    def table_has_integer_primary_key_id(self, table_name):

    def table_create_column(self, table_name, column_definition):

    def table_column_add_key(self, table_name, column_name):

    def table_drop_column(self, table_name, column_name):

    def table_drop_constraint(self, table_name, constraint_name):

    def load_column_with_uuids(self, table_name, column_name, force=False):

    def get_all_foreign_keys_to_table(self, table_name, column_name=None):

    def select_into_outfile(self, outfile, table_name, column_names):

    def load_from_infile(self, infile, table_name, column_names):

    def copy_uuid_from_referenced_table_to_foreign_key_table(self, 
                referenced_table_name, referenced_table_column_name, 
                foreign_key_table_name, foreign_key_table_column_name, 
                from_referenced_table_column_name, to_foreign_key_table_column_name):

1. Konvertieren Sie die vorhandene Datenbank in eine neue Datenbank DB_DATA mit UUIDs

Wir müssen eine neue Datenbank mit UUIDs an den richtigen Stellen erstellen. Das bedeutet, dass wir Integer Primary Keys und Integer Foreign Keys in UUIDs konvertieren müssen. Nachdem wir UUID Foreign Keys erstellt haben, können wir die Einschränkungen fallen lassen.
Dies macht es einfach, Spalten umzubenennen.

Das Erstellen einer Spalte UUID Primary Key ist kein großes Problem. Ich erstelle eine CHAR(32)-Spalte 'id_upk_copy' und lade sie mit UUIDs. Um Foreign Keys zu behandeln, können wir die Tabelle INFORMATION_SCHEMA verwenden, um alle Foreign Keys in eine Tabelle zu bekommen. Unten sehen Sie ein Beispiel für die Tabelle Foreign Keys , die sich auf die Spalte id der Tabelle user bezieht. Die Abfrage lautet:

SELECT
  TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
  FROM
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
   WHERE  
    REFERENCED_TABLE_SCHEMA = 'peterspython_dev_existing' 
    AND
    REFERENCED_TABLE_NAME = 'user';

Und das Ergebnis ist:

+---------------------+-------------+----------------------------+-----------------------+------------------------+
| TABLE_NAME          | COLUMN_NAME | CONSTRAINT_NAME            | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+---------------------+-------------+----------------------------+-----------------------+------------------------+
| ...                 | ...         | ...                        |  user                   | id                     |
|  user_mtm_user_group |  user_id     |  user_mtm_user_group_ibfk_1 |  user                   | id                     |
|  user_mtm_user_role  |  user_id     |  user_mtm_user_role_ibfk_1  |  user                   | id                     |
|  user_login          |  user_id     |  user_login_ibfk_1          |  user                   | id                     |
| comment             |  user_id     | comment_ibfk_3             |  user                   | id                     |
| contact_form        |  user_id     | contact_form_ibfk_2        |  user                   | id                     |
| ...                 | ...         | ...                        |  user                   | id                     |
+---------------------+-------------+----------------------------+-----------------------+------------------------+

Das Ergebnis enthält alles, was wir zur Konvertierung von Foreign Keys benötigen. Die Tabellen 'user_mtm_user_group' und 'user_mtm_user_role' sind die Beziehungstabellen many-to-many _role . Was ich tue, ist, für jedes Constraint

  • Erstellen einer neuen Spalte user_id_ufk_copy
  • Kopieren Sie die Spalte UUID aus der Spalte REFERENCED_TABLE id_upk_copy nach TABLE_NAME user_id_ufk_copy

Letzteres geschieht über eine Methode meiner Datenbankklasse:

    def copy_uuid_from_referenced_table_to_foreign_key_table(self, 
                referenced_table_name, referenced_table_column_name, 
                foreign_key_table_name, foreign_key_table_column_name, 
                from_referenced_table_column_name, to_foreign_key_table_column_name):

        # we alias the referenced_table because the key can be in the same table
        query = '''
            UPDATE {} 
              INNER JOIN {} abcde
                ON abcde.{} = {}.{}
              SET {}.{} = abcde.{}'''\
                .format(
                    foreign_key_table_name, 
                    referenced_table_name, 
                    referenced_table_column_name, 
                    foreign_key_table_name, foreign_key_table_column_name,
                    foreign_key_table_name, to_foreign_key_table_column_name,
                    from_referenced_table_column_name)

        cursor = self.conn.cursor()
        self.execute_query(cursor, query)

        return True

Das Skript für die Datenbankkonvertierung sieht wie folgt aus:

# convert integer primary keys and integer foreign keys to uuids
def to_uuid():

    db = Database(
         user=DB_USER, 
        passwd=DB_PASSWORD, 
        host=DB_HOST,
        db=DB_DATABASE_NAME)

    # connect to database

    # get all tables

    # get all tables with integer primary key id

    # create and load new columns: id_ipk_copy, INT(11), and id_upk_copy, CHAR(32)
    for table_name in table_names_ipkid:

        # create new column id_ipk_copy and copy id column into it

        # create new column id_upk_copy and fill with uuids

    # create new foreign key uuid columns in tables
    for table_name_ipkid in table_names_ipkid:
        for row in db.get_all_foreign_keys_to_table(table_name_ipkid, column_name='id'):

            foreign_key_table_name = row['FOREIGN_KEY_TABLE_NAME']
            foreign_key_table_column_name = row['FOREIGN_KEY_TABLE_COLUMN_NAME']

            if not db.table_column_is_integer(foreign_key_table_name, foreign_key_table_column_name):
                # already uuid?
                continue

            referenced_table_name = row['REFERENCED_TABLE_NAME']
            referenced_table_column_name = row['REFERENCED_TABLE_COLUMN_NAME']

            foreign_key_table_new_column_name = foreign_key_table_column_name  +  '_ufk_copy'
            foreign_key_table_new_column_definition = {
                'column_name': foreign_key_table_new_column_name,
                'definition': foreign_key_table_new_column_name  +  ' CHAR(32)',
            }
            db.table_create_column(foreign_key_table_name, foreign_key_table_new_column_definition)

            # copy uuids (id_upk_copy) from referenced_table to new column of foreign_key_table
            db.copy_uuid_from_referenced_table_to_foreign_key_table(
                referenced_table_name, referenced_table_column_name, 
                foreign_key_table_name, foreign_key_table_column_name, 
                'id_upk_copy', foreign_key_table_new_column_name)

    # at this point we have:
    # 
    # - tables with an integer primary key column id:
    #   - have a new column id_ipk_copy with a copy of id
    #   - have a new column id_upk_copy with uuids values 
    # - all tables with foreign keys:
    #   - have an extra foreign key column foreign_key_table_column_name  +  '_uuid'
    # 

    # now we must rearrange

    # first we drop all constraints
    ...

    # 1. Rearrange primary key
    # - drop integer primary key column id
    # - rename column id_upk_copy to id
    ...

    # 2. Rearrange foreign keys
    # for all tables, using column names ending with '_ufk_copy':
    # - drop integer foreign key column 
    # - rename uuid foreign key column to dropped integer foreign key column name
    ...

    # 3. Remove temporary columns
    ...

    # at this point we have:
    # a database that has all the data in the correct columns

2. Generieren Sie eine Datenbank DB_FINAL mit Alembic mit UUID Primary Keys und Foreign Keys

Diese Datenbank hat die UUID Primary Keys, UUID Foreign Keys und Beziehungen. Aber sie hat keine Daten. Ich habe einen neuen Baum oder eine neue Version der Software erstellt. Hier nehme ich alle Änderungen vor, um UUID Primary Keys anstelle von Integer Primary Keys zu behandeln. In dieser neuen Version habe ich die folgenden Änderungen an der Datei models.py vorgenommen:

  • Ersetzte Integer Primary Keys durch UUID Primary Keys
  • Ersetzt Integer Foreign Keys durch UUID Foreign Keys

Der erste Schritt ist die Erstellung einer leeren Datenbank. In mysql habe ich das getan:

drop database  peterspython_dev;
create database  peterspython_dev;

Als nächstes leeren wir das Verzeichnis alembic/versions. Dann führen wir Alembic aus, um eine neue Version zu erstellen:

alembic revision -m "v2.20 first" 
alembic upgrade head

Und tun Sie dies ein zweites Mal, um alle Tabellen und Beziehungen zu generieren:

alembic revision --autogenerate -m "v2.20 2e time"
alembic upgrade head

Ich habe mich noch nicht mit dem Import von GUID() im Prozess Alembic befasst. Bevor ich 'alembic upgrade head' das zweite Mal ausgeführt habe, habe ich die Versionsdatei bearbeitet und die Zeichenfolge ersetzt:

shared.models.GUID()

durch:

sa.CHAR(32)

3. 3. Vergleichen Sie die Datenbanktabellen und Spalten der Datenbank DB_DATA mit den Datenbanktabellen und Spalten der Datenbank DB_FINAL

Dazu habe ich auch ein Skript erstellt. Es ist nicht sehr schwierig, muss aber gemacht werden, unsere Datenbanken müssen identisch sein! Ich vergleiche nicht nur Tabellennamen und Spaltennamen, sondern prüfe auch, ob der DATA_TYPE der Spalten übereinstimmt. Das Vergleichsskript gab mir (Fehler-)Meldungen wie

db1 column content_item_translation.intro data_type text not same as db2 data_type longtext
db1 column content_item_translation.summary data_type text not same as db2 data_type longtext
db1 column mail_smtp_message.body_text data_type text not same as db2 data_type mediumtext
db1 column contact_form.message data_type text not same as db2 data_type mediumtext

Wahrscheinlich habe ich sie von Hand geändert, weil ich gerade mit SQLAlchemy angefangen habe. Ich habe den Datentyp SQLAlchemy Text verwendet und mehr Platz benötigt. Wie auch immer, es wird Zeit, dies richtig zu machen.

Leider ist der einzige Weg, die MySQL Dialekt-Datentypen MEDIUMTEXT und LONGTEXT zu verwenden, was mich einen weiteren Schritt weg von der Unterstützung beider MariaDb / MySQL und PostgreSQL bringt. Aber immerhin sind jetzt beide Datenbanken identisch!

4. Kopieren Sie die Datenbanktabellendaten von DB_DATA in die Datenbanktabellen von DB_FINAL

Natürlich bin ich hier auf ein Problem gestoßen. NULL -Werte der DB_DATA-Datenbank waren keine NULL -Werte in der DB_FINAL-Datenbank. Der Grund dafür war, dass ich ein eigenes Feldtrennzeichen, ein Zeilentrennzeichen, definiert hatte. Als ich im Internet darüber las, schien die Lösung einfach: Verwenden Sie die MariaDb / MySQL -Standardwerte. Dies bedeutet Export durch:

SELECT  <column_names_list> FROM <table_name> INTO OUTFILE <outfile_infile>

Und dann durch Importieren:

LOAD DATA LOCAL INFILE <outfile_infile> INTO TABLE <table_name> <column_names_list>

Jetzt werden die NULL -Werte korrekt übertragen. Ein weiteres Problem, auf das Sie stoßen könnten, ist die OUTFILE. Wenn diese Datei existiert, erhalten Sie einen Fehler, also stellen Sie sicher, dass Sie diese Dateien vor einem neuen Lauf entfernen.

Dinge, die schief gelaufen sind

Datenbank hat nicht mehr geantwortet

Vielleicht ist all dieses Hinzufügen und Entfernen von Spalten etwas, das etwas durcheinander bringt. Aber wahrscheinlich war etwas in meinem Code falsch. In der ersten Version habe ich vergessen, die Verbindung zu schließen. Als ich in mysql ging und die Datenbank löschen wollte, bekam ich diese Meldung:

MySQL: Error dropping database (errno 13; errno 17; errno 39)

Das bedeutet, dass es eine oder mehrere Dateien gibt, die vom Datenbankserver gesperrt sind oder was auch immer. Die Lösung ist, in dieses Datenbankverzeichnis auf Ihrem Dateisystem zu gehen und diese Dateien z.B. manuell zu entfernen:

sudo rm /var/lib/mysql/your_database_name/category_translation.ibd

Seien Sie hier vorsichtig! Nachdem ich die Verbindung im Skript geschlossen hatte, sah ich diese Meldung nicht mehr, aber ich dachte, ich gebe sie einfach weiter.

UUID Objekt hat kein Attribut 'übersetzen'.

Beim Testen des Kontaktformulars erhielt ich die Nachricht:

AttributeError: 'UUID' object has no attribute 'translate' when using backend-agnostic  GUID type

Warum? Das passierte, als ich zuerst das Objekt mail_message committed habe und dann diese mail_message.id als Foreign Key beim Hinzufügen von Datensätzen zur Tabelle mail_message_to benutzt habe.Nach dem Commit, type(item.id) = <class 'uuid.UUID'>, item.id = dcd0fd6b-cd0f-44b0-92c6-a5f08c0d784f konnte sie nicht in das ForeignKey-Feld geschrieben werden.

Das Problem: Ich hatte die Integer Primary Keys in UUID Primary Keys konvertiert, tat dies aber nicht für die Foreign Keys ... uh oh ... dummes Ich ... Die Lösung war, CHAR(32) in der models.py für GUID() zu ersetzen:

    ... = Column(CHAR(32), ForeignKey(...

Muß geändert werden in:

    ... = Column(GUID(), ForeignKey(...

Es war nicht notwendig, Alembic nach dieser Änderung auszuführen.

Fehlende Foreign Keys hinzugefügt

An (mindestens, bisher) drei Stellen habe ich gerade ein Integer zu einer Tabelle hinzugefügt, wo ich ein Foreign Key hätte hinzufügen sollen. Zwei davon waren in ContentItem und ContentItemTranslation klassenlos. Ich habe sie verwendet, um das übergeordnete Element zu markieren. Nachdem ich ein ContentItem oder ContentItemTranslation-Objekt bearbeitet habe, klicke ich auf die Schaltfläche Speichern. Dann wird eine Kopie des aktuellen Datensatzes erstellt, mit einer parent_id des ursprünglichen Datensatzes. Um dies zu beheben, ging ich zur ursprünglichen Datenbank zurück, fügte Foreign Keys hinzu und ließ den Prozess erneut laufen.

Raw SQL

Obwohl ich die meisten SLQAlchemy ORM -Abfragen verwende, verwende ich auch SQLAlchemy Raw SQL. Es stellte sich heraus, dass einige dieser Abfragen fehlschlugen, weil nach der Konvertierung die ids nicht zitiert wurden.

Flask routes

Natürlich gibt es bei vielen Routen ein Problem. In Flask können Sie einen Datentyp für die Parameter der Sichtfunktion angeben, und in den meisten Fällen waren es Integer. Jetzt müssen sie Zeichenketten sein. Beispiel:

@pages_blueprint.route('/category', defaults={'category_id': 0})
@pages_blueprint.route('/category/<int:category_id>')
def category(category_id):
    ...

Muss geändert werden in:

@pages_blueprint.route('/category', defaults={'category_id': ''})
@pages_blueprint.route('/category/<category_id>')
def category(category_id):
    ...

Integer Prüfung

An einigen Stellen überprüfe ich explizit, ob ein Wert ein Integer ist. Das bin nur ich im paranoiden Modus. Diese Website verwendet zum Beispiel Flask-Login, und in create_app() haben wir den user_loader:

    @login_manager.user_loader
    def load_user(user_id):
        ...
        return g.db_session.query(User).get(user_id)

Ich musste die Überprüfung entfernen, ob die user_id wirklich eine Integer ist.

Sortierung

Ja, natürlich habe ich die ID Integer Primary Key in einer Reihe von Fällen zum Sortieren der Datensätze verwendet. Mit UUIDs kommt diese Sortierung durcheinander. Dies wurde durch die Verwendung des (Datensatz) created_on-Zeitstempels behoben. Ich hatte diese Spalte created_on bereits in jeder Tabelle.

WTForms Auswahlfeld

In den meisten Formularen mit Selects verwende ich (id, name) Tupel. Aber die id ist nicht mehr ein Integer. Die Lösung besteht darin, den Parameter coerce=int zu entfernen. Beispiel:

class ContentItemAssignAuthorsForm(FlaskForm):

    author_ids = MultiCheckboxField(_('Select authors for content item'),  coerce=int)
    submit = SubmitField(_l('Assign'))

Muss geändert werden in:

class ContentItemAssignAuthorsForm(FlaskForm):

    author_ids = MultiCheckboxField(_('Select authors for content item'))
    submit = SubmitField(_l('Assign'))

Zusammenfassung

Dies war das erste Mal, dass ich Python pymysql mit hauptsächlich MariaDb / MySQL Wartungsbefehlen verwendete, wie z.B. Spalteninformationen abrufen, Eingrenzungen, Hinzufügen und Entfernen von Spalten, Speichern und Laden von Daten. Irgendwo während der Konvertierung hatte ich ernsthafte Schwierigkeiten erwartet, aber dies ist nicht eingetreten.

Die Verwendung von UUIDs kann verwirrend sein. Ist es zu einem bestimmten Zeitpunkt ein UUID -Objekt oder eine Zeichenfolge? Ich verwende das Rezept Backend-agnostic GUID Type , siehe Links unten. Ich denke, ich würde es vorziehen, dass UUIDs überall Zeichenketten sind, schließlich brauchen wir das UUID -Objekt nur, wenn wir ein Primary Key oder Foreign Key einfügen.

Links / Impressum

AttributeError: 'UUID' object has no attribute 'replace' when using backend-agnostic GUID type
https://stackoverflow.com/questions/47429929/attributeerror-uuid-object-has-no-attribute-replace-when-using-backend-agno

Backend-agnostic GUID Type
https://docs.sqlalchemy.org/en/13/core/custom_types.html?highlight=guid#backend-agnostic-guid-type

How can I use UUIDs in SQLAlchemy?
https://stackoverflow.com/questions/183042/how-can-i-use-uuids-in-sqlalchemy

How do I see all foreign keys to a table or column?
https://stackoverflow.com/questions/201621/how-do-i-see-all-foreign-keys-to-a-table-or-column

MySQL: Error dropping database (errno 13; errno 17; errno 39)
https://stackoverflow.com/questions/12196996/mysql-error-dropping-database-errno-13-errno-17-errno-39

Replace integer id field with uuid
https://stackoverflow.com/questions/42674931/replace-integer-id-field-with-uuid

SQLAlchemy one to one relationship get parent and add child
https://stackoverflow.com/questions/59227673/sqlalchemy-one-to-one-relationship-get-parent-and-add-child

Using custom UUID Type from SQLAlchemy
https://stackoverflow.com/questions/47275130/using-custom-uuid-type-from-sqlalchemy

What column type does SQLAlchemy use for “Text” on MySQL?
https://stackoverflow.com/questions/47644739/what-column-type-does-sqlalchemy-use-for-text-on-mysql

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.