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 参数不起作用