Pandas to_sql 'append' 现有 table 导致 Python 崩溃
Pandas to_sql 'append' to an existing table causes Python crash
我的问题本质上是这样的:当我尝试将 to_sql 与 if_exists = 'append' 一起使用时,我的 [=64= 上的名称设置为 table ] 已经存在的服务器 python 崩溃了。
这是我的代码:
@event.listens_for(engine, 'before_cursor_execute') def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
if executemany:
cursor.fast_executemany = True
df.to_sql(name = 'existingSQLTable', con = engine, if_exists = 'append', index = False, chunksize = 10000, dtype = dataTypes)
我没有包含它,但 dataTypes 是所有列名称及其数据类型的字典。
这是我得到的错误:
Traceback (most recent call last):
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1116, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\default.py", line 447, in do_executemany
cursor.executemany(statement, parameters)
pyodbc.IntegrityError: ('23000', "[23000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Violation of PRIMARY KEY constraint 'PK__existingSQLTable__'. Cannot insert duplicate key in object 'dbo.existingSQLTable'. The duplicate key value is (20008.7, 2008-08-07, Fl). (2627) (SQLExecute); [23000] [Microsoft][SQL Server Native Client 11.0][SQL Server]The statement has been terminated. (3621)")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
Table.to_sql(name = 'existingSQLTable', con = engine, if_exists = 'append', index = False, chunksize = 10000, dtype = dataTypes)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\core\generic.py", line 1165, in to_sql
chunksize=chunksize, dtype=dtype)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 571, in to_sql
chunksize=chunksize, dtype=dtype)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 1250, in to_sql
table.insert(chunksize)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 770, in insert
self._execute_insert(conn, keys, chunk_iter)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 745, in _execute_insert
conn.execute(self.insert_statement(), data)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 914, in execute
return meth(self, multiparams, params)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1010, in _execute_clauseelement
compiled_sql, distilled_params
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1146, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1341, in _handle_dbapi_exception
exc_info
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 202, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 185, in reraise
raise value.with_traceback(tb)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1116, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\default.py", line 447, in do_executemany
cursor.executemany(statement, parameters)
根据错误,在我看来,标志 fast_executemany 似乎有问题,但我已经阅读了很多关于它的文档,没有发现任何问题。
可能需要注意的事项:
- A table 不存在 if_exists = 'replace' 按预期工作
- A table 不存在 if_exists = 'append' 按预期工作
- A table 已经存在 if_exists = 'replace' 按预期工作
- 我的 DataFrame 大约有 300 万行和 25 列(主要是浮点数和一些短字符串)
- 我可以成功写入 900,000 行绝对最大值而不会 python 崩溃。
- 我正在使用 SQL 服务器,pandas 0.23.3,pyodbc 4.0.23(我也遇到了与 4.0.22 相同的错误),Jupyter Notebook(我也在 IDLE 中尝试了相同的结果),Windows 10,Python 3.5.1 和 Anaconda 3.
对我来说显而易见的解决方案是将 DataFrame 分成 900,000 行的块。虽然第一个块已成功上传,但我无法在不 python 崩溃的情况下向其附加一行。
此错误是否是旨在加速该过程的代码的结果(它做得非常好)?我误解了 to_sql 功能吗?还是有其他事情发生?任何建议都会很棒!另外,如果有人有类似的问题,我会很高兴知道!
正如@Jon Clements 所解释的那样,问题在于有些行具有相同的主键(但这些行本身并不相同)。我使用了 pandas df.drop_duplicates 函数,子集参数设置为主键列。这解决了违反 PK 错误。
我的问题本质上是这样的:当我尝试将 to_sql 与 if_exists = 'append' 一起使用时,我的 [=64= 上的名称设置为 table ] 已经存在的服务器 python 崩溃了。
这是我的代码:
@event.listens_for(engine, 'before_cursor_execute') def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
if executemany:
cursor.fast_executemany = True
df.to_sql(name = 'existingSQLTable', con = engine, if_exists = 'append', index = False, chunksize = 10000, dtype = dataTypes)
我没有包含它,但 dataTypes 是所有列名称及其数据类型的字典。
这是我得到的错误:
Traceback (most recent call last):
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1116, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\default.py", line 447, in do_executemany
cursor.executemany(statement, parameters)
pyodbc.IntegrityError: ('23000', "[23000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Violation of PRIMARY KEY constraint 'PK__existingSQLTable__'. Cannot insert duplicate key in object 'dbo.existingSQLTable'. The duplicate key value is (20008.7, 2008-08-07, Fl). (2627) (SQLExecute); [23000] [Microsoft][SQL Server Native Client 11.0][SQL Server]The statement has been terminated. (3621)")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
Table.to_sql(name = 'existingSQLTable', con = engine, if_exists = 'append', index = False, chunksize = 10000, dtype = dataTypes)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\core\generic.py", line 1165, in to_sql
chunksize=chunksize, dtype=dtype)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 571, in to_sql
chunksize=chunksize, dtype=dtype)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 1250, in to_sql
table.insert(chunksize)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 770, in insert
self._execute_insert(conn, keys, chunk_iter)
File "C:\Apps\Anaconda3\lib\site-packages\pandas\io\sql.py", line 745, in _execute_insert
conn.execute(self.insert_statement(), data)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 914, in execute
return meth(self, multiparams, params)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1010, in _execute_clauseelement
compiled_sql, distilled_params
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1146, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1341, in _handle_dbapi_exception
exc_info
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 202, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 185, in reraise
raise value.with_traceback(tb)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1116, in _execute_context
context)
File "C:\Apps\Anaconda3\lib\site-packages\sqlalchemy\engine\default.py", line 447, in do_executemany
cursor.executemany(statement, parameters)
根据错误,在我看来,标志 fast_executemany 似乎有问题,但我已经阅读了很多关于它的文档,没有发现任何问题。
可能需要注意的事项:
- A table 不存在 if_exists = 'replace' 按预期工作
- A table 不存在 if_exists = 'append' 按预期工作
- A table 已经存在 if_exists = 'replace' 按预期工作
- 我的 DataFrame 大约有 300 万行和 25 列(主要是浮点数和一些短字符串)
- 我可以成功写入 900,000 行绝对最大值而不会 python 崩溃。
- 我正在使用 SQL 服务器,pandas 0.23.3,pyodbc 4.0.23(我也遇到了与 4.0.22 相同的错误),Jupyter Notebook(我也在 IDLE 中尝试了相同的结果),Windows 10,Python 3.5.1 和 Anaconda 3.
对我来说显而易见的解决方案是将 DataFrame 分成 900,000 行的块。虽然第一个块已成功上传,但我无法在不 python 崩溃的情况下向其附加一行。
此错误是否是旨在加速该过程的代码的结果(它做得非常好)?我误解了 to_sql 功能吗?还是有其他事情发生?任何建议都会很棒!另外,如果有人有类似的问题,我会很高兴知道!
正如@Jon Clements 所解释的那样,问题在于有些行具有相同的主键(但这些行本身并不相同)。我使用了 pandas df.drop_duplicates 函数,子集参数设置为主键列。这解决了违反 PK 错误。