pyodbc 不报告 sql 服务器错误
pyodbc doesn't report sql server error
我遇到一个问题,pyodbc 无法捕获从存储过程返回的错误。我的实际存储过程做了很多事情,但为了演示错误,我创建了一个简单的过程和关联的 python 代码。相关代码如下:
存储过程:
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代码:
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()
我得到的错误是预期的:
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)")
然而,当我修改我的存储过程以包含 select 语句时,错误不再返回到我的 python 代码。 Python 代码退出就像没有发生错误一样。
更新的存储过程:
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
当通过 select 语句存在交错结果记录时,pyodbc 似乎看不到错误。这里的问题是什么,有没有办法解决这个问题?
编辑: 我用 pymssql 试过了,看到了相同的行为
我能够通过使用 pypyodbc 的 Python 3.4.3 以及使用 ADO 的 VBScript 重现您的问题。似乎一旦存储过程发出结果集,ODBC 就会注意到 SP 已返回 something 并且 SP 中的后续错误不会触发调用过程中的错误。
一种可能的解决方法是构造您的存储过程,使其直到最后才产生任何结果集。如果 T-SQL 代码在执行任何创建结果集的 SELECT 之前遇到错误,那么该错误将返回给调用者。例如,你的存储过程的这个调整版本确实抛出一个 py[py]odbc 可以捕获的错误:
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
我遇到一个问题,pyodbc 无法捕获从存储过程返回的错误。我的实际存储过程做了很多事情,但为了演示错误,我创建了一个简单的过程和关联的 python 代码。相关代码如下:
存储过程:
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代码:
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()
我得到的错误是预期的:
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)")
然而,当我修改我的存储过程以包含 select 语句时,错误不再返回到我的 python 代码。 Python 代码退出就像没有发生错误一样。
更新的存储过程:
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
当通过 select 语句存在交错结果记录时,pyodbc 似乎看不到错误。这里的问题是什么,有没有办法解决这个问题?
编辑: 我用 pymssql 试过了,看到了相同的行为
我能够通过使用 pypyodbc 的 Python 3.4.3 以及使用 ADO 的 VBScript 重现您的问题。似乎一旦存储过程发出结果集,ODBC 就会注意到 SP 已返回 something 并且 SP 中的后续错误不会触发调用过程中的错误。
一种可能的解决方法是构造您的存储过程,使其直到最后才产生任何结果集。如果 T-SQL 代码在执行任何创建结果集的 SELECT 之前遇到错误,那么该错误将返回给调用者。例如,你的存储过程的这个调整版本确实抛出一个 py[py]odbc 可以捕获的错误:
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