Table of Contents
These coding examples illustrate how to develop Python applications and scripts which connect to MySQL Server using MySQL Connector/Python.
The connect() constructor creates a connection
to the MySQL server and returns a
MySQLConnection object.
The following example shows how to connect to the MySQL server:
import mysql.connector
cnx = mysql.connector.connect(user='scott', password='tiger',
host='127.0.0.1',
database='employees')
cnx.close()
Section 7.1, “Connector/Python Connection Arguments” describes the permitted connection arguments.
It is also possible to create connection objects using the connection.MySQLConnection() class:
from mysql.connector import (connection)
cnx = connection.MySQLConnection(user='scott', password='tiger',
host='127.0.0.1',
database='employees')
cnx.close()
Both methods, using the connect() constructor,
or the class directly, are valid and functionally equal, but using
connector() is preferred and is used in most
examples in this manual.
To handle connection errors, use the try
statement and catch all errors using the
errors.Error
exception:
import mysql.connector
from mysql.connector import errorcode
try:
cnx = mysql.connector.connect(user='scott',
database='testt')
except mysql.connector.Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
print("Something is wrong with your user name or password")
elif err.errno == errorcode.ER_BAD_DB_ERROR:
print("Database does not exist")
else:
print(err)
else:
cnx.close()
If you have lots of connection arguments, it's best to keep them
in a dictionary and use the ** operator:
import mysql.connector
config = {
'user': 'scott',
'password': 'tiger',
'host': '127.0.0.1',
'database': 'employees',
'raise_on_warnings': True,
}
cnx = mysql.connector.connect(**config)
cnx.close()
As of Connector/Python 2.1.1, the use_pure connection
argument determines whether to connect using a pure Python
interface to MySQL, or a C Extension that uses the MySQL C client
library (see Chapter 8, The Connector/Python C Extension). The default
is True (use the pure Python implementation).
Setting use_pure to False
causes the connection to use the C Extension if your Connector/Python
installation includes it. The following examples are similar to
others shown previously but with the includion of
use_pure=False.
Connect by naming arguments in the connect()
call:
import mysql.connector
cnx = mysql.connector.connect(user='scott', password='tiger',
host='127.0.0.1',
database='employees',
use_pure=False)
cnx.close()
Connect using an argument dictionary:
import mysql.connector
config = {
'user': 'scott',
'password': 'tiger',
'host': '127.0.0.1',
'database': 'employees',
'raise_on_warnings': True,
'use_pure': False,
}
cnx = mysql.connector.connect(**config)
cnx.close()
It is also possible to use the C Extension directly, by importing
the _mysql_connector module rather than the
mysql.connector module. For more information,
see Section 8.2, “The _mysql_connector C Extension Module”.
All DDL (Data Definition Language) statements are executed using a handle structure known as a cursor. The following examples show how to create the tables of the Employee Sample Database. You need them for the other examples.
In a MySQL server, tables are very long-lived objects, and are often accessed by multiple applications written in different languages. You might typically work with tables that are already set up, rather than creating them within your own application. Avoid setting up and dropping tables over and over again, as that is an expensive operation. The exception is temporary tables, which can be created and dropped quickly within an application.
from __future__ import print_function
import mysql.connector
from mysql.connector import errorcode
DB_NAME = 'employees'
TABLES = {}
TABLES['employees'] = (
"CREATE TABLE `employees` ("
" `emp_no` int(11) NOT NULL AUTO_INCREMENT,"
" `birth_date` date NOT NULL,"
" `first_name` varchar(14) NOT NULL,"
" `last_name` varchar(16) NOT NULL,"
" `gender` enum('M','F') NOT NULL,"
" `hire_date` date NOT NULL,"
" PRIMARY KEY (`emp_no`)"
") ENGINE=InnoDB")
TABLES['departments'] = (
"CREATE TABLE `departments` ("
" `dept_no` char(4) NOT NULL,"
" `dept_name` varchar(40) NOT NULL,"
" PRIMARY KEY (`dept_no`), UNIQUE KEY `dept_name` (`dept_name`)"
") ENGINE=InnoDB")
TABLES['salaries'] = (
"CREATE TABLE `salaries` ("
" `emp_no` int(11) NOT NULL,"
" `salary` int(11) NOT NULL,"
" `from_date` date NOT NULL,"
" `to_date` date NOT NULL,"
" PRIMARY KEY (`emp_no`,`from_date`), KEY `emp_no` (`emp_no`),"
" CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) "
" REFERENCES `employees` (`emp_no`) ON DELETE CASCADE"
") ENGINE=InnoDB")
TABLES['dept_emp'] = (
"CREATE TABLE `dept_emp` ("
" `emp_no` int(11) NOT NULL,"
" `dept_no` char(4) NOT NULL,"
" `from_date` date NOT NULL,"
" `to_date` date NOT NULL,"
" PRIMARY KEY (`emp_no`,`dept_no`), KEY `emp_no` (`emp_no`),"
" KEY `dept_no` (`dept_no`),"
" CONSTRAINT `dept_emp_ibfk_1` FOREIGN KEY (`emp_no`) "
" REFERENCES `employees` (`emp_no`) ON DELETE CASCADE,"
" CONSTRAINT `dept_emp_ibfk_2` FOREIGN KEY (`dept_no`) "
" REFERENCES `departments` (`dept_no`) ON DELETE CASCADE"
") ENGINE=InnoDB")
TABLES['dept_manager'] = (
" CREATE TABLE `dept_manager` ("
" `dept_no` char(4) NOT NULL,"
" `emp_no` int(11) NOT NULL,"
" `from_date` date NOT NULL,"
" `to_date` date NOT NULL,"
" PRIMARY KEY (`emp_no`,`dept_no`),"
" KEY `emp_no` (`emp_no`),"
" KEY `dept_no` (`dept_no`),"
" CONSTRAINT `dept_manager_ibfk_1` FOREIGN KEY (`emp_no`) "
" REFERENCES `employees` (`emp_no`) ON DELETE CASCADE,"
" CONSTRAINT `dept_manager_ibfk_2` FOREIGN KEY (`dept_no`) "
" REFERENCES `departments` (`dept_no`) ON DELETE CASCADE"
") ENGINE=InnoDB")
TABLES['titles'] = (
"CREATE TABLE `titles` ("
" `emp_no` int(11) NOT NULL,"
" `title` varchar(50) NOT NULL,"
" `from_date` date NOT NULL,"
" `to_date` date DEFAULT NULL,"
" PRIMARY KEY (`emp_no`,`title`,`from_date`), KEY `emp_no` (`emp_no`),"
" CONSTRAINT `titles_ibfk_1` FOREIGN KEY (`emp_no`)"
" REFERENCES `employees` (`emp_no`) ON DELETE CASCADE"
") ENGINE=InnoDB")
The preceding code shows how we are storing the
CREATE statements in a Python dictionary called
TABLES. We also define the database in a global
variable called DB_NAME, which enables you to
easily use a different schema.
cnx = mysql.connector.connect(user='scott') cursor = cnx.cursor()
A single MySQL server can manage multiple databases. Typically, you specify the database to switch to when connecting to the MySQL server. This example does not connect to the database upon connection, so that it can make sure the database exists, and create it if not:
def create_database(cursor):
try:
cursor.execute(
"CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(DB_NAME))
except mysql.connector.Error as err:
print("Failed creating database: {}".format(err))
exit(1)
try:
cnx.database = DB_NAME
except mysql.connector.Error as err:
if err.errno == errorcode.ER_BAD_DB_ERROR:
create_database(cursor)
cnx.database = DB_NAME
else:
print(err)
exit(1)
We first try to change to a particular database using the
database property of the connection object
cnx. If there is an error, we examine the error
number to check if the database does not exist. If so, we call the
create_database function to create it for us.
On any other error, the application exits and displays the error message.
After we successfully create or change to the target database, we
create the tables by iterating over the items of the
TABLES dictionary:
for name, ddl in TABLES.iteritems():
try:
print("Creating table {}: ".format(name), end='')
cursor.execute(ddl)
except mysql.connector.Error as err:
if err.errno == errorcode.ER_TABLE_EXISTS_ERROR:
print("already exists.")
else:
print(err.msg)
else:
print("OK")
cursor.close()
cnx.close()
To handle the error when the table already exists, we notify the
user that it was already there. Other errors are printed, but we
continue creating tables. (The example shows how to handle the
“table already exists” condition for illustration
purposes. In a real application, we would typically avoid the
error condition entirely by using the IF NOT
EXISTS clause of the CREATE
TABLE statement.)
The output would be something like this:
Creating table employees: already exists. Creating table salaries: already exists. Creating table titles: OK Creating table departments: already exists. Creating table dept_manager: already exists. Creating table dept_emp: already exists.
To populate the employees tables, use the dump files of the
Employee
Sample Database. Note that you only need the data dump
files that you will find in an archive named like
employees_db-dump-files-1.0.5.tar.bz2. After
downloading the dump files, execute the following commands, adding
connection options to the mysql commands if
necessary:
shell>tar xzf employees_db-dump-files-1.0.5.tar.bz2shell>cd employees_dbshell>mysql employees < load_employees.dumpshell>mysql employees < load_titles.dumpshell>mysql employees < load_departments.dumpshell>mysql employees < load_salaries.dumpshell>mysql employees < load_dept_emp.dumpshell>mysql employees < load_dept_manager.dump
Inserting or updating data is also done using the handler
structure known as a cursor. When you use a transactional storage
engine such as InnoDB (the default in MySQL 5.5
and later), you must commit the
data after a sequence of INSERT,
DELETE, and
UPDATE statements.
This example shows how to insert new data. The second
INSERT depends on the value of the
newly created primary key
of the first. The example also demonstrates how to use extended
formats. The task is to add a new employee starting to work
tomorrow with a salary set to 50000.
The following example uses tables created in the example
Section 5.2, “Creating Tables Using Connector/Python”. The
AUTO_INCREMENT column option for the primary
key of the employees table is important to
ensure reliable, easily searchable data.
from __future__ import print_function
from datetime import date, datetime, timedelta
import mysql.connector
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
tomorrow = datetime.now().date() + timedelta(days=1)
add_employee = ("INSERT INTO employees "
"(first_name, last_name, hire_date, gender, birth_date) "
"VALUES (%s, %s, %s, %s, %s)")
add_salary = ("INSERT INTO salaries "
"(emp_no, salary, from_date, to_date) "
"VALUES (%(emp_no)s, %(salary)s, %(from_date)s, %(to_date)s)")
data_employee = ('Geert', 'Vanderkelen', tomorrow, 'M', date(1977, 6, 14))
# Insert new employee
cursor.execute(add_employee, data_employee)
emp_no = cursor.lastrowid
# Insert salary information
data_salary = {
'emp_no': emp_no,
'salary': 50000,
'from_date': tomorrow,
'to_date': date(9999, 1, 1),
}
cursor.execute(add_salary, data_salary)
# Make sure data is committed to the database
cnx.commit()
cursor.close()
cnx.close()
We first open a connection to the MySQL server and store the
connection
object in the variable cnx. We then
create a new cursor, by default a
MySQLCursor
object, using the connection's
cursor()
method.
We could calculate tomorrow by calling a database function, but
for clarity we do it in Python using the
datetime module.
Both INSERT statements are stored in the
variables called add_employee and
add_salary. Note that the second
INSERT statement uses extended Python format
codes.
The information of the new employee is stored in the tuple
data_employee. The query to insert the new
employee is executed and we retrieve the newly inserted value for
the emp_no column (an
AUTO_INCREMENT column) using the
lastrowid property of the cursor object.
Next, we insert the new salary for the new employee, using the
emp_no variable in the dictionary holding the
data. This dictionary is passed to the
execute() method of the cursor object if an
error occurred.
Since by default Connector/Python turns
autocommit off, and MySQL
5.5 and later uses transactional InnoDB tables
by default, it is necessary to commit your changes using the
connection's commit() method. You could also
roll back using the
rollback() method.
The following example shows how to
query data using a cursor
created using the connection's
cursor()
method. The data returned is formatted and printed on the console.
The task is to select all employees hired in the year 1999 and print their names and hire dates to the console.
import datetime
import mysql.connector
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
query = ("SELECT first_name, last_name, hire_date FROM employees "
"WHERE hire_date BETWEEN %s AND %s")
hire_start = datetime.date(1999, 1, 1)
hire_end = datetime.date(1999, 12, 31)
cursor.execute(query, (hire_start, hire_end))
for (first_name, last_name, hire_date) in cursor:
print("{}, {} was hired on {:%d %b %Y}".format(
last_name, first_name, hire_date))
cursor.close()
cnx.close()
We first open a connection to the MySQL server and store the
connection
object in the variable cnx. We then
create a new cursor, by default a
MySQLCursor
object, using the connection's
cursor()
method.
In the preceding example, we store the SELECT
statement in the variable query. Note that we
are using unquoted %s-markers where dates
should have been. Connector/Python converts hire_start and
hire_end from Python types to a data type that
MySQL understands and adds the required quotes. In this case, it
replaces the first %s with
'1999-01-01', and the second with
'1999-12-31'.
We then execute the operation stored in the
query variable using the
execute()
method. The data used to replace the %s-markers
in the query is passed as a tuple: (hire_start,
hire_end).
After executing the query, the MySQL server is ready to send the
data. The result set could be zero rows, one row, or 100 million
rows. Depending on the expected volume, you can use different
techniques to process this result set. In this example, we use the
cursor object as an iterator. The first column
in the row is stored in the variable
first_name, the second in
last_name, and the third in
hire_date.
We print the result, formatting the output using Python's built-in
format() function. Note that
hire_date was converted automatically by Connector/Python
to a Python datetime.date object. This means
that we can easily format the date in a more human-readable form.
The output should be something like this:
.. Wilharm, LiMin was hired on 16 Dec 1999 Wielonsky, Lalit was hired on 16 Dec 1999 Kamble, Dannz was hired on 18 Dec 1999 DuBourdieux, Zhongwei was hired on 19 Dec 1999 Fujisawa, Rosita was hired on 20 Dec 1999 ..