使用write_pandas向Snowflake上传DataFrame时表不存在问题排查
问题:使用write_pandas上传DataFrame到Snowflake时提示“表不存在”
问题重现
尝试用write_pandas将DataFrame上传到Snowflake,已创建数据库,但执行上传时报错“表不存在”,代码如下:
from snowflake.connector.pandas_tools import write_pandas conn = sf.connect(user=snow_username, password=snow_password, account=snow_account, wharehouse=snow_wharehouse, database= database, schema=schema) cur = conn.cursor() query = f"Use Database {database}" cur.execute(query) channel_name = "testdeb" query = (f'''CREATE TABLE IF NOT EXISTS {channel_name} ( sepal_length INTEGER, sepal_width INTEGER NOT NULL, petal_length INTEGER NOT NULL, petal_widht INTEGER NOT NULL) ''') cur.execute(query) success, nchunks, nrows, _ = write_pandas(conn, test_df, channel_name)
错误信息:
ProgrammingError: 001757 (42601): SQL compilation error:
Table '"testdeb"' does not exist
但使用SQLAlchemy可以正常上传:
conn_string = f"snowflake://{snow_username}:{snow_password}@{snow_account}/{snow_database}/{snow_schema}?warehouse={snow_wharehouse}" engine = create_engine(conn_string) connection = engine.connect() if_exists = 'replace' with engine.connect() as con: test_df.to_sql(name=channel_name.lower(), con=con, if_exists=if_exists,index=False)
原因分析
核心问题是表名大小写处理差异和会话schema上下文不一致:
- 大小写敏感性冲突:
- Snowflake默认会将未加双引号的标识符(如表名)转换为大写。你创建表时用的是
CREATE TABLE IF NOT EXISTS {channel_name},实际创建的是大写表TESTDEB。 - 但
write_pandas默认会给表名加上双引号(从错误信息里的"testdeb"可验证),此时它会严格查找小写的testdeb表,自然找不到实际存在的大写表。
- Snowflake默认会将未加双引号的标识符(如表名)转换为大写。你创建表时用的是
- schema上下文不匹配:
你只执行了USE Database {database},但未切换到指定schema。虽然连接时指定了schema参数,但创建表时未明确指定schema,可能会话当前的schema并非预期值,导致写入时找不到对应schema下的表。
而SQLAlchemy的to_sql方法默认不会强制给表名加双引号,且连接字符串明确指定了database和schema,因此能正确匹配到表。
解决方法
方法1:统一表名大小写(创建带双引号的小写表)
创建表时给表名加双引号,确保表名是小写的testdeb,与write_pandas查找的表名一致:
query = (f'''CREATE TABLE IF NOT EXISTS "{channel_name}" ( sepal_length INTEGER, sepal_width INTEGER NOT NULL, petal_length INTEGER NOT NULL, petal_widht INTEGER NOT NULL) ''') cur.execute(query)
方法2:关闭write_pandas的标识符引号
调用write_pandas时添加quote_identifiers=False参数,让函数不给表名加双引号,Snowflake会自动转成大写,匹配你创建的表:
success, nchunks, nrows, _ = write_pandas(conn, test_df, channel_name, quote_identifiers=False)
方法3:确保会话切换到目标schema
在创建表前执行USE SCHEMA {schema},确保创建表和写入操作在同一个schema下:
cur.execute(f"Use Database {database}") cur.execute(f"Use SCHEMA {schema}") # 添加该行切换schema
内容的提问来源于stack exchange,提问作者Abdul Rahuman
相关产品推荐
相关产品推荐

