使用替换参数生成sqlalchemy查询

时间:2016-11-10 17:22:19

标签: python sqlalchemy bulkinsert

我有一个已经使用sqlalchemy的新应用程序,因此已经有了sqlalchemy表定义。

我想使用sqlalchemy生成一个SQL脚本来从旧应用程序迁移数据。所以我想生成一个像这样的PostgreSQL插入语句:

INSERT INTO widgets (public_identifier, name, spam) VALUES
('006b92ce-a767-11e6-b47e-f30689ab4e07', 'joe', 'spam'),
('1b74c518-a767-11e6-a2df-abc58de4160b', 'adam', 'ham'),
...
ON CONFLICT ON CONSTRAINT widgets_public_identifier_key DO NOTHING;

我想将它写入一个大文件,以便在导入新应用程序的数据库之前可以检查它是否正确/移动到另一台机器。该文件不会太大,可能是10000行(如果它是COPY而不是INSERT INTO我认为没有坏处。)

在任何人'回答'之前,通过解释一个人通常不想以这种方式文本替换参数值(例如出于安全性和正确性原因):这是真的,但不适用于这种情况:这里,生成的SQL文件在被执行之前必须由人进行检查。

我遇到的问题是我不知道如何告诉sqlalchemy将参数值替换为生成的SQL而不是生成%s替换参数。显然我可以手动生成SQL,但是因为这种事情并不常见,并且使用sqlalchemy似乎应该很方便,我想这样做。

(我也不知道如何在一个语句中插入多行,也不知道如何最好地从生成的INSERT语句中省略id字段,但这不是这个问题的重点。)

这是我到目前为止所拥有的:

from sqlalchemy import MetaData, Table, Column, String, Integer
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Insert
from sqlalchemy.dialects import postgresql


metadata = MetaData()

table = Table(
    'widgets',
    metadata,
    Column('id', Integer, autoincrement=True, primary_key=True),
    Column('public_identifier', String(255), unique=True, nullable=False),
    Column('name', String(255), nullable=True),
    Column('spam', String(255), nullable=True),
)


@compiles(Insert)
def prefix_inserts(insert, compiler, **kw):
    return compiler.visit_insert(insert, **kw) + " ON CONFLICT ON CONSTRAINT widgets_public_identifier_key DO NOTHING"


q = table.insert()
print str(q.compile(dialect=postgresql.dialect()))

生成此输出:

INSERT INTO widgets (id, public_identifier, name, spam) VALUES (%(id)s, %(public_identifier)s, %(name)s, %(spam)s) ON CONFLICT ON CONSTRAINT widgets_public_identifier_key DO NOTHING

如何使匹配符合上面所需的输出(至少就参数而言)?

0 个答案:

没有答案