【问题标题】:Pyodbc not returning error from SQL ServerPyodbc 未从 SQL Server 返回错误
【发布时间】:2019-01-10 17:31:47
【问题描述】:

好的,希望这是我忽略的非常愚蠢的事情......

我在 SQL Server 17 (14.0.2002.14) 上使用 Python 3.7.2 和 Pyodbc 4.0.24

在我的 SQL Server 上,我创建了一个这样的表:

create table test(
    test1 varchar(5)
)

但是当我尝试通过使用 pyodbc 执行相同的查询来引发错误(因为表已经存在)时,我没有看到返回任何错误:

def createSQLTable():
    try:
        sql_conn = pyodbc.connect('Driver={ODBC Driver 17 for SQL Server};'
                                    'Server=[SERVERNAME];'
                                    'Database=[DATABASENAME];'
                                    'Trusted_Connection=yes;')
        cursor = sql_conn.cursor()
        sql = '''set nocount on;
           use [DATABASENAME]
           create table test(test1 varchar(5));'''
        cursor.execute(sql)
    except Exception as e:
        print(e)
    finally:
        sql_conn.commit()
        cursor.close()
        sql_conn.close()

createSQLTable()

如果我在 SQL Server 上运行相同的 TSQL,我会收到错误消息:

Msg 2714, Level 16, State 6, Line 1 已经有一个对象名为 数据库中的“测试”。

那么如何让 Python/Pyodbc 抛出相同或相似的错误?

【问题讨论】:

  • @Parfait 感谢您的建议,不幸的是这并没有改变任何事情。
  • @Parfait 自动提交不走运。
  • 删除多余的USE 行,因为您根据连接字符串直接连接到此数据库。
  • @Parfait 啊哈!认为这是一件愚蠢的事情……那行得通。提交答案,我会将其标记为正确。非常感谢!
  • @Parfait 这确实引发了另一个问题......为什么数据库冗余会导致代码无声地完成而没有错误?我现在可以让代码正常工作,只是想完全理解它为什么工作/不工作。

标签: python sql sql-server python-3.x pyodbc


【解决方案1】:

Pyodbc 不会引发任何异常,因为 USE [DATABASENAME] 没有错误,这是多语句查询中的第一个事务类型行。

与大多数 Python DB-API 一样,Pyodbc 不支持在同一个执行调用中使用多个事务性 SQL 语句,但有一些例外。通常只会运行第一个查询。

考虑在同一try 块中单独发送它们:

cur.execute('set nocount on;')
cur.execute('use [DATABASENAME];')
cur.execute('create table test(test1 varchar(5));')

或将行放在存储过程中并使用以下任一方式运行:

cursor.execute("EXEC mystoredProc")

cursor.execute("{CALL mystoredProc}")

或者只保留相关行,因为数据库连接规范不需要USE

cur.execute('''set nocount on
               create table test(test1 varchar(5)
            ''')

【讨论】:

  • "通常只会运行第一个查询。" - 不是我的经验。是的,在某些情况下,匿名代码块会失败或产生潜在的混淆结果(例如,在需要时省略 SET NOCOUNT ON;),但这更多是 ODBC 驱动程序的功能,而不是 pyodbc 本身的功能。 pyodbc 只是将 SQL 命令文本传递给 ODBC 驱动程序管理器并等待结果返回。
  • 好点@GordThompson。我不想做出绝对的声明,因为某些多行代码块可以运行,尤其是 TSQL,它的批处理调用使用 GO。一切都依赖于 API、驱动程序,甚至是 RDBMS。
  • 同意。是的,在这种情况下(SQL Server),use [DATABASENAME] 需要先进入它自己的 .execute,然后是其余的匿名代码块。
【解决方案2】:

抱歉死灵,但万一其他人正在搜索这个,pyodbc 不会返回错误,因为它是首先获取与错误无关的消息,例如(1) rows affected。我通过在程序开始时调用set nocount on 解决了我的问题,而无需根据接受的答案拆分呼叫。

【讨论】:

    猜你喜欢
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多