Sqlalchemy – ¿Cómo obtener sql sin formato de insert (), update () enunciados con parámetros enlazados?

Ejemplo:

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()) 

El resultado de esto es:

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

La pregunta es cómo hacer que sqlalchemy genere algo así:

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

Para select , compile_kwargs= {"literal_binds": True} resuelve el problema, pero no funciona para la update , insert .

Gracias por cualquier ayuda.

PD: Necesito crear consultas de sql sin procesar desde orm, por lo que cualquier sugerencia de cualquier otro orms, que tenga una forma fácil de generar sql sin procesar, es bienvenida.

La solución que utiliza compile_kwargs , como se anuncia en otra parte, funciona solo parcialmente, es decir, para tipos de datos simples como Integer o String (a partir de 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 | -- | +-------------+----------------+--------+---------------+----------+ 

Dependiendo de los requisitos y restricciones, las siguientes soluciones harán el trabajo:

  • Si puede usar SQLAlchemy v1.0.13 o superior, en esta respuesta se proporciona la solución más sencilla. La clase LiteralDialect presentada allí todavía es necesaria para proporcionar una cotización correcta de los tipos de datos, como datetime. Aunque no está completo, agregar tipos de datos faltantes es muy sencillo. Y, desafortunadamente, debe corregir None a null() para INSERTAR / ACTUALIZAR.

  • Si puede usar SQLAlchemy v1.0.11 y necesita solo sentencias SELECT ( no INSERT / UPDATE ), también puede usar la solución de la respuesta anterior . SQLAlchemy v1.0.11 se distribuye con ubuntu 16.04 xenial, la versión actual de LTS (a partir de marzo de 2017).

Si estás atascado con alguna versión anterior de SQLAlchemy, no hay un enfoque dulce y simple para el problema.

Así que se me ocurrió un código que admite la comstackción de consultas SQL (SELECT), así como las instrucciones INSERT y UPDATE. El código funciona con SQLAlchemy v0.7.9 – v1.1.6 y Python2 / Python3.

Un análisis detallado (e hilarante) de las diversas características se incluye como doctest.

Las secciones de código relevantes son:

  • funcion sql_statement
  • clase LiteralDialect
  • funciones fix_null_params , fix_null_values , null_if_none
  • variable COMPILE_KWARGS
  • y como bonus table_sql_dump

Acabo de ejecutar este fragmento en python 2.7 y SQLAlchemy (1.0.13) y funcionó.

 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}) 

mi salida es:

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

Tal vez algo está mal con su entorno?