问题
I have an issue where pyodbc doesn't capture errors returned from stored procedure. My actual stored proc does a lot of stuff but for the purpose of demonstrating the error I created a simple proc and associated python code. Relevant code is below:
Stored Procedure:
CREATE PROCEDURE [dbo].[testErrors]
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into Parameter(Name, Units, DataType) values (null, null, null)
END
GO
Python code:
import pyodbc
connectString = "DRIVER={SQL Server};SERVER=%s;DATABASE=%s;UID=%s;PWD=%s" % (r'srvr', r'mydb', r'usr', r'pwd')
cnxn = pyodbc.connect(connectString)
cnxn.autocommit = True
cursor = cnxn.cursor()
cursor.execute("exec testErrors")
cursor.close()
Error I get as expected:
cursor.execute("exec testErrors")
pyodbc.IntegrityError: ('23000', "[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'Name', table 'Parametrics.dbo.Parameter'; column does not allow nulls. INSERT fails. (515) (SQLExecDirectW); [01000] [Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been terminated. (3621)")
However when I modified my stored procedure to include a select statement the error no longer comes back to my python code. Python code exits as if no error has occurred.
Updated Stored Procedure:
CREATE PROCEDURE [dbo].[testErrors]
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select 108
-- Insert statements for procedure here
insert into Parameter(Name, Units, DataType) values (null, null, null)
END
GO
It seems pyodbc doesn't see the error when there are interleaving result records through select statements. What is the issue here and is there a way to overcome this issue?
EDIT: I tried this with pymssql and see the same behavior
回答1:
I was able to recreate your issue with Python 3.4.3 using pypyodbc, and also with a VBScript using ADO. It appears that once a stored procedure has emitted a result set then ODBC notices that the SP has returned something and subsequent errors in the SP don't trigger an error in the calling procedure.
One possible workaround would be to structure your stored procedure so that it doesn't produce any result set(s) until the very end. If the T-SQL code encounters an error before executing any SELECT that creates a result set then the error gets passed back to the caller. For example, this tweaked version of your stored procedure does throw an error that py[py]odbc can catch:
CREATE PROCEDURE [dbo].[Table1sp] AS
BEGIN
DECLARE @foo int;
SET NOCOUNT ON;
SELECT @foo = 108;
INSERT INTO Table1 (textcol) VALUES (NULL); -- error here
SELECT @foo AS foo
END
来源:https://stackoverflow.com/questions/29377756/pyodbc-doesnt-report-sql-server-error