You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

获取SQL Server备份BAK文件中的数据库名后,连接数据库查询表名时遇登录失败错误的求助

获取SQL Server备份BAK文件中的数据库名后,连接数据库查询表名时遇登录失败错误的求助

嘿,我一眼就看出问题所在啦——你犯了一个很容易忽略的小错误:你只是读取了备份文件的元数据(用RESTORE FILELISTONLY),但并没有把BAK文件里的数据库实际还原到你的SQL Server实例中

你拿到的database_name只是备份文件里记录的数据库名称,但这个数据库在你的本地SQL Server Express里根本还不存在,所以当你尝试连接它的时候,SQL Server会报错说找不到这个数据库,进而触发登录失败的提示。

下面是完整的解决步骤和修正后的代码:

核心解决思路

  1. 先把BAK文件中的数据库完整还原到你的SQL Server实例中
  2. 还原完成后,再连接该数据库查询表名
  3. 最后实现导出表到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

火山引擎 最新活动