【问题标题】:Pyodbc error when running the same code from different VENV从不同的 VENV 运行相同的代码时出现 Pyodbc 错误
【发布时间】:2021-09-30 02:03:57
【问题描述】:

我正在尝试从我创建的新 venv 运行一个执行存储过程的特定 SQL 命令,但我不断收到此错误:

pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 3 (""): Data type 0x63 has an invalid data length or metadata length. (8016) (SQLExecDirectW)')

我正在执行完全相同的语句,具有完全相同的值:

sql = "exec insertpart ?, ?, ?, ?, ?, ?, ?, ? output"
values = (0, 1, 2, 3, 4, 5, 6, 7)
cursor.execute(sql, values)

当我从一年多前编写的程序中执行它时,它的工作方式完全符合预期。但是当我从另一个 Venv 的新应用程序中执行它时,它会抛出上述错误。

这只发生在这个特定的执行语句中。我知道我已连接到 SQL 服务器,因为在此之前我多次查询数据库并获取信息,并且我从新的 venv 执行其他存储过程并且它们运行良好。

代码中唯一不同的是,在我的第一个 venv 中,此语句起作用,我仅在常规函数中设置与数据库的连接,并使光标成为全局变量。在我遇到问题的新版本中,我将其设置在一个类中,然后在我的程序中调用该类。

工作连接

def connect():
    try:
        global conn
        database = 'database'
        table = 'table'
        conn = pyodbc.connect('Driver={};'
                              'Server=192.168.1.5\SQL-SERVER-01,9400;'
                              'Database={};'
                              'UID=username;'
                              'PWD=password;'.format('SQL Server', database)
                              )
        global cursor
        cursor = conn.cursor()
        return cursor

非工作连接

class connection():
    def __init__(self):
        try:
            database = 'database'
            table = 'table'
            self.conn = pyodbc.connect('Driver={};'
                                  'Server=192.168.1.5\SQL-SERVER-01,9400;'
                                  'Database={};'
                                  'UID=username;'
                                  'PWD=password;'.format('SQL Server', database)
                                  )
            self.cursor = self.conn.cursor()

        except OperationalError as e:
            messagebox.showerror(title='Error', message='Error connecting to the Local server.')


........ later in the program 

        connect = connection()
        conn = connect.conn       # I use this conn and cursor to pass into my function that is
        cursor = connect.cursor   # actually executing the statement. 

最后,当我运行 SQL 分析器并观察我尝试从 2 个不同的环境运行此代码时。我不确定这是否有帮助,但我得到了他们俩的这条线

exec sp_sproc_columns N'insertpart',@ODBCVer=3

然后是有效的,探查器上接下来的 2 行是:

exec sp_unprepare 3
...
declare @p1 int
set @p1=4
exec sp_prepexec @p1 output,N'...... ALL of the info I am trying to update into the DB.

一个不起作用的,探查器显示:

exec sp_unprepare 1
...
exec sp_unprepare 1

【问题讨论】:

  • 你用的是什么python版本和pyodbc版本?我认为这些在虚拟环境之间有所不同。您可以发布错误的调用堆栈吗?我有点怀疑您发布的python代码是错误的根源。
  • 这似乎是从 SQL Server Native Client 通过 pyodbc 冒泡的错误。我怀疑两个 venv 之间的 SQL Server Native Client 版本不同。如果有帮助,数据类型0x63 引用ntext 数据type
  • @StevenEnsslen 在发布之前我认为它可能是 pyodbc 。我检查并在一个工作它是 4.0.30 和一个不工作的是 4.0.32,所以我卸载了 4.0.32 并 pip 安装了 4.0.30,它做同样的事情。两个版本都使用 Python 3.8。我什至将不工作的那个指向另一个 venv 中的 python 3.8,但它什么也没改变。我对这两个都使用 PyCharm,在同一台计算机上同时打开,如果这很重要的话。
  • @AlwaysLearning 我明天会研究一下 ntext 到底是什么。我不确定那是什么。它绝对可以是不同版本的 SQL Server Native Client。我不知道如何/在哪里检查那个版本。

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


【解决方案1】:

感谢一些 cmets,特别是 @StevenEnsslen,我能够运行命令 pyodbc.drivers() 并查看已安装的驱动程序。根据他发布的 github 链接,我注意到我在 pyodbc.connect() 命令中使用了过时的驱动程序。我将驱动程序从“SQL Server”更改为“ODBC Driver 17 for SQL Server”,现在我的程序运行良好。

我无法解释为什么。我正在使用同一台计算机以相同的登录凭据连接到同一台 SQL 服务器,并且“SQL Server”驱动程序在我的一个 VENV 中完美运行,而在另一台 VENV 中仅在某些命令上失败。

无论哪种方式,我希望这个答案对其他人有所帮助。如果其他人有更多关于如何/为什么会发生这种情况的信息并想对这个问题有所了解,我很乐意将您的答案标记为正确答案。谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多