pandas DataFrame.to_sql() 函数 if_exists 参数不起作用

Posted

技术标签:

【中文标题】pandas DataFrame.to_sql() 函数 if_exists 参数不起作用【英文标题】:pandas DataFrame.to_sql() function if_exists parameter not working 【发布时间】:2014-07-30 09:11:51 【问题描述】:

当我尝试将 if_exists='replace' 参数传递给 to_sql 时,我收到一个编程错误,告诉我表已经存在:

>>> foobar.to_sql('foobar', engine, if_exists=u'replace')
...
ProgrammingError: (ProgrammingError) ('42S01', "[42S01] [Microsoft][ODBC SQL Server Driver][SQL Server]There is already an object named 'foobar' in the database. (2714) (SQLExecDirectW)") u'\nCREATE TABLE foobar...

从文档看来,这个选项应该删除表并重新创建它,这不是观察到的行为。如果表不存在,则工作正常。如果这是一个错误或我做错了什么,有什么想法吗?

我正在使用 pandas 0.14 和 sqlalchemy 0.8.3 以及 enthought canopy python 发行版,并且我正在连接到 SQL Server。

编辑 根据 joris 的 cmets:

>>>pd.__version__
Out[4]: '0.14.0'
>>>pd.io.sql.has_table('foobar', engine)
Out[7]: False
>>>foobar.to_sql('foobar', engine, if_exists=u'replace', index=False)
---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
<ipython-input-9-2f4ac7ed7f23> in <module>()
----> 1 foobar.to_sql('foobar', engine, if_exists=u'replace', index=False)

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\pandas\core\generic.pyc in to_sql(self, name, con, flavor, if_exists, index, index_label)
    948         sql.to_sql(
    949             self, name, con, flavor=flavor, if_exists=if_exists, index=index,
--> 950             index_label=index_label)
    951 
    952     def to_pickle(self, path):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\pandas\io\sql.pyc in to_sql(frame, name, con, flavor, if_exists, index, index_label)
    438 
    439     pandas_sql.to_sql(frame, name, if_exists=if_exists, index=index,
--> 440                       index_label=index_label)
    441 
    442 

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\pandas\io\sql.pyc in to_sql(self, frame, name, if_exists, index, index_label)
    812         table = PandasSQLTable(
    813             name, self, frame=frame, index=index, if_exists=if_exists,
--> 814             index_label=index_label)
    815         table.insert()
    816 

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\pandas\io\sql.pyc in __init__(self, name, pandas_sql_engine, frame, index, if_exists, prefix, index_label)
    530             else:
    531                 self.table = self._create_table_statement()
--> 532                 self.create()
    533         else:
    534             # no data provided, read-only mode

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\pandas\io\sql.pyc in create(self)
    546 
    547     def create(self):
--> 548         self.table.create()
    549 
    550     def insert_statement(self):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\schema.pyc in create(self, bind, checkfirst)
    614         bind._run_visitor(ddl.SchemaGenerator,
    615                             self,
--> 616                             checkfirst=checkfirst)
    617 
    618     def drop(self, bind=None, checkfirst=False):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _run_visitor(self, visitorcallable, element, connection, **kwargs)
   1477                                     connection=None, **kwargs):
   1478         with self._optional_conn_ctx_manager(connection) as conn:
-> 1479             conn._run_visitor(visitorcallable, element, **kwargs)
   1480 
   1481     class _trans_ctx(object):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _run_visitor(self, visitorcallable, element, **kwargs)
   1120     def _run_visitor(self, visitorcallable, element, **kwargs):
   1121         visitorcallable(self.dialect, self,
-> 1122                             **kwargs).traverse_single(element)
   1123 
   1124 

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\sql\visitors.pyc in traverse_single(self, obj, **kw)
    120             meth = getattr(v, "visit_%s" % obj.__visit_name__, None)
    121             if meth:
--> 122                 return meth(obj, **kw)
    123 
    124     def iterate(self, obj):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\ddl.pyc in visit_table(self, table, create_ok)
     87                 self.traverse_single(column.default)
     88 
---> 89         self.connection.execute(schema.CreateTable(table))
     90 
     91         if hasattr(table, 'indexes'):

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in execute(self, object, *multiparams, **params)
    660                                                 object,
    661                                                 multiparams,
--> 662                                                 params)
    663         else:
    664             raise exc.InvalidRequestError(

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _execute_ddl(self, ddl, multiparams, params)
    718             compiled,
    719             None,
--> 720             compiled
    721         )
    722         if self._has_events:

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
    872                                 parameters,
    873                                 cursor,
--> 874                                 context)
    875 
    876         if self._has_events:

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _handle_dbapi_exception(self, e, statement, parameters, cursor, context)
   1022                                         self.dialect.dbapi.Error,
   1023                                         connection_invalidated=self._is_disconnect),
-> 1024                                     exc_info
   1025                                 )
   1026 

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\util\compat.pyc in raise_from_cause(exception, exc_info)
    194         # the code line where the issue occurred
    195         exc_type, exc_value, exc_tb = exc_info
--> 196         reraise(type(exception), exception, tb=exc_tb)
    197 
    198 

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
    865                                     statement,
    866                                     parameters,
--> 867                                     context)
    868         except Exception, e:
    869             self._handle_dbapi_exception(

C:\Users\AppData\Local\Enthought\Canopy\User\lib\site-packages\sqlalchemy\engine\default.pyc in do_execute(self, cursor, statement, parameters, context)
    322 
    323     def do_execute(self, cursor, statement, parameters, context=None):
--> 324         cursor.execute(statement, parameters)
    325 
    326     def do_execute_no_params(self, cursor, statement, context=None):

ProgrammingError: (ProgrammingError) ('42S01', "[42S01] [Microsoft][ODBC SQL Server Driver][SQL Server]There is already an object named 'foobar' in the database. (2714) (SQLExecDirectW)") u'\nCREATE TABLE foobar (\n\tfactor TEXT NULL, \n\tnum_avail INTEGER NULL, \n\tpct_avail FLOAT NULL, \n\tmin FLOAT NULL, \n\tmax FLOAT NULL, \n\tptile1 FLOAT NULL, \n\tptile99 FLOAT NULL, \n\tpct_yday FLOAT NULL, \n\tdiff_yday FLOAT NULL, \n\tcorr_yday FLOAT NULL\n)\n\n' ()

【问题讨论】:

奇怪,你能显示pd.__version__吗(只是为了确保它没有选择另一个版本的熊猫,因为这是0.13及更早版本中的一个错误(带有替换),但现在应该修复) .另外,你能显示pd.io.sql.has_table('foobar', engine) 和完整的错误回溯吗? @joris 我发现了问题;我在 SQL Server 中连接的默认架构不是标准的 dbo 架构。在写入表时,它会将其写入我的个人模式。但是,pandas 只检查现有表的 dbo 模式。当我将默认模式切换回dbo 时,一切正常。但是,我希望能够使用 pandas 从多个模式中写入和读取数据。 pandas 支持这个功能吗? 你能在 github (github.com/pydata/pandas/issues) 上为此打开一个问题吗? 好的,我会打开一个问题。 如果您使用的是默认架构,这不会是一个问题,replace 参数会在不同的架构上引发错误,因为 DROP 会直接进入默认架构,解决方案是添加 schema =' your_schema' 【参考方案1】:

此问题似乎已在 0.14.1 reference 中修复

解决方案

更新你的熊猫

【讨论】:

在 pandas 1.0.5 中仍然相同 @DimaLituiev 我建议你在 gitlab 上提交一个错误,参考我在回答中引用的票证。 除非您使用默认架构,否则它仍然存在问题。 当还在 to_sql 函数中使用 schema 参数时,仍然会看到 pandas 1.2.5 中的错误。

以上是关于pandas DataFrame.to_sql() 函数 if_exists 参数不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 pyODBC 的 fast_executemany 加速 pandas.DataFrame.to_sql

pandas DataFrame.to_sql 和 nan 值

Pandas DataFrame.to_sql() 错误 - 在字符串格式化期间并非所有参数都转换

pandas DataFrame.to_sql() 函数 if_exists 参数不起作用

Python:使用 dataframe.to_sql 向 MySQL 添加主键

如何将 DataFrame 写入 postgres 表?