Skip to content

Commit ed726cd

Browse files
committed
ENH: Allow to_sql to recognize single sql type pandas-dev#11886
1 parent ae2ca83 commit ed726cd

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

doc/source/whatsnew/v0.18.2.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ Other enhancements
8989

9090
- ``pd.read_html()`` has gained support for the ``decimal`` option (:issue:`12907`)
9191

92-
92+
- ``DataFrame.to_sql `` now allows a single value as the SQL type for all columns (:issue:`11886`).
9393

9494
.. _whatsnew_0182.api:
9595

pandas/io/sql.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
string_types, text_type)
1919
from pandas.core.api import DataFrame, Series
2020
from pandas.core.common import isnull
21+
from pandas.core.generic import is_dictlike
2122
from pandas.core.base import PandasObject
2223
from pandas.types.api import DatetimeTZDtype
2324
from pandas.tseries.tools import to_datetime
@@ -550,9 +551,10 @@ def to_sql(frame, name, con, flavor='sqlite', schema=None, if_exists='fail',
550551
chunksize : int, default None
551552
If not None, then rows will be written in batches of this size at a
552553
time. If None, all rows will be written at once.
553-
dtype : dict of column name to SQL type, default None
554+
dtype : single SQLtype or dict of column name to SQL type, default None
554555
Optional specifying the datatype for columns. The SQL type should
555556
be a SQLAlchemy type, or a string for sqlite3 fallback connection.
557+
If all columns are of the same type, one single value can be used.
556558
557559
"""
558560
if if_exists not in ('fail', 'replace', 'append'):
@@ -1231,11 +1233,15 @@ def to_sql(self, frame, name, if_exists='fail', index=True,
12311233
chunksize : int, default None
12321234
If not None, then rows will be written in batches of this size at a
12331235
time. If None, all rows will be written at once.
1234-
dtype : dict of column name to SQL type, default None
1236+
dtype : single SQL type or dict of column name to SQL type, default None
12351237
Optional specifying the datatype for columns. The SQL type should
1236-
be a SQLAlchemy type.
1238+
be a SQLAlchemy type. If all columns are of the same type, one
1239+
single value can be used.
12371240
12381241
"""
1242+
if dtype and not is_dictlike(dtype):
1243+
dtype = {col_name : dtype for col_name in frame}
1244+
12391245
if dtype is not None:
12401246
from sqlalchemy.types import to_instance, TypeEngine
12411247
for col, my_type in dtype.items():
@@ -1644,11 +1650,15 @@ def to_sql(self, frame, name, if_exists='fail', index=True,
16441650
chunksize : int, default None
16451651
If not None, then rows will be written in batches of this
16461652
size at a time. If None, all rows will be written at once.
1647-
dtype : dict of column name to SQL type, default None
1653+
dtype : single SQL type or dict of column name to SQL type, default None
16481654
Optional specifying the datatype for columns. The SQL type should
1649-
be a string.
1655+
be a string. If all columns are of the same type, one single value
1656+
can be used.
16501657
16511658
"""
1659+
if dtype and not is_dictlike(dtype):
1660+
dtype = {col_name : dtype for col_name in frame}
1661+
16521662
if dtype is not None:
16531663
for col, my_type in dtype.items():
16541664
if not isinstance(my_type, str):

pandas/io/tests/test_sql.py

+28
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,21 @@ def test_dtype(self):
15521552
self.assertTrue(isinstance(sqltype, sqlalchemy.String))
15531553
self.assertEqual(sqltype.length, 10)
15541554

1555+
def test_to_sql_save_indexgle_dtype(self):
1556+
self.drop('single_dtype_test')
1557+
cols = ['A','B']
1558+
data = [('a','b'),
1559+
('c','d')]
1560+
df = DataFrame(data,columns=cols)
1561+
df.to_sql('single_dtype_test',self.conn,dtype=sqlalchemy.TEXT)
1562+
meta = sqlalchemy.schema.MetaData(bind=self.conn)
1563+
meta.reflect()
1564+
sqltypea = meta.tables['single_dtype_test'].columns['A'].type
1565+
sqltypeb = meta.tables['single_dtype_test'].columns['B'].type
1566+
self.assertTrue(isinstance(sqltypea, sqlalchemy.TEXT))
1567+
self.assertTrue(isinstance(sqltypeb, sqlalchemy.TEXT))
1568+
self.drop_table('single_dtype_test')
1569+
15551570
def test_notnull_dtype(self):
15561571
cols = {'Bool': Series([True, None]),
15571572
'Date': Series([datetime(2012, 5, 1), None]),
@@ -2025,6 +2040,19 @@ def test_dtype(self):
20252040
self.assertRaises(ValueError, df.to_sql,
20262041
'error', self.conn, dtype={'B': bool})
20272042

2043+
def test_to_sql_single_dtype(self):
2044+
if self.flavor == 'mysql':
2045+
raise nose.SkipTest('Not applicable to MySQL legacy')
2046+
self.drop_table('single_dtype_test')
2047+
cols = ['A','B']
2048+
data = [('a','b'),
2049+
('c','d')]
2050+
df = DataFrame(data,columns=cols)
2051+
df.to_sql('single_dtype_test',self.conn,dtype='STRING')
2052+
self.assertEqual(self._get_sqlite_column_type('single_dtype_test','A'),'STRING')
2053+
self.assertEqual(self._get_sqlite_column_type('single_dtype_test','B'),'STRING')
2054+
self.drop_table('single_dtype_test')
2055+
20282056
def test_notnull_dtype(self):
20292057
if self.flavor == 'mysql':
20302058
raise nose.SkipTest('Not applicable to MySQL legacy')

0 commit comments

Comments
 (0)