我有一个运行 SQL Server 2008 R2 Express Edition 的旧数据库。
今天,我尝试使用
sqlacodegen
通过 pyodbc
包生成 SQLAlchemy 类。我能够毫无问题地连接到数据库,但我遇到了由 SQLAlchemy 生成的以下查询的立即错误:
SELECT
CAST(com.value AS nvarchar(max))
FROM
fn_listextendedproperty('MS_Description',
'schema', CAST(? AS NVARCHAR(max)), 'table', CAST(? AS NVARCHAR(max)), NULL, NULL) AS com;
具有以下参数:
[('dbo', 'Accounting')]
错误如下:
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]'CAST'附近的语法不正确。(102) (SQLExecDirectW); [42000] [Microsoft][适用于 SQL Server 的 ODBC 驱动程序 18][SQL 服务器]无法准备语句。 (8180)")
但是,当我用
'dbo'
和 'Accounting'
替换准备好的语句通配符,然后在 SQL Server Management Studio 中运行它时,查询运行良好。
然后我尝试使用
sqlcmd
并得到与通过 Python 运行代码时完全相同的错误,证明这不是 SQLAlchemy 或 pyodbc
错误:
1> SELECT
2> cast ( com.value as nvarchar(max) )
3> FROM
4> fn_listextendedproperty
5> (
6> 'MS_Description'
7> , 'schema'
8> , cast ( 'dbo' as nvarchar(max) )
9> , 'table'
10> , cast ( 'Accounting' as nvarchar(max) )
11> , NULL
12> , NULL
13> ) as com
14> go
消息 156,级别 15,状态 1,服务器 SERVER,第 8 行
“CAST”附近的语法不正确。
我什至根据
一些文档替换了
{ fn convert ('dbo', SQL_LONGVARCHAR) }
,但这没有帮助。
然后,我对不同的 Azure SQL Server 数据库运行了类似的查询,都使用门户中的在线查询编辑器和 SQLAlchemy ODBC 连接,并且都成功了。
我还尝试了我拥有的所有不同的可用驱动程序(
'SQL Server'
、'SQL Server Native Client 10.0'
、'ODBC Driver 18 for SQL Server'
、'ODBC Driver 17 for SQL Server'
、'ODBC Driver 13 for SQL Server'
、'ODBC Driver 11 for SQL Server'
)以及连接字符串选项的各种排列(仅TrustServerCertificate=Yes;
)
对 'ODBC Driver 18'
有帮助),但没有任何作用。然而我尝试的所有查询都在 SSMS 中成功执行。
我可以通过 ODBC 运行查询的唯一方法是为两个有问题的参数声明并设置变量
fn_listextendedproperties
:
DECLARE @schemaname NVARCHAR(max)
SET @schemaname = { fn convert ( 'dbo', SQL_LONGVARCHAR ) }
DECLARE @tablename NVARCHAR(max)
SET @tablename = { fn convert ( 'Accounting', SQL_LONGVARCHAR ) }
SELECT
CONVERT(nvarchar(max), com.value)
FROM
fn_listextendedproperty ('MS_Description',
'schema', @schemaname,
'table', @tablename,
NULL, NULL) AS com
导致这些错误的原因是什么? SQL Server 2008 R2 是否存在某种错误,或者我没有正确配置 ODBC 连接?
根据 @siggemannen 的评论,我运行了以下命令:
select cmptlevel, @@OPTIONS & 256 from sys.sysdatabases where name = DB_NAME()
输出是:
cmpt级别 | (无列名) |
---|---|
80 | 256 |
根据Microsoft 的文档,这表示与 SQL Server 2000 的兼容性级别。
我在
master
中运行以下命令来更新与 SQL Server 2008 R2 的兼容性级别:
ALTER DATABASE <dbname>
SET COMPATIBILITY_LEVEL = 100
此后,我可以毫无问题地运行查询。
此外,我发现我无意中针对
master
数据库运行 SSMS 查询,该数据库的兼容性级别已经为 100。当我在 SSMS 中针对我感兴趣的数据库运行查询时,我得到了与我是用 ODBC 做的。