如何在 sqlalchemy 引擎 INSERT 语句的一个字段中指定默认值?

问题描述 投票:0回答:1

我使用原始 SQLAlchemy

engine.execute()
调用来执行 INSERT 语句,例如

engine = create_engine("mysql+pymysql://...")
engine.execute("INSERT INTO table VALUES (%s, %s, %s %s)", v1, v2, v3, v4)

现在假设第三列定义为

varchar(10) NOT NULL DEFAULT 'foo'
我想指定我想使用该默认值。

MySQL 为此有 DEFAULT 关键字,但我如何告诉 SQLAlchemy 为其中一个变量生成 DEFAULT 关键字?

我想象类似的事情

engine.execute("INSERT INTO table VALUES (%s, %s, %s %s)", v1, v2, default, v4)

但是我在这里需要

default
什么呢? (SQLAlchemy 是否支持这一点?)

(我不能使用

None
,因为它会被转换为 NULL 并违反 NOT NULL 约束。(在 MySQL 8 上)

(我可以省略这样的列

engine.execute("INSERT INTO table (col1, col2, col4) VALUES (%s, %s, %s)", v1, v2, v4)

但我发现生成列名称列表是不可取的,我更喜欢使用 DEFAULT 关键字。)

python mysql sqlalchemy
1个回答
0
投票

这可以使用 SQLAlchemy 核心来实现,方法是传递名为“default”的列对象(或数据库用来表示默认值的任何内容),并将

is_literal
标志设置为
True
。这将导致“DEFAULT”被插入到不带引号的查询中。

import sqlalchemy as sa

engine = sa.create_engine('mysql+pymysql://root:@localhost/test', echo=True)

tbl = sa.Table(
    'so75659729',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('col_a', sa.String(32), server_default='foo', nullable=False),
    sa.Column('col_b', sa.Integer, server_default='1', nullable=False),
    sa.Column('col_c', sa.Integer, nullable=False),
)

tbl.drop(engine, checkfirst=True)
tbl.create(engine)

# Check that the dialect (probably the database) supports "DEFAULT" as a concept.
assert engine.dialect.supports_default_metavalue
# Get the value that the dialect uses for "DEFAULT".
default_token = engine.dialect.default_metavalue_token
# This is the parameter value.
default = sa.column(default_token, is_literal=True)

with engine.begin() as conn:
    stmt = tbl.insert()
    values = {
        'id': default,
        'col_a': default,
        'col_b': default,
        'col_c': 42,
    }

    conn.execute(stmt.values(**values))

这是参数绑定之前已编译的 SQL:

INSERT INTO so75659729 (id, col_a, col_b, col_c) VALUES (DEFAULT, DEFAULT, DEFAULT, %(col_c)s)

使用文本语句实现此目标更加困难,因为参数在绑定时会被引用。一种解决方案是这个答案中演示的技术 - 在绑定参数之前手动替换占位符。

© www.soinside.com 2019 - 2024. All rights reserved.