59

trying to write pandas dataframe to MySQL table using to_sql. Previously been using flavor='mysql', however it will be depreciated in the future and wanted to start the transition to using SQLAlchemy engine.

sample code:

import pandas as pd
import mysql.connector
from sqlalchemy import create_engine

engine = create_engine('mysql+mysqlconnector://[user]:[pass]@[host]:[port]/[schema]', echo=False)
cnx = engine.raw_connection()
data = pd.read_sql('SELECT * FROM sample_table', cnx)
data.to_sql(name='sample_table2', con=cnx, if_exists = 'append', index=False)

The read works fine but the to_sql has an error:

DatabaseError: Execution failed on sql 'SELECT name FROM sqlite_master WHERE type='table' AND name=?;': Wrong number of arguments during string formatting

Why does it look like it is trying to use sqlite? What is the correct use of a sqlalchemy connection with mysql and specifically mysql.connector?

I also tried passing the engine in as the connection as well, and that gave me an error referencing no cursor object.

data.to_sql(name='sample_table2', con=engine, if_exists = 'append', index=False)
>>AttributeError: 'Engine' object has no attribute 'cursor'
7
  • 1
    You have to pass the Engine itself, not a raw connection (in the future an sqlalchemy Connection will also be possible, but not a raw connection). Can you see if that solves the problem? Commented Jun 3, 2015 at 22:04
  • Ah, I see that you already tried that :-) Can you show the error you get in that case? Commented Jun 3, 2015 at 22:04
  • 1
    when using engine: AttributeError: 'Engine' object has no attribute 'cursor' Commented Jun 3, 2015 at 22:21
  • Can you show the output of pd.__versions__? You're sure not picking up an old pandas version? Commented Jun 3, 2015 at 22:23
  • pd.__version__ is 0.16.1, assuming you meant __version__ not __versions__ Commented Jun 3, 2015 at 22:29

4 Answers 4

81

Using the engine in place of the raw_connection() worked:

import pandas as pd
import mysql.connector
from sqlalchemy import create_engine

engine = create_engine('mysql+mysqlconnector://[user]:[pass]@[host]:[port]/[schema]', echo=False)
data.to_sql(name='sample_table2', con=engine, if_exists = 'append', index=False)

Not clear on why when I tried this yesterday it gave me the earlier error.

Sign up to request clarification or add additional context in comments.

6 Comments

Glad it works now! In any case, this is the way to go
BTW, you may accept your own answer to indicated this is fixed!
In case you run into problems installing mysql.connector or don't know how to install it, see this link stackoverflow.com/questions/32754461/… They recommend pip install mysql-connector==2.1.4. It also solved this problem for me.
Consistently getting error Python installation has no SSL support. Running with python 3.7 with fresh Anaconda install.
I have @ in password filed and it's creating an issue. How can we fix this. engine = create_engine("mysql+pymysql://dbuser:DBuser@12345@xyz/table") Here DBuser@12345 is password. but somehow script not able to interpret it correct. It user 12345@xyz as hostname instead of xyz
|
15

Alternatively, use pymysql package...

import pymysql
from sqlalchemy import create_engine
cnx = create_engine('mysql+pymysql://[user]:[pass]@[host]:[port]/[schema]', echo=False)

data = pd.read_sql('SELECT * FROM sample_table', cnx)
data.to_sql(name='sample_table2', con=cnx, if_exists = 'append', index=False)

7 Comments

openwonk - can you elaborate on the [port]/[schema] portion of this code? Not exactly sure what to put there. Thank you!
Gonna answer my own question here, schema = data base.
Glad to help, @pshep123
Although I'm still having a hell of a time here: stackoverflow.com/questions/44933704/…. Not sure if you have any insight, thanks.
I spent forever trying to find an answer like this that worked!
|
8

Using pymysql and sqlalchemy, this works for Pandas v0.22:

import pandas as pd
import pymysql
from sqlalchemy import create_engine

user = 'yourUserName'
passw = 'password'
host =  'hostName'  # either localhost or ip e.g. '172.17.0.2' or hostname address 
port = 3306 
database = 'dataBaseName'

mydb = create_engine('mysql+pymysql://' + user + ':' + passw + '@' + host + ':' + str(port) + '/' + database , echo=False)

directory = r'directoryLocation'  # path of csv file
csvFileName = 'something.csv'

df = pd.read_csv(os.path.join(directory, csvFileName ))

df.to_sql(name=csvFileName[:-4], con=mydb, if_exists = 'replace', index=False)

"""
if_exists: {'fail', 'replace', 'append'}, default 'fail'
     fail: If table exists, do nothing.
     replace: If table exists, drop it, recreate it, and insert data.
     append: If table exists, insert data. Create if does not exist.
"""

Comments

0

I know in the title of the question is included the word SQLAlchemy, however I see in the questions and answers the need to import pymysql or mysql.connector, and also is possible to do the job with pymysql, withouth calling SQLAlchemy.

import pymysql
user = 'root'
passw = 'my-secret-pw-for-mysql-12ud' # In previous posts variable "pass"
host =  '172.17.0.2'
port = 3306

database = 'sample_table' # In previous posts similar to "schema"

conn = pymysql.connect(host=host,
                       port=port,
                       user=user, 
                       passwd=passw,  
                       db=database)

data.to_sql(name=database, con=conn, if_exists = 'append', index=False, flavor = 'mysql')

I think this solution could be good althought it is not using SQLAlchemy.

3 Comments

The flavor keyword arg no longer is allowed.
Please rename "database" to "table". That way it is very misleading and wrong.
was looking all over for an answer like this

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.