tutorial - sqlalchemy query select
Ejecutar SQL desde archivo en SQLAlchemy (5)
¿Cómo puedo ejecutar un archivo sql entero en la base de datos usando SQLAlchemy? Puede haber muchas consultas de sql diferentes en el archivo, incluyendo begin y commit / rollback.
Lamentablemente no soy consciente de una buena respuesta general para esto. Algunos dbapi''s (psycopg2, por ejemplo) admiten la ejecución de varias declaraciones a la vez. Si los archivos no son enormes, solo puede cargarlos en una cadena y ejecutarlos en una conexión. Para otros, intentaría usar un cliente de línea de comandos para esa base de datos y canalizar los datos en el que utiliza el módulo de subproceso.
Si esos enfoques no son aceptables, entonces tendrá que seguir adelante e implementar un pequeño analizador de SQL que pueda dividir el archivo en declaraciones separadas. Esto es realmente difícil de conseguir al 100% correcto, ya que tendrá que tener en cuenta las reglas de escape literales específicas del dialecto de la base de datos, el conjunto de caracteres utilizado, las opciones de configuración de la base de datos que afecten el análisis literal (por ejemplo, PostgreSQL standard_conforming_strings).
Si solo necesitas obtener este 99.9% correcto, entonces un poco de magia con expresiones regulares debería hacerte llegar la mayor parte del camino.
Pude ejecutar archivos de esquema .sql utilizando SQLAlchemy puro y algunas manipulaciones de cadenas. Seguramente no es un enfoque elegante, pero funciona.
# Open the .sql file
sql_file = open(''file.sql'',''r'')
# Create an empty command string
sql_command = ''''
# Iterate over all lines in the sql file
for line in sql_file:
# Ignore commented lines
if not line.startswith(''--'') and line.strip(''/n''):
# Append line to the command string
sql_command += line.strip(''/n'')
# If the command string ends with '';'', it is a full statement
if sql_command.endswith('';''):
# Try to execute statement and commit it
try:
session.execute(text(sql_command))
session.commit()
# Assert in case of error
except:
print(''Ops'')
# Finally, clear command string
finally:
sql_command = ''''
Se itera sobre todas las líneas en un archivo .sql ignorando las líneas comentadas. Luego concatena líneas que forman una declaración completa e intenta ejecutar la instrucción. Solo necesitas un manejador de archivos y un objeto de sesión.
Puede acceder a la conexión DBAPI en bruto a través de este
raw_connection = mySqlAlchemyEngine.raw_connection()
raw_cursor = raw_connection() #get a hold of the proxied DBAPI connection instance
pero luego dependerá de qué dialecto / controlador está utilizando, al que se puede hacer referencia a través de esta list .
Para pyscog2, solo puedes hacer
raw_cursor.execute(open("my_script.sql").read())
pero pysqlite tendría que hacer
raw_cursor.executescript(open("my_script").read())
y en línea con eso, deberá verificar la documentación de cualquier controlador DBAPI que esté usando para ver si se permiten varias declaraciones en una ejecución o si necesitaría usar un ayudante como el ejecutable que es exclusivo de pysqlite.
Puedes hacerlo con SQLalchemy y psycopg2.
file = open(path)
engine = sqlalchemy.create_engine(db_url)
escaped_sql = sqlalchemy.text(file.read())
engine.execute(escaped_sql)
Si está utilizando sqlite3, tiene una extensión útil para dbapi llamada conn.executescript (str), lo he conectado a través de algo como esto y parece funcionar: (No se muestra todo el contexto, pero debería ser suficiente para obtener el deriva)
def init_from_script(script):
Base.metadata.drop_all(db_engine)
Base.metadata.create_all(db_engine)
# HACK ALERT: we can do this using sqlite3 low level api, then reopen session.
f = open(script)
script_str = f.read().strip()
global db_session
db_session.close()
import sqlite3
conn = sqlite3.connect(db_file_name)
conn.executescript(script_str)
conn.commit()
db_session = Session()
Es este puro mal me pregunto? Busqué en vano un equivalente sqlalchemy ''puro'', ¿tal vez eso podría agregarse a la biblioteca, algo como db_session.execute_script (file_name)? Espero que db_session funcione bien después de todo eso (es decir, no es necesario reiniciar el motor) pero aún no estoy seguro ... se necesitan más investigaciones (es decir, necesitamos un nuevo motor o solo una sesión después de ir detrás de sqlalchemy) ?)
Para su información, sqlite3 incluye una rutina relacionada: sqlite3.complete_statement (sql) si lanza su propio analizador ...