SQL Server 函数本地参数绑定错误

7 投票
1 回答
1550 浏览
提问于 2025-04-16 00:35

我在使用Ubuntu 10.04 Lucid LTS系统,连接数据库时用的是以下软件:

  1. python 2.6.5(这是Ubuntu自带的软件包)
  2. pyodbc的最新代码版本 eb545758079a743b2e809e2e219c8848bc6256b2
  3. unixodbc 2.2.11(也是Ubuntu自带的软件包)
  4. freetds 0.82(同样是Ubuntu自带的软件包)
  5. Windows系统上的Microsoft SQL Server 2000(8.0版本)

当我尝试在SQL SERVER函数的参数中使用本地参数绑定时,出现了这个错误:

Traceback (most recent call last):
 File "/home/nosklo/devel/testes/sqlfunc.py", line 32, in <module>
   cur.execute("SELECT * FROM fn_FuncTest(?)", ('test',))
pyodbc.ProgrammingError: ('42000', '[42000] [FreeTDS][SQL
Server]SqlDumpExceptionHandler: Process 54 generated fatal exception
c0000005 EXCEPTION_ACCESS_VIOLATION. SQL Server is terminating this
process.\r\n (0) (SQLPrepare)')

这是我用来重现问题的代码:

import pyodbc
constring = 'server=myserver;uid=uid;pwd=pwd;database=db;TDS_Version=8.0;driver={FreeTDS}'

con = pyodbc.connect(constring)
print 'VERSION: ', con.getinfo(pyodbc.SQL_DBMS_VER)

cur = con.cursor()
try:
   cur.execute('DROP FUNCTION fn_FuncTest')
   con.commit()
   print "Function dropped"
except pyodbc.Error:
   pass

cur.execute('''
   CREATE FUNCTION fn_FuncTest (@testparam varchar(4))
   RETURNS @retTest TABLE (param varchar(4))
   AS
   BEGIN
       INSERT @retTest
       SELECT @testparam
       RETURN
   END''')
con.commit()

现在函数已经创建好了。如果我直接在查询中使用一个值(不使用本地绑定),那是可以正常工作的:

cur.execute("SELECT * FROM fn_FuncTest('test')")
assert cur.fetchone()[0] == 'test'

但是当我尝试使用本地绑定(通过使用参数占位符并单独传递值)时,就会出现上面的错误:

cur.execute("SELECT * FROM fn_FuncTest(?)", ('test',))

进一步调查后,我发现了一些奇怪的事情,想和大家分享:

  • 如果我把TDS版本改成4.2,一切都能正常工作(不过,SQL Server报告的版本不对——使用TDS版本4.2时,我得到的是'95.08.0255',而不是实际版本'08.00.0760')。
  • 对于其他两种类型的函数,一切都能正常工作——返回值的函数和仅仅是SELECT查询的函数(像视图那样)都能正常运行。你甚至可以定义一个新函数,返回对另一个(出问题的)函数的查询结果,这样一切都会正常工作,即使在参数上使用本地绑定。例如:CREATE FUNCTION fn_tempFunc(@testparam varchar(4)) RETURNS TABLE AS RETURN (SELECT * FROM fn_FuncTest(@testparam))
  • 在出现这个错误后,连接变得非常不稳定,无法恢复。
  • 这个错误在尝试绑定任何类型的数据时都会发生。

我该如何进一步解决这个问题?我希望能对函数参数进行本地绑定。

1 个回答

0

最后,这可能不是你想要的答案,但大约两三年前我在用Perl连接MSSQL时,最开始用的是ODBC和FreeTDS,但我没能成功(虽然我不记得具体的错误了,但我当时在尝试绑定,似乎这也是问题的来源之一)。

在这个Perl项目中,我最后使用了一个为Sybase设计的驱动程序(MSSQL是从Sybase分出来的),所以你可以考虑看看这个方向。

Python的维基上有关于Sybase和SQL Server的页面,你可能会想去看看,寻找其他的替代方案:

http://wiki.python.org/moin/Sybase

http://wiki.python.org/moin/SQL%20Server

撰写回答