Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Alembic升级脚本中执行插入和更新?_Python_Sqlalchemy_Alembic - Fatal编程技术网

Python 如何在Alembic升级脚本中执行插入和更新?

Python 如何在Alembic升级脚本中执行插入和更新?,python,sqlalchemy,alembic,Python,Sqlalchemy,Alembic,我需要在Alembic升级期间更改数据 我目前在第一版中有一个“玩家”表: def upgrade(): op.create_table('player', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.Unicode(length=200), nullable=False), sa.Column('position', sa.Unicode(leng

我需要在Alembic升级期间更改数据

我目前在第一版中有一个“玩家”表:

def upgrade():
    op.create_table('player',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.Unicode(length=200), nullable=False),
        sa.Column('position', sa.Unicode(length=200), nullable=True),
        sa.Column('team', sa.Unicode(length=100), nullable=True)
        sa.PrimaryKeyConstraint('id')
    )
def upgrade():
    op.create_table('teams',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.String(length=80), nullable=False)
    )
    op.add_column('players', sa.Column('team_id', sa.Integer(), nullable=False))
我想介绍一个“团队”表。我创建了第二个修订版:

def upgrade():
    op.create_table('player',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.Unicode(length=200), nullable=False),
        sa.Column('position', sa.Unicode(length=200), nullable=True),
        sa.Column('team', sa.Unicode(length=100), nullable=True)
        sa.PrimaryKeyConstraint('id')
    )
def upgrade():
    op.create_table('teams',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.String(length=80), nullable=False)
    )
    op.add_column('players', sa.Column('team_id', sa.Integer(), nullable=False))
我希望第二次迁移还添加以下数据:

  • 填充团队表:

    INSERT INTO teams (name) SELECT DISTINCT team FROM players;
    
  • 根据players.team name更新players.team\u id:

    UPDATE players AS p JOIN teams AS t SET p.team_id = t.id WHERE p.team = t.name;
    

  • 如何在升级脚本中执行插入和更新?

    您要求的是数据迁移,而不是Alembic文档中最常见的模式迁移

    这个答案假设您正在使用声明性(而不是类映射器表或核心)来定义模型。将其应用于其他形式应该相对简单

    注意,Alembic提供了一些基本的数据函数:和。如果操作非常简单,请使用这些。如果迁移需要关系或其他复杂的交互,我更喜欢使用模型和会话的全部功能,如下所述

    下面是一个迁移脚本示例,它设置了一些用于在会话中操作数据的声明性模型。重点是:

  • 定义所需的基本模型以及所需的列。您不需要每一列,只需要主键和要使用的列

  • 在升级功能中,使用获取当前连接,并与其建立会话

    • 或者使用
      bind.execute()
      使用SQLAlchemy的较低级别直接编写SQL查询。这对于简单的迁移非常有用
  • 像在应用程序中一样使用模型和会话


  • 迁移定义了单独的模型,因为代码中的模型表示数据库的当前状态,而迁移表示过程中的步骤。您的数据库可能处于该路径上的任何状态,因此模型可能尚未与数据库同步。除非您非常小心,否则直接使用真实模型将导致缺少列、无效数据等问题。更清楚的是,明确说明您将在迁移中使用哪些列和模型。

    我建议使用特别表使用SQLAlchemy核心语句,因为它允许使用不可知SQL和python编写,并且是自包含的。SQLAlchemy Core是迁移脚本的最佳选择

    以下是该概念的一个示例:

    from sqlalchemy.sql import table, column
    from sqlalchemy import String
    from alembic import op
    
    account = table('account',
        column('name', String)
    )
    op.execute(
        account.update().\\
        where(account.c.name==op.inline_literal('account 1')).\\
            values({'name':op.inline_literal('account 2')})
            )
    
    # If insert is required
    from sqlalchemy.sql import insert
    from sqlalchemy import orm
    
    session = orm.Session(bind=bind)
    bind = op.get_bind()
    
    data = {
        "name": "John",
    }
    ret = session.execute(insert(account).values(data))
    # for use in other insert calls
    account_id = ret.lastrowid
    

    您还可以使用direct SQL see(),如下例所示:

    from alembic import op
    
    # revision identifiers, used by Alembic.
    revision = '1ce7873ac4ced2'
    down_revision = '1cea0ac4ced2'
    branch_labels = None
    depends_on = None
    
    
    def upgrade():
        # ### commands made by andrew ###
        op.execute('UPDATE STOCK SET IN_STOCK = -1 WHERE IN_STOCK IS NULL')
        # ### end Alembic commands ###
    
    
    def downgrade():
        # ### commands auto generated by Alembic - please adjust! ###
        pass
        # ### end Alembic commands ###
    

    如果我一直想从外部文件读取SQL语句,然后将其传递到
    upgrade()
    中的
    op.execute
    ,有没有办法提供一个默认模板供
    alembic revision
    命令使用(生成的
    .py
    文件的默认主体)?我不知道@Quentin。这是一个有趣的想法。