tutorial raw query create column python sqlalchemy pylons

python - raw - SQLAlchemy imprime SQL sin formato desde create()



sqlalchemy query select (7)

¿Algo como esto? (de las preguntas frecuentes de SQLA)

http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html

Estoy probando Pylons con SQLAlchemy, y me encanta, solo hay una cosa: ¿es posible imprimir los datos sin procesar de SQL CREATE TABLE generados desde Table (). Create () antes de que se ejecuten?


¿Puede ser que te refieres al parámetro echo de sqlalchemy.create_engine?

/ tmp $ cat test_s.py

import sqlalchemy as sa from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Department(Base): __tablename__ = "departments" department_id = sa.Column(sa.types.Integer, primary_key=True) name = sa.Column(sa.types.Unicode(100), unique=True) chief_id = sa.Column(sa.types.Integer) parent_department_id = sa.Column(sa.types.Integer, sa.ForeignKey("departments.department_id")) parent_department = sa.orm.relation("Department") engine = sa.create_engine("sqlite:///:memory:", echo=True) Base.metadata.create_all(bind=engine)

/ tmp $ python test_s.py

2011-03-24 15:09:58,311 INFO sqlalchemy.engine.base.Engine.0x...42cc PRAGMA table_info("departments") 2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc () 2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc CREATE TABLE departments ( department_id INTEGER NOT NULL, name VARCHAR(100), chief_id INTEGER, parent_department_id INTEGER, PRIMARY KEY (department_id), UNIQUE (name), FOREIGN KEY(parent_department_id) REFERENCES departments (department_id) ) 2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc () 2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc COMMIT


Necesitaba obtener la tabla RAW sql para configurar las pruebas para algunos modelos existentes. Aquí hay una prueba de unidad exitosa que creé para SQLAlchemy 0.7.4 basada en la respuesta de Antoine como prueba de concepto:

from sqlalchemy import create_engine from sqlalchemy.schema import CreateTable from model import Foo sql_url = "sqlite:///:memory:" db_engine = create_engine(sql_url) table_sql = CreateTable(Foo.table).compile(db_engine) self.assertTrue("CREATE TABLE foos" in str(table_sql))


Puede configurar su motor para volcar la secuencia de creación de metadatos, usando lo siguiente:

def metadata_dump(sql, *multiparams, **params): # print or write to log or file etc print(sql.compile(dialect=engine.dialect)) engine = create_engine(myDatabaseURL, strategy=''mock'', executor=metadata_dump) metadata.create_all(engine)

Una ventaja de este enfoque es que las enumeraciones y los índices se incluyen en la impresión. Usar CreateTable deja esto fuera.

Otra ventaja es que el orden de las definiciones de esquema es correcto y (casi) utilizable como script.


Resulta que esto es sencillo:

from sqlalchemy.dialects import postgresql from sqlalchemy.schema import CreateTable from sqlalchemy import Table, Column, String, MetaData metadata = MetaData() users = Table(''users'', metadata, Column(''username'', String) ) statement = CreateTable(users) print(statement.compile(dialect=postgresql.dialect()))

Salidas esto:

CREATE TABLE users ( username VARCHAR )

Yendo más lejos, incluso puede soportar parámetros vinculados en declaraciones preparadas.

Referencia

¿Cómo renderizo expresiones SQL como cadenas, posiblemente con parámetros enlazados en línea?

...

o sin un motor:

from sqlalchemy.dialects import postgresql print(statement.compile(dialect=postgresql.dialect()))

FUENTE: http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html#faq-sql-expression-string

Ejemplo: Usar SQL Alchemy para generar un script de cambio de nombre de usuario

#!/usr/bin/env python import csv from sqlalchemy.dialects import postgresql from sqlalchemy import bindparam, Table, Column, String, MetaData metadata = MetaData() users = Table(''users'', metadata, Column(''username'', String) ) renames = [] with open(''users.csv'') as csvfile: for row in csv.DictReader(csvfile): renames.append({ ''from'': row[''sAMAccountName''], ''to'': row[''mail''] }) for rename in renames: stmt = (users.update() .where(users.c.username == rename[''from'']) .values(username=rename[''to''])) print(str(stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True})) + '';'')

Al procesar este users.csv:

sAMAccountName,mail bmcboatface,[email protected] ndhyani,[email protected]

Da salida como esta:

UPDATE users SET username=''[email protected]'' WHERE users.username = ''bmcboatface''; UPDATE users SET username=''[email protected]'' WHERE users.username = ''ndhyani'';users.username = ''ndhyani'';

Por qué un barco de investigación tiene una dirección de correo electrónico aún no se ha determinado. He estado en contacto con el equipo de TI de Example Inc y no he tenido respuesta.


SQLAlchemy está diseñado de tal manera que no permite hacer eco de sentencias DDL generadas sin ejecutarlas realmente. AFAIK, SQLAlchemy Migrate usa el simulador de motor para capturar sentencias sin ejecutarlas cuando se utiliza la opción --preview_sql, por lo que usarla es una forma de resolver el problema.


from sqlalchemy.schema import CreateTable print(CreateTable(table))

Si usa sintaxis declarativa:

print(CreateTable(Model.__table__))

Actualizar:

Como tengo la respuesta aceptada y hay información importante en la respuesta de klenwell , también la agregaré aquí.

Puede obtener el SQL para su base de datos específica (MySQL, Postgresql, etc.) compilando con su motor.

print(CreateTable(Model.__table__).compile(engine))

Actualización 2:

@jackotonye Agregado en los comentarios una forma de hacerlo sin un motor.

print(CreateTable(Model.__table__).compile(dialect=postgresq‌​l.dialect()))