¿Cómo puedo llamar a los procedimientos almacenados del servidor sql con sqlAlchemy?procedimientos almacenados con sqlAlchemy
Respuesta
Los motores y las conexiones tienen un método execute()
que puede usar para las sentencias sql arbitrarias, y también lo hacen las sesiones. Por ejemplo:
results = sess.execute('myproc ?, ?', [param1, param2])
Puede utilizar outparam()
para crear parámetros de salida si es necesario (o para los parámetros, use bind bindparam()
con la opción isoutparam=True
)
sólo hay que ejecutar procedimiento objeto creado con func
:
from sqlalchemy import create_engine, func
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite://', echo=True)
print engine.execute(func.upper('abc')).scalar() # Using engine
session = sessionmaker(bind=engine)()
print session.execute(func.upper('abc')).scalar() # Using session
Esto no funciona con MySQL, 'Function no existe. – Profpatsch
Funcionó para mí, forma elegante y simple de llamar a procedimientos almacenados. Notas oficiales _La construcción: data: '.func' solo tiene soporte limitado para llamar a " procedimientos almacenados "independientes, especialmente aquellos con problemas de parametrización especiales . Consulte la sección: ref: 'stored_procedures' para obtener detalles sobre cómo usar el método' 'callproc()' 'de nivel DBAPI para los procedimientos almacenados totalmente tradicionales._ Código para personas como yo:' session.execute (Func.your_proc_name (param1, param2)) ' – Niyojan
Suponiendo que ya tiene una sesión creada con sessionmaker(), puede usar la siguiente función:
def exec_procedure(session, proc_name, params):
sql_params = ",".join(["@{0}={1}".format(name, value) for name, value in params.items()])
sql_string = """
DECLARE @return_value int;
EXEC @return_value = [dbo].[{proc_name}] {params};
SELECT 'Return Value' = @return_value;
""".format(proc_name=proc_name, params=sql_params)
return session.execute(sql_string).fetchall()
Ahora usted puede ejecutar su procedimiento 'MyProc' almacenado con parámetros simplemente por el estilo:
params = {
'Foo': foo_value,
'Bar': bar_value
}
exec_procedure(session, 'MyProc', params)
Esto parece vulnerable a la inyección de SQL. –
Esto de hecho es vulnerable. Es mejor pasar argumentos con nombre con 'execute (sql_string, params = ...) 'para permitir que el motor escape los valores del argumento. La respuesta de @Profpatsch ya lo hace. –
¿Cómo puedo recopilar un parámetro de salida con esto? es decir, mi declaración es: 'EXEC dbo.next_rowid 'dbo', 'workorder_feature', @id OUTPUT;' ¿cómo obtengo el id? – roemhildtg
Fuera de desesperada necesidad de un proyecto mío, escribí una función que se encarga de procedimiento almacenado llama.
Aquí van:
import sqlalchemy as sql
def execute_db_store_procedure(database, types, sql_store_procedure, *sp_args):
""" Execute the store procedure and return the response table.
Attention: No injection checking!!!
Does work with the CALL syntax as of yet (TODO: other databases).
Attributes:
database -- the database
types -- tuple of strings of SQLAlchemy type names.
Each type describes the type of the argument
with the same number.
List: http://docs.sqlalchemy.org/en/rel_0_7/core/types.html
sql_store_procudure -- string of the stored procedure to be executed
sp_args -- arguments passed to the stored procedure
"""
if not len(types) == len(sp_args):
raise ValueError("types tuple must be the length of the sp args.")
# Construch the type list for the given types
# See
# http://docs.sqlalchemy.org/en/latest/core/sqlelement.html?highlight=expression.text#sqlalchemy.sql.expression.text
# sp_args (and their types) are numbered from 0 to len(sp_args)-1
type_list = [sql.sql.expression.bindparam(
str(no), type_=getattr(sql.types, typ)())
for no, typ in zip(range(len(types)), types)]
try:
# Adapts to the number of arguments given to the function
sp_call = sql.text("CALL `%s`(%s)" % (
sql_store_procedure,
", ".join([":%s" % n for n in range(len(sp_args))])),
bindparams=type_list
)
#raise ValueError("%s\n%s" % (sp_call, type_list))
with database.engine.begin() as connection:
return connection.execute(
sp_call,
# Don't do this at home, kids...
**dict((str(no), arg)
for (no, arg) in zip(range(len(sp_args)), sp_args)))
except sql.exc.DatabaseError:
raise
Se trabaja con la sintaxis de llamada, por lo MySQL debería funcionar como se espera. MSSQL usa EXEC en lugar de llamada y una pequeña sintaxis, supongo. Así que hacerlo independiente del servidor depende de usted, pero no debería ser demasiado difícil.
La forma más fácil de llamar a un procedimiento almacenado en MySQL utilizando SQLAlchemy es mediante el método callproc
de Engine.raw_connection()
. call_proc
requerirá el nombre del procedimiento y los parámetros necesarios para el procedimiento almacenado que se llama.
def call_procedure(function_name, params):
connection = cloudsql.Engine.raw_connection()
try:
cursor = connection.cursor()
cursor.callproc(function_name, params)
results = list(cursor.fetchall())
cursor.close()
connection.commit()
return results
finally:
connection.close()
- 1. Creación de procedimientos almacenados con SQLAlchemy
- 2. WebMatrix y procedimientos almacenados
- 3. Procedimientos almacenados Ingeniería inversa
- 4. Versiones de procedimientos almacenados
- 5. Funciones vs procedimientos almacenados
- 6. Procedimientos almacenados vs. Vistas
- 7. Patrones para procedimientos almacenados?
- 8. Procedimientos almacenados y funciones
- 9. Patrón de repositorio con procedimientos almacenados
- 10. ¿Accediendo a procedimientos almacenados con robconery/masivo?
- 11. MySQL: Vistas vs Procedimientos almacenados
- 12. Procedimientos almacenados a archivos .sql
- 13. ¿Puede tener demasiados procedimientos almacenados?
- 14. Procedimientos almacenados y pruebas unitarias
- 15. Expresiones regulares en procedimientos almacenados
- 16. consultas parametrizadas SIN procedimientos almacenados?
- 17. herramienta generador de procedimientos almacenados
- 18. Tablas temporales en procedimientos almacenados
- 19. Procedimientos almacenados - Fin de días
- 20. ¿El SQL formado dinámicamente en los procedimientos almacenados niega el propósito mismo de los procedimientos almacenados?
- 21. Eliminar todos los procedimientos almacenados en MySQL o usar procedimientos almacenados temporales
- 22. Soltar grupo de procedimientos almacenados por nombre
- 23. Lista de procedimientos almacenados de la tabla
- 24. Mejores lenguajes que SQL para procedimientos almacenados
- 25. cambios de versión para procedimientos almacenados
- 26. Depuración de procedimientos almacenados en Management studio
- 27. Consultas de LINQ frente a Procedimientos almacenados
- 28. Uso de procedimientos almacenados en rieles
- 29. MYSQL Procedimientos almacenados Si enunciado Problema
- 30. ¿Cómo encontrar los procedimientos almacenados por nombre?
Esto no es agnóstico de la base de datos. Use 'sqlalchemy.sql.text' en su lugar. – Profpatsch
BTW necesita 'sess.execute ('SET NOCOUNT ON')' si desea acceder a las filas devueltas por el procedimiento almacenado en MS SQL Server. Puede hacerlo en una llamada de ejecución: 'results = sess.execute ('SET NOCOUNT ON; EXEC myproc?,?; SET NOCOUNT OFF', [param1, param2])'. –
Este es un hilo antiguo, tal vez esto es algo que ha cambiado en las versiones más recientes de sqlalchemy, pero tuve que usar un diccionario en lugar de una lista para los parámetros y usar ": param_name" en el sql en bruto en lugar de "?" . Así que, el ejemplo anterior se convierte en: 'sess.execute ('myproc: p1,: p2', {'p1': 'value1', 'p2': 'value2'})' – ThatAintWorking