J'ajoute une colonne à une table existante. Cette nouvelle colonne est nullable=False
.
op.add_column('mytable', sa.Column('mycolumn', sa.String(), nullable=False))
Lorsque je lance la migration, il se plaint:
sqlalchemy.exc.IntegrityError: column "mycolumn" contains null values
C’est parce que vos données existantes n’ont aucune valeur pour cette nouvelle colonne, c’est-à-dire null
. Causant ainsi ladite erreur. Lorsque vous ajoutez une colonne non Nullable, vous devez décider quelle valeur attribuer aux données existantes.
Bon, les données existantes devraient alors avoir "lorem ipsum" pour cette nouvelle colonne. Mais comment je le fais? Je ne peux pas mettre à jour parce que la colonne n'est pas encore là.
Utilisez le server_default
arg:
op.add_column('mytable', sa.Column(
'mycolumn',
sa.String(),
nullable=False,
server_default='lorem ipsum', # <--- add this
))
Mais, mais je ne veux pas qu'il ait la valeur par défaut
Déposez-le ensuite en utilisant op.alter_column('mytable', 'mycolumn', server_default=None)
Par exemple. Votre fonction upgrade()
serait:
def upgrade():
op.add_column('mytable', sa.Column('mycolumn', sa.String(), nullable=False, server_default='lorem ipsum'))
op.alter_column('mytable', 'mycolumn', server_default=None)
Une alternative à la réponse de @ Ron est de faire le contraire et de modifier les données avant ajouter la contrainte:
def upgrade():
op.add_column('my_table', sa.Column('my_column', sa.String()))
op.execute('UPDATE my_table SET my_column=my_other_column')
op.alter_column('my_table', 'my_column', nullable=False)
Cela semble plus propre et plus puissant pour moi, mais vous écrivez SQL :-).
Cela vous indique - à juste titre - qu'il existe (ou existera) des valeurs NULL existantes dans la base de données pour cette colonne. La réponse consiste à modifier le fichier de migration pour mettre à jour la colonne avant de modifier la définition de la colonne:
from sqlalchemy.sql import table, column
def upgrade():
op.add_column('role', sa.Column('role_name', sa.String(length=30), nullable=True))
role = table('role', column('role_name'))
op.execute(role.update().values(role_name=''))
op.alter_column('role', 'role_name', nullable=False)