Trying to use the method detailed here to call a stored proc and perform an update using pyodbc in python3.6. I have one method that handles starting the instance and one that wraps things up.
Starting the instance works perfectly:
def start_instance(self, count):
params = [1, count]
sql = """
DECLARE @out as int;
EXEC [dbo].[my_sproc] @id = ?, @count = ?, @instance_id = NULL, @output = @out OUTPUT;
SELECT @out as op;
"""
val = self.dbObj.query(sql, params).fetchval()
self.instance = val
Ending it produces an error:
def end_instance(self):
params = [1, self.instance]
sql = """
DECLARE @out as int;
EXEC [dbo].[my_sproc] @id = ?, @instance_id = ?, @output = @out OUTPUT;
SELECT @out as op;
"""
val = self.dbObj.query(sql, params).fetchval()
print(val)
The error is pyodbc.ProgrammingError: No results. Previous SQL was not a query.
My Stored Proc:
ALTER PROCEDURE [dbo].[my_sproc] @id int, @count int = NULL, @instance_id int = NULL, @output int OUTPUT
AS
IF(@instance_id IS NULL)
BEGIN
DECLARE @OutputTbl TABLE (ID INT)
INSERT INTO [dbo].[my_table]([id], [record_count]) OUTPUT INSERTED.id VALUES(@id, COALESCE(@count, 0));
END
IF(@instance_id IS NOT NULL)
BEGIN
UPDATE [dbo].[my_table] SET [instance_end] = GETDATE(), [records_processed] = COALESCE(@count, 0) WHERE [id] = @id AND [instance_id] = @instance_id;
SET @output = 1
END
I can run the below sql in SSMS and it will work fine:
DECLARE @out as int;
EXEC [dbo].[my_sproc] @id = 1, @count = NULL, @instance_id = 12, @output = @out OUTPUT;
SELECT @out as op
UPDATE:
Got it working initially thanks to Gord Thompson's hint regarding SET NOCOUNT ON
. However, I ultimately want end_instance()
to run atexit. I'm currently doing this:
atexit.register(self.clean_up_on_exit)
and then:
def clean_up_on_exit(self):
self.check_in_records()
self.end_instance()
self.dbObj.close_conn()
If I just call end_instance()
at the end of start_instance()
just for testing purposes, I get the expected result. However, adding it to my clean_up_on_exit()
method doesn't produce an error, but doesn't work either.
UPDATE 2:
Registering my functions separately fixed the second problem:
atexit.register(self.check_in_records)
atexit.register(self.end_instance)