Sqlalchemy - 如何从带有绑定参数的insert(),update()语句中获取原始sql?

时间:2015-06-23 00:43:28

标签: python orm sqlalchemy

示例:

from sqlalchemy.dialects import mysql
from sqlalchemy import Integer, Column, update, insert
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = "test"

    a = Column(Integer, primary_key=True)
    b = Column(Integer)


update_stmt = update(Test).where(Test.a == 1).values(b=2)
print update_stmt.compile(dialect=mysql.dialect(), compile_kwargs=  {"literal_binds": True})

insert_stmt = insert(Test).values(a=1, b=1)
print insert_stmt.compile(dialect=mysql.dialect())

结果是:

UPDATE test SET b=%s WHERE test.a = %s
INSERT INTO test (a, b) VALUES (%s, %s)

问题是如何让sqlalchemy像这样生成smth:

UPDATE test SET b=2 WHERE test.a = 1
INSERT INTO test (a, b) VALUES (1, 1)

对于selectcompile_kwargs= {"literal_binds": True}解决了该问题,但它不适用于updateinsert

感谢您的帮助。

P.S。我需要从orm构建原始的sql查询,所以欢迎任何其他有简单生成原始sql的方法的建议。

2 个答案:

答案 0 :(得分:2)

使用 compile_kwargs 的解决方案 - 正如其他地方所宣传的那样 - 只能部分工作,即对于像Integer或String这样的简单数据类型(从SQLAlchemy v1.1.6开始)。

+-------------+----------------+--------+---------------+----------+
| SQA version | compile_kwargs | SELECT | INSERT/UPDATE | datetime |
+=============+================+========+===============+==========+
| 0.7.9       |       --       |    --  |        --     |    --    |
+-------------+----------------+--------+---------------+----------+
| 0.9.4       |       √        |   1/2  |        --     |    --    |
+-------------+----------------+--------+---------------+----------+
| 1.0.11      |       √        |    √   |        --     |    --    |
+-------------+----------------+--------+---------------+----------+
| 1.0.13      |       √        |    √   |       1/2     |    --    |
+-------------+----------------+--------+---------------+----------+
| 1.1.6       |       √        |    √   |       1/2     |    --    |
+-------------+----------------+--------+---------------+----------+

根据要求和限制,以下解决方案可以胜任:

  • 如果您可以使用SQLAlchemy v1.0.13 或更高版本,this answer中提供了最简单的解决方案。提供的 LiteralDialect 类仍然需要提供正确的数据类型引用,如datetime。虽然它不完整,但添加缺少的数据类型非常简单。不幸的是,您必须将None修改为null()以进行INSERT / UPDATE。

  • 如果您可以使用SQLAlchemy v1.0.11 并且需要仅SELECT 语句(不是INSERT / UPDATE ),您还可以使用the above answer中的解决方案。 SQLAlchemy v1.0.11与ubuntu 16.04 xenial(当前的LTS版本)(截至2017年3月)一起发布。

如果您遇到一些较旧版本的SQLAlchemy,那么问题并没有简单明了的方法。

所以我想出了some code supporting SQL compilation个查询(SELECT)以及INSERT和UPDATE语句。该代码适用于SQLAlchemy v0.7.9 - v1.1.6 和Python2 / Python3。

包含detailed (and hilarious) analysis of the various features作为doctest。

相关的代码部分是:

答案 1 :(得分:0)

我只是在python 2.7SQLAlchemy (1.0.13)上运行此代码段并且有效。

from sqlalchemy.dialects import mysql
from sqlalchemy import Integer, Column, update, insert
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Test(Base):
    __tablename__ = "test"

    a = Column(Integer, primary_key=True)
    b = Column(Integer)


update_stmt = update(Test).where(Test.a == 1).values(b=2)
print update_stmt.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})

insert_stmt = insert(Test).values(a=1, b=1)
print insert_stmt.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})

我的输出是:

UPDATE test SET b=2 WHERE test.a = 1
INSERT INTO test (a, b) VALUES (1, 1)

您的环境可能出现问题?