[PYTHON] Définition de table dans SQL Alchemy

introduction

Ici, nous résumons la méthode de définition d'une table à l'aide de SQLAlchemy. ** Ci-après, le dialecte (type DB) est mysql. ** **

Spécification du jeu de caractères

Il peut être spécifié par mysql_charset de __table_args__. Par exemple, si vous souhaitez spécifier charset comme utf8mb4

class User(Base):
    __table_args__=({"mysql_charset": "utf8mb4"})

Et c'est suffisant. En passant, si vous spécifiez utf8, un avertissement sera émis comme suit.

Warning: (3719, "'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.")

ROW_FORMAT=DYNAMIC La longueur maximale de la clé de l'index est de 3072 octets, mais si la version mysql est 5.6 ou antérieure, la valeur par défaut est de 767 octets. Par conséquent, si vous utilisez la version 5.6 ou antérieure et écrivez comme ci-dessous, une erreur se produira.

class User(Base):
    __table_args__=({"mysql_charset": "utf8mb4"})
    a=Column(String(255), unique=True)

Cela est dû au fait que utf8mb4 est spécifié, donc 255 * 4 = 1020 (octet), ce qui dépasse 767 octets. (À propos, dans le cas de utf8mb3, 255 * 3 = 765 (octet) est correct) Par conséquent, en définissant ROW_FORMAT = DYNAMIC, la longueur de clé maximale de l'index devient 3072 octets. Vous pouvez écrire comme suit.

class User(Base):
    __table_args__=({"mysql_charset": "utf8mb4", "mysql_row_format": "DYNAMIC"})
    a=Column(String(255), unique=True)

Dans 5.7 et versions ultérieures, par défaut, ROW_FORMAT = DYNAMIC.

Spécification du moteur DB

Il peut être spécifié par mysql_engine de __table_args__. Par exemple, si vous souhaitez spécifier le moteur DB pour InnoDB,

class User(Base):
    __table_args__=({"mysql_engine": "InnoDB"})

Et c'est suffisant. Data Types En tant que types génériques de SQLAlchemy, vous pouvez l'importer et l'utiliser avec from sqlalchemy.types import hogehoge. Par exemple, il y a les suivants.

from sqlalchemy.types import Float
from sqlalchemy.types import Integer
from sqlalchemy.types import String
from sqlalchemy.types import DateTime

Pour ces types génériques, SQL Alchemy sélectionnera les types de données appropriés en fonction du type de base de données à utiliser lorsque CREATE TABLE. Documents officiels (types génériques)

Cependant, par exemple, unsigned int, tiny int et timestamp type ne sont pas inclus dans les types génériques. Dans ce cas, utilisez from sqlalchemy.dialects.mysql import fugafuga.

from sqlalchemy.dialects.mysql import INTEGER as Integer
from sqlalchemy.dialects.mysql import TINYINT as Tinyint
from sqlalchemy.dialects.mysql import TIMESTAMP as Timestamp

class User(Base):
    a=Column(Integer(unsigned=True)) #a est un entier non signé
    b=Column(Tinyint(1)) #b est minuscule int(1)
    c=Column(Timestamp) #c est horodatage

(Documentation officielle (types de données MySQL)) Primary Key Vous pouvez définir primary_key = True dans la colonne.

class User(Base):
    id=Column(Integer, primary_key=True) #id est la clé primaire

Si vous voulez créer une clé primaire composée, définissez primary_key = True pour les deux.

class User(Base):
    # id_1 et id_2 est une clé primaire composite
    id_1=Column(Integer, primary_key=True)
    id_2=Column(Integer, primary_key=True)

Auto Increment Définissez ʻautoincrement = True` dans la colonne.

class User(Base):
    id=Column(Integer, autoincrement=True) #id est l'incrémentation automatique

Valeur par défaut

Définissez server_default = hogehoge dans la colonne. Notez que vous devez passer string ou text () à server_default.

from sqlalchemy.dialects.mysql import TINYINT as Tinyint

class User(Base):
    bool=Column(Tinyint(1), server_default="1") #Passing string

Si celui qui est passé est une chaîne, il se transforme en guillemets simples, et s'il s'agit de texte (), il change sans guillemets.

x=Column(String, server_default="val")
x STRING DEFAULT 'val' #Changer en guillemets simples
y=Column(DateTime, server_default=text("NOW()")
y DATETIME DEFAULT NOW() #Pas de devis

Documentation officielle (server_default)

Si vous voulez que la valeur par défaut soit current_timestamp, définissez from sqlalchemy.sql.functions import current_timestamp et server_default = current_timestamp ().

from sqlalchemy.dialects.mysql import TIMESTAMP as Timestamp
from sqlalchemy.sql.functions import current_timestamp

class User(Base):
    created_at=Column(Timestamp, server_default=current_timestamp())

Documentation officielle (current_timestamp) )

Mettre à jour la valeur

Il n'est pas reflété même si server_onupdate = hogehoge est défini dans Column. Par conséquent, si vous souhaitez définir DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, utilisez server_default.

from sqlalchemy.dialects.mysql import TIMESTAMP as Timestamp
from sqlalchemy.sql.expression import text

class User(Base):
    created_at=Column(Timestamp, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))

Et c'est suffisant. How to set DEFAULT ON UPDATE CURRENT_TIMESTAMP in mysql with sqlalchemy?

Contrainte nulle

Vous pouvez définir nullable = False dans la colonne.

class User(Base):
    a=Column(Integer, nullable=False) #a est un entier et non nul

Contrainte unique

Si vous souhaitez mettre une contrainte Unique sur une seule colonne, vous pouvez définir ʻunique = True` dans Column.

class User(Base):
    a=Column(Integer, unique=True) #a est int et unique

Si vous voulez mettre des contraintes uniques sur plusieurs colonnes, vous devez écrire sqlalchemy.schema.UniqueConstraint dans __table_args__.

from sqlalchemy.schema import UniqueConstraint

class User(Base):
    #(a, b)En unique
    __table_args__=(UniqueConstraint("a", "b", name="uq_user_00"))
    a=Column(Integer)
    b=Column(Integer)

Bien sûr, vous pouvez utiliser sqlalchemy.schema.UniqueConstraint même si vous souhaitez mettre une contrainte unique sur une seule colonne.

Contrainte de clé étrangère

Comment utiliser

Dans Colonne, définissez sqlalchemy.schema.ForeignKey. Fondamentalement, sqlalchemy.schema.ForeignKey (" {nom_table}. {Nom_colonne} ", name =" {nom_constraint_clé_tranger} ")

from sqlalchemy.schema import ForeignKey

class User(Base):
    __tablename__="users"
    id=Column(Integer, nullable=False, autoincrement=True, primary_key=True)
    name=Column(String(255), nullable=False)

class TestResult(Base):
    __tablename__="test_results"
    id=Column(Integer, nullable=False, autoincrement=True, primary_key=True)
    value=Column(Integer, nullable=False)
    user_id=Column(Integer, ForeignKey("users.id", name="fk_test_results_00", nullable=False)) #L'identifiant de la table des utilisateurs est ForeignKey

Si vous voulez définir OnUpdate ou OnDelete, ajoutez ʻonupdate = "CASCADE" ou ʻondelete =" CASCADE " dans sqlalchemy.schema.ForeignKey (). Document officiel (ForeignKey.params.column) En guise de mise en garde, parmi les options à écrire dans Column, DataType et ForeignKey doivent être écrites avant, et celles passées avec "=" doivent être écrites après. relation En créant une relation, vous pouvez suivre la clé étrangère sans la rejoindre explicitement. La relation peut être définie sur `hoge = sqlalchemy.orm.relationship (" {nom de classe} ", uselist = {True ou False}) ʻ comme dans la définition de colonne. Uselist est défini sur True s'il existe plusieurs données liées pour une seule donnée et sur False s'il n'y en a qu'une. Dans ce qui suit, User: TestResult = one: many.

from sqlalchemy.schema import ForeignKey
from sqlalchemy.orm import relationship

class User(Base):
    __tablename__="users"
    id=Column(Integer, nullable=False, autoincrement=True, primary_key=True)
    name=Column(String(255), nullable=False)
    test_result=relationship("TestResult", uselist=True) #Créer une relation entre User et TestResult,Plusieurs données à lier

class TestResult(Base):
    __tablename__="test_results"
    id=Column(Integer, nullable=False, autoincrement=True, primary_key=True)
    value=Column(Integer, nullable=False)
    user_id=Column(Integer, ForeignKey("users.id", name="fk_test_results_00", nullable=False)) #L'identifiant de la table des utilisateurs est ForeignKey
    user=relationship("User") #Créer une relation entre TestResult et User,Une seule donnée à connecter

En définissant une relation comme celle-ci, vous pouvez appeler une instance de chaque classe comme suit.


test_result_1=session.query(TestResult).filter(TestResult.id==1).one() # test_Dans le tableau des résultats, récupérez celui avec l'ID 1.
user_of_test_result_1=test_result_1.user #test_result_1 utilisateur_Vous pouvez récupérer une instance de la classe User dont l'ID correspond à l'ID.
# user_of_test_result_1=User

user_1=session.query(User).filter(User.id==1).one() #Dans le tableau des utilisateurs, récupérez celui avec l'ID 1.
test_results_of_user_1=user_1.test_result # user_Identifiant utilisateur correspondant sur 1_Vous pouvez récupérer une liste d'instances de la classe TestResult avec id
# test_results_of_user_1=[TestResult, TestResult, ...]

L'une des options est paresseuse, et ce paramètre vous permet de définir le moment auquel la table à laquelle la relation est définie est lue. Par défaut, il est chargé lors de son appel.

lazy = "select" (idem pour "True")

Identique à la valeur par défaut. Il est lu lorsque la destination de la relation est appelée.

test_result_1=session.query(TestResult).filter(TestResult.id==1).one() #L'utilisateur n'est pas encore chargé ici.
user_of_test_result_1=test_result_1.user #L'utilisateur est chargé ici

lazy="immediate" Lorsque la source de la relation est appelée, la destination de la relation est également appelée. La requête est émise séparément pour appeler la source et la destination de la relation.

test_result_1=session.query(TestResult).filter(TestResult.id==1).one() #L'utilisateur est également chargé ici

lazy = "join" (idem pour "False")

Lorsque la source de la relation est appelée, la destination de la relation est également appelée. La différence avec lazy = "immédiat" est le nombre de fois où la requête est émise. Puisqu'elle est appelée par jointure, la requête ne peut être émise qu'une seule fois. Document officiel (relation)

Les références

Cet article a été rédigé en référence aux informations suivantes. ・ Document officiel

Recommended Posts

Définition de table dans SQL Alchemy
Conseils de définition de table sqlalchemy
OperationalError dans SQLAlchemy + SQLite3
Obtenez la table dynamiquement avec sqlalchemy
Renommer les colonnes de table dans Django3
Sortie de la structure de table dans Django
Type de gain de temps avec SQLAlchemy
Générer des définitions de table SQL Alchemy à partir d'un serveur MySQL existant à l'aide de sqlacodegen
Mettre en œuvre un test piloté par table en Java
Comment gérer une session dans SQLAlchemy
Définition du type d'argument de fonction en python
(sqlalchemy) Afficher le texte dans le champ de sélection
Traitement des insertions de table DB à l'aide de sqlalchemy
sqlalchemy
Ecrire une courte définition de propriété en Python
Associez l'ensemble de tables dans les modèles de python.py
Comment afficher la table quatre-vingt-dix-neuf en python
Code requis pour la conversion d'API dans sqlalchemy