Skip to content

Commit e0058fb

Browse files
Merge pull request pandas-dev#6598 from jorisvandenbossche/sql-to_sql
SQL: move df.to_sql to generic + update with new functionality
2 parents 429f0f5 + b77eb1f commit e0058fb

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

pandas/core/frame.py

-19
Original file line numberDiff line numberDiff line change
@@ -1261,25 +1261,6 @@ def to_stata(
12611261
time_stamp=time_stamp, data_label=data_label)
12621262
writer.write_file()
12631263

1264-
def to_sql(self, name, con, flavor='sqlite', if_exists='fail', **kwargs):
1265-
"""
1266-
Write records stored in a DataFrame to a SQL database.
1267-
1268-
Parameters
1269-
----------
1270-
name : str
1271-
Name of SQL table
1272-
conn : an open SQL database connection object
1273-
flavor: {'sqlite', 'mysql', 'oracle'}, default 'sqlite'
1274-
if_exists: {'fail', 'replace', 'append'}, default 'fail'
1275-
- fail: If table exists, do nothing.
1276-
- replace: If table exists, drop it, recreate it, and insert data.
1277-
- append: If table exists, insert data. Create if does not exist.
1278-
"""
1279-
from pandas.io.sql import write_frame
1280-
write_frame(
1281-
self, name, con, flavor=flavor, if_exists=if_exists, **kwargs)
1282-
12831264
@Appender(fmt.docstring_to_string, indents=1)
12841265
def to_string(self, buf=None, columns=None, col_space=None, colSpace=None,
12851266
header=True, index=True, na_rep='NaN', formatters=None,

pandas/core/generic.py

+27
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,33 @@ def to_msgpack(self, path_or_buf=None, **kwargs):
908908
from pandas.io import packers
909909
return packers.to_msgpack(path_or_buf, self, **kwargs)
910910

911+
def to_sql(self, name, con, flavor='sqlite', if_exists='fail', index=True):
912+
"""
913+
Write records stored in a DataFrame to a SQL database.
914+
915+
Parameters
916+
----------
917+
name : string
918+
Name of SQL table
919+
con : SQLAlchemy engine or DBAPI2 connection (legacy mode)
920+
Using SQLAlchemy makes it possible to use any DB supported by that
921+
library.
922+
If a DBAPI2 object is given, a supported SQL flavor must also be provided
923+
flavor : {'sqlite', 'mysql'}, default 'sqlite'
924+
The flavor of SQL to use. Ignored when using SQLAlchemy engine.
925+
Required when using DBAPI2 connection.
926+
if_exists : {'fail', 'replace', 'append'}, default 'fail'
927+
- fail: If table exists, do nothing.
928+
- replace: If table exists, drop it, recreate it, and insert data.
929+
- append: If table exists, insert data. Create if does not exist.
930+
index : boolean, default True
931+
Write DataFrame index as a column
932+
933+
"""
934+
from pandas.io import sql
935+
sql.to_sql(
936+
self, name, con, flavor=flavor, if_exists=if_exists, index=index)
937+
911938
def to_pickle(self, path):
912939
"""
913940
Pickle (serialize) object to input file path

pandas/io/sql.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import pandas.core.common as com
1313
from pandas.compat import lzip, map, zip, raise_with_traceback, string_types
14-
from pandas.core.api import DataFrame
14+
from pandas.core.api import DataFrame, Series
1515
from pandas.core.base import PandasObject
1616
from pandas.tseries.tools import to_datetime
1717

@@ -253,6 +253,12 @@ def to_sql(frame, name, con, flavor='sqlite', if_exists='fail', index=True):
253253
Write DataFrame index as a column
254254
"""
255255
pandas_sql = pandasSQL_builder(con, flavor=flavor)
256+
257+
if isinstance(frame, Series):
258+
frame = frame.to_frame()
259+
elif not isinstance(frame, DataFrame):
260+
raise NotImplementedError
261+
256262
pandas_sql.to_sql(frame, name, if_exists=if_exists, index=index)
257263

258264

pandas/io/tests/test_sql.py

+12
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,18 @@ def test_to_sql_append(self):
337337
self.assertEqual(
338338
num_rows, num_entries, "not the same number of rows as entries")
339339

340+
def test_to_sql_series(self):
341+
s = Series(np.arange(5, dtype='int64'), name='series')
342+
sql.to_sql(s, "test_series", self.conn, flavor='sqlite', index=False)
343+
s2 = sql.read_sql("SELECT * FROM test_series", self.conn,
344+
flavor='sqlite')
345+
tm.assert_frame_equal(s.to_frame(), s2)
346+
347+
def test_to_sql_panel(self):
348+
panel = tm.makePanel()
349+
self.assertRaises(NotImplementedError, sql.to_sql, panel,
350+
'test_panel', self.conn, flavor='sqlite')
351+
340352
def test_legacy_write_frame(self):
341353
"""Test legacy write frame name.
342354
Assume that functionality is already tested above so just do quick check that it basically works"""

0 commit comments

Comments
 (0)