获取SQL Server备份BAK文件中的数据库名后,连接数据库查询表名时遇登录失败错误的求助
获取SQL Server备份BAK文件中的数据库名后,连接数据库查询表名时遇登录失败错误的求助
嘿,我一眼就看出问题所在啦——你犯了一个很容易忽略的小错误:你只是读取了备份文件的元数据(用RESTORE FILELISTONLY),但并没有把BAK文件里的数据库实际还原到你的SQL Server实例中!
你拿到的database_name只是备份文件里记录的数据库名称,但这个数据库在你的本地SQL Server Express里根本还不存在,所以当你尝试连接它的时候,SQL Server会报错说找不到这个数据库,进而触发登录失败的提示。
下面是完整的解决步骤和修正后的代码:
核心解决思路
- 先把BAK文件中的数据库完整还原到你的SQL Server实例中
- 还原完成后,再连接该数据库查询表名
- 最后实现导出表到CSV的逻辑
完整修正代码
from sqlalchemy import create_engine, text import pandas as pd # 基础配置信息 driver = 'ODBC Driver 17 for SQL Server' server = r'.\SQLEXPRESS' file_path_bak = r'C:\Users\ganes\Downloads\New folder (3)\StackOverflowMini_database.bak' # 还原后数据文件/日志文件的存放路径(请根据你的SQL Server实例路径修改) restore_data_path = r'C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\DATA\' # 第一步:连接master数据库,完成数据库还原 master_engine = create_engine(f'mssql+pyodbc://{server}/master?driver={driver}&trusted_connection=yes') with master_engine.connect() as conn: # 获取备份文件中的所有文件元数据(数据文件MDF + 日志文件LDF) result = conn.execute(text(f"RESTORE FILELISTONLY FROM DISK = '{file_path_bak}'")) file_list = result.fetchall() # 提取备份中的数据库名称 database_name = file_list[0][0] # 构造还原时的文件映射规则:将备份中的逻辑文件指向本地物理路径 move_clauses = [] for file in file_list: logical_file_name = file[0] original_physical_path = file[2] # 提取原文件名,替换为本地指定的存储路径 local_file_path = restore_data_path + original_physical_path.split('\\')[-1] move_clauses.append(f"MOVE '{logical_file_name}' TO '{local_file_path}'") # 构造完整的数据库还原语句 restore_sql = f""" RESTORE DATABASE [{database_name}] FROM DISK = '{file_path_bak}' WITH {', '.join(move_clauses)}, REPLACE """ # 执行还原操作(大备份文件需要等待一段时间) conn.execute(text(restore_sql)) # 显式提交事务确保还原完成 conn.commit() # 关闭master数据库连接 master_engine.dispose() # 第二步:连接已还原的数据库,查询所有用户表 db_engine = create_engine(f'mssql+pyodbc://{server}/{database_name}?driver={driver}&trusted_connection=yes') with db_engine.connect() as conn: result = conn.execute(text(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' """)) table_names = [row[0] for row in result.fetchall()] print(f"数据库 {database_name} 中的用户表:{table_names}") # 第三步:将每个表导出为CSV文件 for table in table_names: # 用pandas快速读取表数据(无需手动处理游标) table_data = pd.read_sql_table(table, db_engine) # 保存为CSV,指定编码避免中文乱码 table_data.to_csv(f"./{table}_export.csv", index=False, encoding='utf-8-sig') print(f"已成功导出表 {table} 到本地CSV文件") # 关闭目标数据库连接 db_engine.dispose()
重要注意事项
- 路径权限:确保你指定的
restore_data_path目录,SQL Server服务账户(通常是NT SERVICE\MSSQL$SQLEXPRESS)有读写权限,否则还原会失败。 - WITH REPLACE选项:如果你的SQL Server中已经存在同名数据库,这个选项会直接覆盖它;如果不想覆盖,可以删除该选项,或者先重命名/删除现有数据库。
- 还原耗时:如果备份文件体积较大,还原操作会需要一定时间,不要中途终止程序。
- CSV导出:使用pandas是最简便的方式,如果你不想依赖pandas,也可以用SQLAlchemy游标逐行读取数据,再手动写入CSV文件。
备注:内容来源于stack exchange,提问作者Fish1996




