Pandas to_sql无法在PostgreSQL中写入除'public'以外的模式
我正在尝试把一个数据框的内容写入一个不是'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_sql
和to_sql
函数写入不同的模式还不被支持(不过已经提交了改进请求:https://github.com/pydata/pandas/issues/7441)。
不过,我描述了一种使用对象接口的变通方法。但我提到的方法只适用于添加表一次,而不适合替换或追加表。所以如果你只是想添加,先删除现有的表,然后再写入。
如果你想要在表中追加数据,下面有一个稍微复杂一点的变通方法。首先重新定义has_table
和get_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
。