同一SQL Server实例跨库执行存储过程报sys.servers找不到服务器错误
问题原因及解决方案
你的代码存在两处关键错误,导致了这个报错:
1. 错误的ODBC连接字符串
你在pyodbc.connect()里重复设置了Driver、Server、Database参数,这不符合ODBC连接规范——一个ODBC连接只能指向单个数据库(同一SQL Server实例下)。同一实例内的其他数据库,只需通过数据库名.架构名.表名的格式直接引用即可,无需在连接字符串中重复配置。
2. 错误的数据库变量拼接
你执行了ABC_database=f'{ABC_database}.dbo',之后在SQL语句中引用表时就变成了{ABC_database}.dbo.{tab},最终生成的SQL会是ABC.dbo.dbo.TABLE_NAME_HERE。SQL Server会将这种格式解析为[服务器名].[数据库名].[架构名].[表名],所以它误以为ABC是一个链接服务器,从而抛出找不到服务器的错误。
修正后的代码
import pyodbc import logging import json import time def pop_abc_insert(): # 配置日志(添加控制台输出) logger = logging.getLogger() logger.setLevel(logging.INFO) if not logger.handlers: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) start_time = time.time() with open(r'upsert_config.json','r') as ts: config = json.load(ts) ABC_driver = config['ABC_layer']['ABC_driver'] ABC_server = config['ABC_layer']['ABC_server'] ABC_database = config['ABC_layer']['ABC_database'] POP_database = config['POP_layer']['POP_database'] # 修正连接字符串:只连接到同一实例下的一个数据库即可 conn = pyodbc.connect( f'Driver={ABC_driver};' f'Server={ABC_server};' f'Database={ABC_database};' f'Trusted_Connection=yes;' f'MARS_Connection=Yes' ) try: cursor = conn.cursor() read_table_query=""" SELECT table_name FROM information_schema.tables WHERE table_name = 'TABLE_NAME_HERE' ORDER BY table_name asc """ cursor.execute(read_table_query) logger.info("Successfully connected to database") except Exception as e: logger.error("Unable to connect to database: %s", str(e)) return for tables in cursor.fetchall(): tab = tables[0] # 修正表引用格式:直接用 数据库名.dbo.表名 ABC_POP_query = f""" update {POP_database}.dbo.{tab} SET Active_ind = 0, expiry_date = GETDATE(), updated_date = GETDATE() WHERE convert(varbinary,hash_key )IN ( SELECT convert(varbinary,T1.hash_key) FROM {ABC_database}.dbo.{tab} T1 LEFT JOIN {POP_database}.dbo.{tab} T2 ON convert(varbinary,T1.hash_key) = convert(varbinary,T2.hash_key) WHERE convert(varbinary,T1.hash_dif) <> convert(varbinary,T2.hash_dif) AND T1.Active_ind = 1 ) AND Active_ind = 1 insert into {POP_database}.dbo.{tab} select * from {ABC_database}.dbo.{tab} WHERE convert(varbinary,hash_key) IN ( SELECT convert(varbinary,T1.hash_key) FROM {ABC_database}.dbo.{tab} T1 LEFT JOIN {POP_database}.dbo.{tab} T2 ON convert(varbinary,T1.hash_key) = convert(varbinary,T2.hash_key) WHERE convert(varbinary,T1.hash_dif) <> convert(varbinary,T2.hash_dif) AND T1.Active_ind = 1) insert into {POP_database}.dbo.{tab} select * from {ABC_database}.dbo.{tab} WHERE convert(varbinary, hash_key) NOT IN ( SELECT convert(varbinary,T2.hash_key) FROM {POP_database}.dbo.{tab} T2 WHERE T2.Active_ind = 1) """ try: cursor.execute(ABC_POP_query) conn.commit() # 提交事务,确保修改生效 logger.info(f"Successfully processed table: {tab}") except Exception as e: conn.rollback() # 出错回滚 logger.error(f"Error processing table {tab}: %s", str(e)) conn.close() logger.info(f"Process completed in {time.time() - start_time:.2f} seconds") pop_abc_insert()
额外说明
- 你的JSON配置文件无需修改,因为配置的服务器和数据库信息是正确的。
- 新增了事务提交/回滚逻辑,避免出现部分更新的情况。
- 完善了日志配置,确保能看到运行时的日志信息。
内容的提问来源于stack exchange,提问作者Forgottenluv
相关产品推荐
相关产品推荐

