【问题标题】:programming error with pyodbcpyodbc 编程错误
【发布时间】:2023-11-05 20:51:01
【问题描述】:

我正在尝试使用以下代码查询 SQL Server 2012 数据库:

import pyodbc

class sqlserverConnector:
    def __init__(self, connectionString):

        """
        this is a typical connection string using windows authentication and the DSN manager:

            'DSN=python;Trusted_Connection=yes'
        """
        self._conn = pyodbc.connect(connectionString)
        self._curs = self._conn.cursor()
        self.fetchall = self._curs.fetchall
        self.description = self._curs.description
        self.columns = dict()

    def __del__(self):
        self._conn.close()

    def __iter__(self):
        return self._curs.__iter__()

    # executes SQL statements
    def execute(self, statement, **params):
        if params is None:
            self._curs.execute(statement)
        else:
            self._curs.execute(statement,params)

        # creates a dictionary of column names and positions
        if self._curs.description != None:
            self.columns = dict((field[0], pos) for pos, field in enumerate(self._curs.description))
        else:
            None

还有:

from sqlutil import *

sqlcnxn = sqlserverConnector('DSN=python;Trusted_Connection=yes')
rows = sqlcnxn.execute("select * from demographics", params=None)

for row in rows:
    print row
    break

目标是打印出一行(表格有 80k+ 行)。但是我总是收到此错误消息:

pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')

我用谷歌搜索了一下,似乎由于不同的原因,不同的人会弹出这个问题,而且我发现没有一个解决方案适合我的错误。我认为正在发生的事情是 execute 方法默认使用第一个 else 语句而不是第一个 if 语句。

【问题讨论】:

    标签: python sql pyodbc


    【解决方案1】:

    当您使用 **params 表示法时,params始终字典。

    使用params=None 调用该函数意味着您现在有一个字典:

    >>> def func(**params):
    ...     print params
    ... 
    >>> func()
    {}
    >>> func(params=None)
    {'params': None}
    >>> func(foo='bar')
    {'foo': 'bar'}
    

    该语法旨在接受任意关键字参数,如上面的 foo 关键字参数所示。

    要么删除**,要么测试空字典,调用.execute()时不要设置params=None

    def execute(self, statement, **params):
        if not params:
            self._curs.execute(statement)
        else:
            self._curs.execute(statement, params)
        # ...
    

    和:

    rows = sqlcnxn.execute("select * from demographics")
    

    请注意,您的execute() 函数没有return 语句,这意味着rows 将设置为None(函数的默认返回值)。如果您打算返回连接对象,请添加 return self 以便可以对其进行迭代。

    【讨论】:

    • 我不知道它总是创建字典。谢谢你。一个后续问题,当我测试像您推荐的行这样的空字典时,变为无。这是为什么呢?
    • @mnky9800n:你的函数没有返回任何东西;最后你忘了return self