这是我的疑问:
QUERY = """
UPDATE my_table
SET
my_prop=:foo
WHERE hello='world'
"""
我执行这样的声明:
sqlalchemy_engine.execute(QUERY, foo='bar')
当我这样做时,我收到以下错误:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) syntax error at or near ":"
UPDATE my_table\n SET\n my_prop.foo = :foo
^
在将值传递给SQL Alchemy执行之前,我从未遇到过问题。我做错了什么?
答案 0 :(得分:6)
在将值传递给SQLAlchemy执行之前,我从未遇到过问题。我做错了什么?
您之前可能一直在使用Session.execute()
,而不是Engine.execute()
。前者使用text()
构造自动包装SQL字符串,或者至少它的行为如此,这是关键所在;它是text()
,它为DB-API驱动程序提供绑定参数/占位符的独立处理。没有它,您可以随心所欲地使用DB-API as noted by Craig Ringer in their answer。
因此,为了直接使用:name
样式占位符和引擎,只需使用text()
包装您的查询:
sqlalchemy_engine.execute(text(QUERY), foo='bar')
请注意,SQLAlchemy应用程序的引擎is the starting point和所有内容都构建在它之上,因此这可能是不进行自动换行的原因,而另一个则是。会话是更高级别的抽象。
答案 1 :(得分:2)
psycopg2
不支持:named
个参数。 The Python DB-API spec允许使用:named
的{{1}}参数,但paramstyle = 'named'
使用:
psycopg2
as documented in the psycopg2
docs
遗憾的是,Python的DB-API允许各种参数样式,但事实就是如此。某些驱动程序似乎支持将>>> import psycopg2
>>> psycopg2.paramstyle
'pyformat'
更改为DB-API扩展。但它看起来不像paramstyle
就是其中之一:
psycopg2
因此,如果您之前看到>>> psycopg2.paramstyle = 'named'
>>> psycopg2.paramstyle
'named'
>>> cur.execute("SELECT :a, :b, :c", {'a': 1, 'b': 2, 'c': 3})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
psycopg2.ProgrammingError: syntax error at or near ":"
LINE 1: SELECT :a, :b, :c
>>> conn.rollback()
>>> cur.execute("SELECT %(a)s, %(b)s, %(c)s", {'a': 1, 'b': 2, 'c': 3})
>>>
样式参数有效,那么因为某些外层(可能是SQLAlchemy)正在为您调整查询。快速查看SQLAlchemy docs表明it may do just that。
猜测,您正在使用当前代码绕过SQLAlchemy方言图层。但我真的不懂SQLAlchemy ......