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=postgresql.dialect()))