【问题标题】:Why does string concatenation create extra parameters using Access and PYODBC?为什么字符串连接会使用 Access 和 PYODBC 创建额外的参数?
【发布时间】:2020-02-19 18:07:36
【问题描述】:

我创建了我用 cursor.execute 方法调用的这个过程。我遇到的问题是 PYODBC 看到的参数比我给出的要多。 在此示例查询中,“-”和“-”被 PYODBC 作为额外参数读取。有谁知道为什么会这样?每当我在 Access 中进行任何字符串连接时都会发生这种情况。

def GetAccessResults(self):

    with pyodbc.connect(SQL.DBPath) as con:
        cursor = con.cursor()

        if self.parameters == None:
            cursor.execute('{{Call {}}}'.format(self.storedProc))
        else:
            callString = self.__CreateStoredProcString()
            cursor.execute(callString, self.parameters)

        returnValue = cursor.fetchall()

    return returnValue

def __CreateStoredProcString(self):

    questionMarks = ('?,' * len(self.parameters))[:-1]

    return '{{Call {} ({})}}'.format(self.storedProc, questionMarks)

【问题讨论】:

  • 由于您是动态构建 sql 的,因此您可以转储参数语句。如果您的列有空格或其他奇怪的字符(不好),那么用 [](方括号)将列名括起来。
  • PYODBC 看到的参数比我给出的更多 ...请发布实际错误和代码。
  • @Parfait 我在没有引号部分的情况下运行了这个完全相同的查询,并且查询在正确数量的参数下运行良好。一旦我将它们添加回来,无论引号中的内容是什么,PYODBC 都会添加两个参数。我用代码更新了我的帖子。
  • PYODBC 添加两个参数 ...再次,请在问题正文中逐字发布实际错误/异常。此外,尝试在存储的访问查询中使用单引号(双引号保留用于 SQL 标识符)。与 Access ODBC 相比,Access GUI 做了不同的事情。
  • @Parfait 抱歉,我认为添加异常不会为这里的问题增加任何价值。不过你是对的,解决了我的问题。一旦我切换到单引号,查询就会按预期运行。我只是花了太长时间试图弄清楚这一点。感谢您的帮助!

标签: python ms-access pyodbc


【解决方案1】:

正如 OP 所发现的,MS Access 作为前端 GUI 应用程序和后端数据库在运行 SQL 时的操作方式不同。通常,后端模式往往更接近标准 SQL,即:

  • 引号:在后端,单引号为文字保留,双引号为标识符保留,而不是在 MSAccess.exe 中可互换。
  • 通配符:在后端,默认情况下LIKE 的通配符使用%,GUI 使用*,除非在SQL Server compatible syntax (ANSI 92) 中运行使用标准% 的Access 数据库。出于这个原因,考虑 Access' ALIKE (ANSI-Like) 和 % 在两种访问模式下都兼容。有趣的是,OP 使用的存储查询并非如此,但在代码中编写查询时会出现这种情况。
  • 参数:在后端,任何未在查询中识别的未引用对象都被视为命名参数并出错。同时,GUI 会弹出一个 Enter Parameter 框(初学者不知道这实际上是运行时错误),允许对输入的答案进行即时评估。
  • GUI 对象:虽然在 GUI 中,Access 查询可以引用打开的表单和报告中的控件,甚至是在独立 VBA 模块中定义的用户定义函数,但这些相同的引用将在后端出错,实际上在 headless 模式,只识别其他表和查询。
  • 优化:查看 Allen Browne 在optimizations 中的差异,在 GUI 与后端创建查询时可能会出现这种差异,尤其是在引用 Access 对象库函数时。

顺便说一句,在子查询上使用LIKE 会将一个标量计算为另一个标量。事实上,如果子查询返回多于一行,而当前设置可能会出现这种情况,Access 就会出错。

错误 3354:此子查询最多可以返回一条记录

在其他数据库中,评估运行在子查询的第一行(没有ORDER BY 可以是随机行),而不是子查询的所有记录。相反,考虑重构 SQL 以使用 EXISTS 子句:

PARAMETERS prmServiceName Tex(255);
SELECT c.* 
FROM Charts c
WHERE EXISTS
  (SELECT 1 
   FROM Services s
   WHERE s.ServiceName = prmService_Name
     AND c.FileName ALIKE '%-' & s.Service_Abbreviation & '-%');

【讨论】:

  • 这太棒了,我得到的东西比我预想的要多。再次感谢您的帮助!
【解决方案2】:

尝试使用 & 符号:

Select "*-" & Service_Abbreviation & "-*"

另外,Like 需要一个用引号括起来的字符串,而您的子查询不会返回它。所以也许:

Select "'*-" & Service_Abbreviation & "-*'"

【讨论】:

  • 我原来是这样试的,还是不行。
  • 为什么不起作用?请发布 Python 错误/异常和代码。这可能是由于您的实施。
  • 在返回值中添加了引号。
  • 这也不起作用。我发布的查询在 Access 中运行时工作正常,只是尝试使用 PYODBC 查询它会导致文件由于额外的参数。当我添加 ' 时,查询无法在 Access 中返回任何结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
相关资源
最近更新 更多