如何用Pandas遍历SQL Server表列表并导出CSV?排查执行报错
SQL Server表导出CSV的问题排查与修复
问题场景
尝试通过Python从SQL Server导出所有基表为CSV文件,原始代码如下:
import pyodbc import pandas as pd cnxn_string = conn_str = pyodbc.connect( 'Driver=ODBC Driver 17 for SQL Server;' 'Server=server;' 'Database=database;' 'Trusted_Connection=yes;' ) select_all_tables_query = pd.read_sql_query("""SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE'""", cnxn_string) df_all_tables=pd.DataFrame(select_all_tables_query) tables = df_all_tables['table_name'] for table in tables: sql_query=pd.read_sql_query("SELECT * FROM {table}", cnxn_string) df=pd.DataFrame(sql_query) df.to_csv(r'C:\path\{table}', index=False)
执行后出现语法错误:
pandas.errors.DatabaseError: Execution failed on sql 'SELECT * FROM {table}': ('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server]Syntax error, permission violation, or other nonspecific error (0) (SQLExecDirectW)')
改为f-string后无输出,且收到警告:
c:\path_to_python_file.py:19: UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy. sql_query=pd.read_sql_query(f"SELECT * FROM {table}", cnxn_string)
错误原因分析
- 字符串未正确格式化:原始代码中
"SELECT * FROM {table}"是普通字符串,Python不会替换{table}变量,导致SQL语句直接包含{table},触发语法错误。改为f-string后虽解决了替换问题,但仍存在循环逻辑错误。 - 循环逻辑错误:数据转换和导出代码写在循环外部,只会处理最后一个表的查询结果;同时CSV路径中的
{table}未做格式化,无法生成对应表名的文件。 - pandas连接兼容性警告:pandas官方更推荐使用SQLAlchemy连接而非原生pyodbc连接,虽然pyodbc仍可工作,但会触发兼容性警告。
修复后的完整代码
import pyodbc import pandas as pd # 建立数据库连接 conn = pyodbc.connect( 'Driver=ODBC Driver 17 for SQL Server;' 'Server=server;' # 替换为实际服务器名 'Database=database;' # 替换为实际数据库名 'Trusted_Connection=yes;' ) # 获取所有基表名称 tables_df = pd.read_sql_query( """SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE'""", conn ) table_names = tables_df['table_name'].tolist() # 循环导出每个表为CSV output_dir = r'C:\path' # 替换为实际输出目录 for table in table_names: # 用方括号包裹表名,避免表名是SQL关键字导致报错 query = f"SELECT * FROM [{table}]" df = pd.read_sql_query(query, conn) # 生成带表名的CSV路径 csv_path = f"{output_dir}\\{table}.csv" df.to_csv(csv_path, index=False, encoding='utf-8-sig') # 用utf-8-sig避免中文乱码 # 关闭连接 conn.close()
关键修复点
- 用f-string正确格式化SQL语句和CSV路径,确保
{table}被实际表名替换。 - 将数据导出代码放入循环内部,保证每个表都被处理并生成对应文件。
- 用
[{table}]包裹表名,避免表名是SQL关键字(如User、Order)时触发语法错误。 - 添加编码参数
encoding='utf-8-sig',避免导出的CSV文件中文乱码。 - 明确关闭数据库连接,释放资源。
关于pandas连接警告的处理
如果想消除警告,可改用SQLAlchemy建立连接,示例代码如下:
from sqlalchemy import create_engine import pandas as pd # 构建SQLAlchemy连接字符串 conn_str = "mssql+pyodbc://server/database?driver=ODBC+Driver+17+for+SQL+Server&trusted_connection=yes" engine = create_engine(conn_str) # 后续查询和导出逻辑与上面一致,只需将conn替换为engine
内容的提问来源于stack exchange,提问作者testmythoughts
相关产品推荐
相关产品推荐

