tsql 实用程序 (FreeTDS) 可以连接到 SQL Server,但 pymssql 不能

Posted

技术标签:

【中文标题】tsql 实用程序 (FreeTDS) 可以连接到 SQL Server,但 pymssql 不能【英文标题】:tsql utility (FreeTDS) can connect to SQL Server but pymssql cannot 【发布时间】:2016-11-16 10:56:32 【问题描述】:

我遇到了一个非常奇怪的问题:我可以使用 tsql 连接到我的 SQL Server,但我无法使用 pymssql 做同样的事情。让我告诉你更多细节。

使用这种tsql 命令似乎一切正常:

$ tsql -H '10.10.10.2' -U 'DOMAIN\myuser' -p 63849
Password: 
locale is "fr_FR.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1>

但是使用以下基本 python 脚本我遇到了一个问题:

$ cat test_mssql.py
# -*- coding: utf8 -*-
import pymssql
import pandas as pd

conn = pymssql.connect(server=r'10.10.10.2', user=r'DOMAIN\myuser', password='mypassword', port='63849')

$ python test_mssql.py
Traceback (most recent call last):
File "api-vinci-rh/current/test_mssql.py", line 60, in <module>
conn = pymssql.connect(server=r'10.10.10.2', user=r'DOMAIN\myuser', password='mypassword', port='63849')
File "pymssql.pyx", line 641, in pymssql.connect (pymssql.c:10788)
pymssql.OperationalError: (20002, 'DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed\n')

通过激活 TDSDUMPCONFIG 环境变量,我可以看到 tls 命令和我的 python 脚本之间的区别:

TDSDUMPCONFIG tls trace
config.c:224:Final connection parameters:
config.c:225:            server_name = 10.10.10.2
config.c:226:       server_host_name = 10.10.10.2
config.c:227:                ip_addr = 10.10.10.2
config.c:228:          instance_name = 
config.c:229:                   port = 63849
config.c:230:          major_version = 7
config.c:231:          minor_version = 1
config.c:232:             block_size = 0
config.c:233:               language = us_english
config.c:234:         server_charset = 
config.c:235:        connect_timeout = 0
config.c:236:       client_host_name = myhost
config.c:237:         client_charset = UTF-8
config.c:238:               app_name = TSQL
config.c:239:              user_name = DOMAIN\myuser
config.c:242:                library = TDS-Library
config.c:243:              bulk_copy = 0
config.c:244:      suppress_language = 0
config.c:245:          encrypt level = 0
config.c:246:          query_timeout = 0
config.c:249:               database = 
config.c:250:              dump_file = /tmp/freetds.log
config.c:251:            debug_flags = 0


TDSDUMPCONFIG pymssql trace
config.c:224:Final connection parameters:
config.c:225:            server_name = 10.10.10.2:63849
config.c:226:       server_host_name = 10.10.10.2
config.c:227:                ip_addr = 10.10.10.2
config.c:228:          instance_name = 
config.c:229:                   port = 63849
config.c:230:          major_version = 7
config.c:231:          minor_version = 1
config.c:232:             block_size = 0
config.c:233:               language = us_english
config.c:234:         server_charset = 
config.c:235:        connect_timeout = 0
config.c:236:       client_host_name = myhost
config.c:237:         client_charset = UTF-8
config.c:238:               app_name = pymssql=2.1.2
config.c:239:              user_name = 
config.c:242:                library = DB-Library
config.c:243:              bulk_copy = 0
config.c:244:      suppress_language = 0
config.c:245:          encrypt level = 0
config.c:246:          query_timeout = 0
config.c:249:               database = 
config.c:250:              dump_file = /tmp/freetds.log
config.c:251:            debug_flags = 0
config.c:252:              text_size = 64512
config.c:253:           broken_dates = 0
config.c:254:     emul_little_endian = 0
config.c:255:      server_realm_name = 

我认为两个主要区别在于 user_name 与 python 脚本为空,libraryDB-Library 而不是 TDS-Library

我目前找不到在 python 脚本中强制使用这些参数的方法,也找不到关于我的问题的任何线索(错误消息是通用的)。

我正在使用 python 2.7.9 和 pymssql==2.1.2 有关我的环境的更多信息:

$ tsql -C
Compile-time settings (established with the "configure" script)
                            Version: freetds v0.91
             freetds.conf directory: /etc/freetds
     MS db-lib source compatibility: no
        Sybase binary compatibility: yes
                      Thread safety: yes
                          iconv library: yes
                        TDS version: 4.2
                              iODBC: no
                           unixodbc: yes
              SSPI "trusted" logins: no
                           Kerberos: yes

$ grep -v '^#' /etc/freetds/freetds.conf 
[global]
    tds version = 7.1
    dump file = /tmp/freetds.log
    text size = 64512
    enable gssapi delegation = off

如果你有任何线索可以帮助我。

编辑:我有另一个 SQL Server 实例用于我的测试,并且我的 python 脚本工作... TDSDUMPCONFIG 中的username 已设置。所以我猜我的环境中有一些奇怪的东西,但不知道是什么

【问题讨论】:

Adaptive Server connection ?这闻起来像 Sybase。您确定您没有错误地使用 Sybase 提供程序吗?微软在 20 年前购买了代码...... Adaptive Server。两家公司都使用 TDS 和 T-SQL 等名称 无论如何,您没有发布任何 T-SQL 代码。您发布的是不同命令行工具的命令行参数。 tsql 是一个 FreeTDS 实用程序。除非您的 Python 代码使用 FreeTDS,否则您不能使用 tsql 的结果作为您的代码正常的指示 @PanagiotisKanavos 你说得对:我没有发布 T-SQL 代码,但我可以通过 tsql 客户端确认我可以请求数据 @PanagiotisKanavos - (1) FreeTDS 经常返回引用“自适应服务器”的错误消息,即使在连接到 Microsoft SQL Server 时也是如此。 (2) pymssql 构建在 FreeTDS 之上,因此如果 Python 代码使用 pymssql,那么它(间接)使用 FreeTDS。 【参考方案1】:

我找到了一条线索,我对此感到非常惊讶...如果我使用少于 32 个字符的 username,我对 pymssql 没有更多问题!我没有发现任何关于这个奇怪的错误 (?) 但我保证它可以解决我的问题。

我需要查看pymssql 的代码,看看我是否发现任何关于username 长度的限制或问题

【讨论】:

感谢您报告您的发现。您遇到的限制在here 中讨论。好消息是,pymssql 的当前和未来版本不应该受到影响,因为高于 v0.91 的 FreeTDS 版本已被修补,允许通过 db-lib API 使用更长的用户名和密码,这是 pymssql 使用的 API。跨度> 感谢您提供这些详细信息@GordThompson :) 我错过了!

以上是关于tsql 实用程序 (FreeTDS) 可以连接到 SQL Server,但 pymssql 不能的主要内容,如果未能解决你的问题,请参考以下文章

尝试从 tsql 连接到 sql-azure 时从服务器读取失败

如何从 php 连接到 mssql?

连接到 MSSQL DB 的问题

[S1000][unixODBC][FreeTDS][SQL Server]无法连接到数据源

为啥我可以使用 tsql 而不是 pymssql 连接到 Azure MS SQL?

从 mac osx 10.11 连接到带有 RODBC 的 MS SQL 服务器