SQL Server 连接 skill
连接 SQL Server(MES、ERP 或其他业务库)并执行只读查询、导出数据。重点保证最小权限 + 环境兼容。
适用场景
- 连接 MES / ERP 等 SQL Server 业务库做数据查询、表结构探查、CSV 导出
- 需要创建只读账号(无 UPDATE / DELETE / INSERT)
- 排查 pyodbc 连接报错(18456、4060、TLS 协议不兼容、端口超时、无效连接属性)
前置条件(连接前自检)
- ODBC 驱动:系统需安装
ODBC Driver 17 for SQL Server(旧版SQL Server/SQL Server Native Client 11.0也可用)。- 检查:PowerShell 读
HKLM:\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers
- 检查:PowerShell 读
- Python 包:
pyodbc(已验证 5.3.0 可用)。pymssql非必需。 - 网络:本机需能 TCP 到达服务器 IP:端口(默认 1433)。
标准连接串(pyodbc)
import pyodbc
conn = pyodbc.connect(
"DRIVER={ODBC Driver 17 for SQL Server};"
f"SERVER={server},{port};" # 例如 "SERVER=10.0.0.5,1433"
f"DATABASE={database};"
f"UID={user};PWD={password};"
"TrustServerCertificate=yes;" # ← SQL 2008 R2 必须,否则证书握手失败
"Login Timeout=10;", # ← 注意是 Login Timeout,不是 Timeout(后者不是有效 ODBC 属性)
autocommit=True
)
SQL 2008 R2 关键兼容项:必须加 TrustServerCertificate=yes。若服务器强制加密且客户端 TLS 版本过低,关闭加密(Encrypt=no)或升级驱动。
只读账号配置(SSMS)
- 登录名 → 服务器角色:仅
public - 切换到「用户映射」→ 勾选目标库 → 数据库角色成员身份:
- ✅
db_datareader(允许 SELECT) - ✅
public - ❌ 不要勾
db_datawriter(含 INSERT/UPDATE/DELETE) - ❌ 不要勾
db_owner
- ✅
- 更细粒度:
GRANT SELECT ON dbo.表 TO 用户名;
已知坑与排查(按出现频率)
坑1:连接串里的无效属性会触发连锁报错
- 现象:
Invalid connection string attribute (0)出现在错误里,同时附带18456/4060等看似不相关的错误,极具迷惑性。 - 根因:连接串中写了
Timeout=10(不是有效 ODBC 属性)→ 驱动解析失败,连带导致后续登录/打开库逻辑异常。 - 解决:超时属性必须写成
Login Timeout=10(或Connection Timeout)。pyodbc/ODBC Driver 17 不认裸Timeout。 - 注意:无效属性是「真凶」时,18456/4060 只是连带产物,修掉属性后往往直接连上。
坑2:18456 与 4060 的区别(分阶段定位)
- 18456 = 登录被拒(账号不存在 / 密码错 / 实例不对)。先连
master(不指定 DATABASE)单独验证登录。 - 4060 = 登录成功但打不开目标库(账号未映射到该库 / 库名拼错 / 连错实例)。此时阶段1连 master 会成功,阶段2开目标库才报 4060。
- 模板已内置两阶段:先连 master 验证登录,再连目标库;4060 时自动列出当前账号可访问的库,方便排查映射。
坑3:登录名拼写一致性
- 真实案例:登录名拼写差一个字母(如把
readuser误写成readusr)→ 服务器无此登录 → 18456。 - 务必与 SSMS/VSCode 中实际登录名逐字核对。建议 SSMS 执行
SELECT name FROM sys.server_principals WHERE name LIKE '%关键字%'看真实拼写。
坑4:端口号与版本号别混淆
- SSMS/VSCode 标题栏里的
SQL Server 10.50.1600是产品版本号(SQL Server 2008 R2 SP1 的 build 号),不是端口。 - 默认实例端口是 1433;命名实例才监听非标准端口。端口自查:SQL Server 配置管理器 → TCP/IP → IP 地址 → TCP 端口。
坑5:ODBC Driver 17 不支持 Encrypt=Mandatory
- 用
Encrypt=yes|no而非Mandatory(会报Invalid value specified for connection string attribute 'Encrypt')。
坑6:沙箱/本地脚本报 18456,先查拼写与连接串属性
- 教训:WorkBuddy 沙箱或本地脚本连
IP:1433报 18456,先怀疑登录名拼写 / 连接串属性,而不是「沙箱网络身份被 SQL Server 区分」。 - 验证方法:用本 skill 模板先在沙箱内试连;能连就直接在 WorkBuddy 里跑只读查询,无需用户在外部终端操作。
脚本模板(生成给用户独立运行)
见 scripts/connect_template.py,参数化 server/port/database/user/password,支持:
- 分阶段连接测试(先连 master 验证登录,再连目标库)
- 列出前 20 张表 / 自定义查询 / 导出 CSV
- 密码走环境变量
DB_PWD或交互输入(不落盘)
用法:
python connect_template.py --server {ip} --port 1433 --database {db} --user {readonly_user}
例如:
python connect_template.py --server 10.0.0.5 --port 1433 --database MESDB --user readonly_user
安全约束
- 凭据仅用于本次连接,不写入任何持久化文件或记忆。
- 默认只读账号;除非用户明确要求,不授予写权限。
- 敏感密码不要硬编码在脚本里——用交互输入或环境变量
os.getenv("DB_PWD")。
微信扫一扫