Pandas to_sql无法在PostgreSQL中写入除'public'以外的模式

4 投票
1 回答
10991 浏览
提问于 2025-04-18 16:20

我正在尝试把一个数据框的内容写入一个不是'public'模式的表。我按照这个链接中描述的方法进行了操作:Pandas写入其他PostgreSQL模式

meta = sqlalchemy.MetaData()
engine = create_engine('postgresql://some:user@host/db')
meta = sqlalchemy.MetaData(engine, schema='schema')
meta.reflect(engine, schema='schema')
pdsql = pandas.io.sql.PandasSQLAlchemy(engine, meta=meta)

但是当我尝试写入这个表时:

pdsql.to_sql(df, 'table', if_exists='append')

我遇到了以下错误:

InvalidRequestError: Table 'schema.table' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

我还尝试在reflect调用中添加extend_existing=True,但这似乎没有什么效果。

我该如何让pandas写入这个表呢?

1 个回答

14

更新: 从pandas 0.15开始,支持写入不同的模式(schema)。这样你就可以使用schema这个参数了:

df.to_sql('test', engine, schema='a_schema')

正如我在链接的问题中提到的,目前使用read_sqlto_sql函数写入不同的模式还不被支持(不过已经提交了改进请求:https://github.com/pydata/pandas/issues/7441)。

不过,我描述了一种使用对象接口的变通方法。但我提到的方法只适用于添加表一次,而不适合替换或追加表。所以如果你只是想添加,先删除现有的表,然后再写入。

如果你想要在表中追加数据,下面有一个稍微复杂一点的变通方法。首先重新定义has_tableget_table

def has_table(self, name):
    return self.engine.has_table(name, schema=self.meta.schema)

def get_table(self, table_name):
    if self.meta.schema:
        table_name = self.meta.schema + '.' + table_name
    return self.meta.tables.get(table_name)

pd.io.sql.PandasSQLAlchemy.has_table = has_table
pd.io.sql.PandasSQLAlchemy.get_table = get_table

然后像之前一样创建PandasSQLAlchemy对象,并写入数据:

meta = sqlalchemy.MetaData(engine, schema='schema')
meta.reflect()
pdsql = pd.io.sql.PandasSQLAlchemy(engine, meta=meta)
pdsql.to_sql(df, 'table', if_exists='append')

这显然不是最好的方法,但我们正在努力为0.15版本提供更好的接口。如果你想帮忙,可以在这里参与讨论:https://github.com/pydata/pandas/issues/7441

注意!这个接口(PandasSQLAlchemy)还不是完全公开的,接下来的pandas版本中可能会有变化,但这是在pandas 0.14(.1)中实现的方法。

更新: 在pandas 0.15中,PandasSQLAlchemy被重命名为SQLDatabase

撰写回答