Cannot return results from stored procedure using Python cursor
Have you tried picking one of the resultsets?
for result in cursor.stored_results():
people = result.fetchall()
It could be that it's allocating for multiple resultsets even though you only have one SELECT
stmt. I know in PHP's MySQLi stored procedures do this to allow for INOUT and OUT variable returns (which again, you have none of, but maybe it's allocating anyways).
The complete code I'm using (which is working) is:
import mysql.connector
cnx = mysql.connector.connect(user='me',password='pw',host='localhost',database='mydb')
cnx._open_connection()
cursor = cnx.cursor()
cursor.callproc("getperson",[1])
for result in cursor.stored_results():
people=result.fetchall()
for person in people:
print person
cnx.close()
MSSQL2014 & python 3.7.3: Trying to get stored procedure return value results in No results. Previous SQL was not a query.
You have to call cursor.nextset()
to skip past any info messages that were output by the called stored procedures, as NOCOUNT ON is not enough here.
But unfortunately cursor
doesn't have a .hasrows()
method, so you have to catch the exception in a loop.
EG:
import pyodbc
sql = """\
SET NOCOUNT ON
DECLARE @rv INT
EXEC @rv = sp_executesql N'print ''informational message'''
SELECT @rv
"""
conn = pyodbc.connect('Driver={ODBC Driver 17 for SQL Server};'
'Server=localhost;'
'Database=tempdb;'
'Trusted_Connection=yes;')
conn.autocommit = True
cursor = conn.cursor()
cursor.execute(sql)
while True:
try:
retv = cursor.fetchone()
break
except pyodbc.ProgrammingError as e:
if "Previous SQL was not a query." in str(e):
if not cursor.nextset():
throw
print(retv)
How to retrieve an output parameter of a stored procedure?
pyodbc does not currently implement the optional .callproc()
method, so a workaround is required to retrieve output parameters and return values. For SQL Server that involves an anonymous code block to EXEC the stored procedure and then SELECT the values, e.g.,
sql = """\
DECLARE @out nvarchar(max);
EXEC [dbo].[test_for_pyodbc] @param_in = ?, @param_out = @out OUTPUT;
SELECT @out AS the_output;
"""
params = ("Burma!", )
crsr.execute(sql, params)
rows = crsr.fetchall()
while rows:
print(rows)
if crsr.nextset():
rows = crsr.fetchall()
else:
rows = None
More details at the pyodbc wiki:
https://github.com/mkleehammer/pyodbc/wiki/Calling-Stored-Procedures#output-parameters-and-return-values
Python sqlalchemy and mySQL stored procedure always returns 0 (out param only)
With the help of this answer I found the following solution that worked for me.
a) Working solution using engine.raw_connection()
and cursor.callproc
:
def call_procedure(engine, function_name):
connection = engine.raw_connection()
try:
cursor = connection.cursor()
cursor.callproc(function_name, [0])
cursor.execute(f"""SELECT @_{function_name}_0""")
results = cursor.fetchone() ## returns a tuple e.g. (285,)
rows_affected = results[0]
cursor.close()
connection.commit()
logger.info(f"Running procedure {function_name} success!")
return rows_affected
except Exception as e:
logger.error(f"Running procedure {function_name} failed!")
logger.exception(e)
return None
finally:
connection.close()
And with this answer I found this solution also:
b) Instead of using a raw connection, this worked as well:
def call_procedure(engine, function_name, params=None):
try:
with engine.begin() as db_conn:
db_conn.execute(f"""CALL {function_name}(@out)""")
results = db_conn.execute('SELECT @out').fetchone() ## returns a tuple e.g. (285,)
rows_affected = results[0]
logger.debug(f"Running procedure {function_name} success!")
return rows_affected
except Exception as e:
logger.error(f"Running procedure {function_name} failed!")
logger.exception(e)
return None
finally:
if db_conn: db_conn.close()
If there are any advantages or drawbacks of using one of these methods over the other, please let me know in a comment.
Related Topics
How to Write Binary Data to Stdout in Python 3
Parsing a JSON String Which Was Loaded from a CSV Using Pandas
Getting One Value from a Tuple
How to Extract an Arbitrary Line of Values from a Numpy Array
How to Solve Readtimeouterror: Httpsconnectionpool(Host='Pypi.Python.Org', Port=443) with Pip
Pyserial Non-Blocking Read Loop
How to Join Two Wav Files Using Python
E731 Do Not Assign a Lambda Expression, Use a Def
Simple Python Challenge: Fastest Bitwise Xor on Data Buffers
What's a Faster Operation, Re.Match/Search or Str.Find
Shuffling/Permutating a Dataframe in Pandas
Can You Use a String to Instantiate a Class
Comparing Boolean and Int Using Isinstance
How to Get Python Requests to Trust a Self Signed Ssl Certificate
Interpolate Nan Values in a Numpy Array
Getting Rid of Console Output When Freezing Python Programs Using Pyinstaller
How to Improve the Label Placement in Scatter Plot
Python Pandas Extract Year from Datetime: Df['Year'] = Df['Date'].Year Is Not Working