为什么字符串连接会使用 Access 和 PYODBC 创建额外的参数?
Why does string concatenation create extra parameters using Access and PYODBC?
我创建了使用 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)
尝试使用符号:
Select "*-" & Service_Abbreviation & "-*"
此外,Like 需要用引号引起来的字符串,而您的子查询不需要 return。所以也许:
Select "'*-" & Service_Abbreviation & "-*'"
正如 OP 所发现的,MS Access 既是前端 GUI 应用程序又是后端数据库,在 运行 SQL 中的运行方式不同。通常,后端模式趋向于接近标准SQL,即:
- Quotes:在后端,单引号保留用于文字,双引号用于标识符,而不是在 MSAccess.exe 中可互换。
- 通配符:在后端,默认通配符
LIKE
使用%
,GUI使用*
除非运行访问SQL Server compatible syntax (ANSI 92) 中使用标准 %
的数据库。出于这个原因,考虑 Access' ALIKE
(ANSI-Like) 和 %
在两种访问模式下兼容。有趣的是,OP 使用的存储查询不是这种情况,但如果在代码中编写查询就会出现这种情况。
- 参数:在后端,查询中未识别的任何未引用对象都被视为命名参数并出错。同时,GUI 会启动一个弹出式 输入参数 框(初学者不知道这实际上是一个运行时错误),允许输入的答案在运行中进行评估。
- GUI 对象:在 GUI 中,Access 查询可以引用打开的表单和报表中的控件,甚至是独立 VBA 模块中定义的用户定义函数,这些相同引用将在后端出错,后端基本上以 headless 模式运行 Access,并且仅识别其他表和查询。
- 优化:请参阅 Allen Browne 在 optimizations 中的差异,这些差异在 GUI 与后端中创建查询时可能发生,尤其是引用 Access 对象库函数时。
顺便说一下,在子查询上使用 LIKE
会将一个标量计算为另一个标量。事实上,如果子查询 returns 超过一行,Access 将会出错,这在当前设置中可能会发生。
Error 3354: At most one record can be returned by this subquery
在其他数据库中,评估在子查询的第一行(没有 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 & '-%');
我创建了使用 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)
尝试使用符号:
Select "*-" & Service_Abbreviation & "-*"
此外,Like 需要用引号引起来的字符串,而您的子查询不需要 return。所以也许:
Select "'*-" & Service_Abbreviation & "-*'"
正如 OP 所发现的,MS Access 既是前端 GUI 应用程序又是后端数据库,在 运行 SQL 中的运行方式不同。通常,后端模式趋向于接近标准SQL,即:
- Quotes:在后端,单引号保留用于文字,双引号用于标识符,而不是在 MSAccess.exe 中可互换。
- 通配符:在后端,默认通配符
LIKE
使用%
,GUI使用*
除非运行访问SQL Server compatible syntax (ANSI 92) 中使用标准%
的数据库。出于这个原因,考虑 Access'ALIKE
(ANSI-Like) 和%
在两种访问模式下兼容。有趣的是,OP 使用的存储查询不是这种情况,但如果在代码中编写查询就会出现这种情况。 - 参数:在后端,查询中未识别的任何未引用对象都被视为命名参数并出错。同时,GUI 会启动一个弹出式 输入参数 框(初学者不知道这实际上是一个运行时错误),允许输入的答案在运行中进行评估。
- GUI 对象:在 GUI 中,Access 查询可以引用打开的表单和报表中的控件,甚至是独立 VBA 模块中定义的用户定义函数,这些相同引用将在后端出错,后端基本上以 headless 模式运行 Access,并且仅识别其他表和查询。
- 优化:请参阅 Allen Browne 在 optimizations 中的差异,这些差异在 GUI 与后端中创建查询时可能发生,尤其是引用 Access 对象库函数时。
顺便说一下,在子查询上使用 LIKE
会将一个标量计算为另一个标量。事实上,如果子查询 returns 超过一行,Access 将会出错,这在当前设置中可能会发生。
Error 3354: At most one record can be returned by this subquery
在其他数据库中,评估在子查询的第一行(没有 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 & '-%');