我有一个已经使用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
如何使匹配符合上面所需的输出(至少就参数而言)?