Stored Procedure executemany does not return selected value
See original GitHub issue- Python: 3.10.2 64bit
- pyodbc: 4.0.32
- OS: Windows 10 64bit
- DB: SQL Server (MSSQL)
- driver: ‘ODBC Driver 17 for SQL Server’
I have the following stored procedure. I create some variables in the beginning that I select no matter what happens in the end as they indicate information about the success of the procedure. So I want to insert, then have the select return a row in the end. I also call this single stored procedure with executemany
on multiple objects. Running the stored procedure in SQL Server Management Studio is working fine and gives back the desired select in the end no matter what. Calling the same from pyodbc only returns the select if I run execute or executemany on exactly 1 object.
Ideally I would like to receive a response for all objects I give to executemany with fast_executemany set to True. If I set fast_executemany
to True I get nothing back, just ‘Previous SQL was not a query’.
I have SET NOCOUNT ON
in the procedure and I have also set autocommit
on when creating the connection. No matter what I do, .fetchall()
gives back 'pyodbc.ProgrammingError: No results. Previous SQL was not a query.'
The row gets inserted correctly and everything works fine, but I am not getting back the return value in Python. Removing fastexecute_many = True
will make the function give back exactly only 1 row of result, but the rest are left out. If I call the executemany function on many rows I would expect to get back a result for each insert. This leaves me with using just execute on rows one-by-one which is not ideal as I am working with many thousands of rows.
How can I use executemany with fast_executemany set to True on multiple objects with all of them getting a return value in the end in an array?
CREATE PROCEDURE [Letters].[spInsertSecretary]
(
@role NVARCHAR(50),
@name NVARCHAR(255),
@source NVARCHAR(20),
@company_id NVARCHAR(10),
@country NVARCHAR(55) = NULL,
@region NVARCHAR(100) = NULL,
@postal_code NVARCHAR(20) = NULL,
@locality NVARCHAR(100) = NULL,
@premises NVARCHAR(100) = NULL,
@address_line_1 NVARCHAR(255) = NULL,
@address_line_2 NVARCHAR(255) = NULL,
@country_of_residence NVARCHAR(55) = NULL,
@appointed_on DATETIME2 = NULL,
@occupation NVARCHAR(55) = NULL,
@nationality NVARCHAR(55) = NULL,
@date_of_birth DATETIME2 = NULL,
@resigned_on DATETIME2 = NULL,
@name_normal NVARCHAR(255) = NULL
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @HasError BIT = 0
DECLARE @InsertedId INT = NULL
DECLARE @ErrorLine INT = NULL
DECLARE @ErrorMessage NVARCHAR(1000) = NULL
BEGIN TRY
INSERT INTO [Letters].[Secretary]
(
role,
name,
source,
company_id,
country,
region,
postal_code,
locality,
premises,
address_line_1,
address_line_2,
country_of_residence,
appointed_on,
occupation,
nationality,
date_of_birth,
resigned_on,
name_normal,
created_at,
last_updated_at
)
VALUES
(
@role,
@name,
@source,
@company_id,
@country,
@region,
@postal_code,
@locality,
@premises,
@address_line_1,
@address_line_2,
@country_of_residence,
@appointed_on,
@occupation,
@nationality,
@date_of_birth,
@resigned_on,
@name_normal,
GETDATE(),
GETDATE()
)
SET @InsertedId = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
SET @HasError = 1
SET @ErrorLine = ERROR_LINE()
SET @ErrorMessage = ERROR_MESSAGE()
END CATCH
SELECT
@InsertedId AS 'InsertedId',
@HasError AS 'HasError',
@ErrorMessage AS 'ErrorMessage',
@ErrorLine AS 'ErrorLine'
END
GO
connection_string = f"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={Config.DATABASE_SERVER_NAME};DATABASE={Config.DATABASE_NAME};UID={Config.DATABASE_USERNAME};PWD={Config.DATABASE_PASSWORD};trusted_connection=yes;autocommit=yes;"
query = 'EXEC Letters.spInsertSecretary @role=?, @name=?, @company_id=?, @country_of_residence=?, @appointed_on=?, @occupation=?, @nationality=?, @date_of_birth=?, @resigned_on=?, @name_normal=?, @source=?, @country=?, @region=?, @postal_code=?, @locality=?, @premises=?, @address_line_1=?, @address_line_2=?'
param_values = (('secretary', 'MARTIN, Rosemary Elisabeth Scudamore', '01833679', None, datetime.datetime(2010, 3, 30, 0, 0), None, None, None, None, None, 'COMPANIES HOUSE', None, 'Berkshire', 'RG14 2FN', 'Newbury', None, 'Vodafone House', 'The Connection'),('secretary', 'MARTIN, Rosemary Elisabeth Scudamore', '01833679', None, datetime.datetime(2010, 3, 30, 0, 0), None, None, None, None, None, 'COMPANIES HOUSE', None, 'Berkshire', 'RG14 2FN', 'Newbury', None, 'Vodafone House', 'The Connection'))
with pyodbc.connect(connection_string) as connection:
with connection.cursor() as cursor:
cursor.fast_executemany = True
result = cursor.executemany(query, param_values) # result becomes None
return_value = cursor.fetchall() # pyodbc.ProgrammingError: No results. Previous SQL was not a query.
As I have stated, the inserts happen, but I get no result back for any of them from the select at the end.
Issue Analytics
- State:
- Created a year ago
- Comments:7 (2 by maintainers)
.executemany()
is not specifically designed to return result sets. PEP 249 says:So if you want result set(s) you need to use
.execute()
. You can either.execute()
call.Thank you very much. I got my answers. The thread can be closed