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` ("
" `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_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:
cursor.execute("USE {}".format(DB_NAME))
except mysql.connector.Error as err:
print("Database {} does not exists.".format(DB_NAME))
if err.errno == errorcode.ER_BAD_DB_ERROR:
create_database(cursor)
print("Database {} created successfully.".format(DB_NAME))
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 table_name in TABLES:
table_description = TABLES[table_name]
try:
print("Creating table {}: ".format(table_name), end='')
cursor.execute(table_description)
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:
Database employees does not exists.
Database employees created successfully.
Creating table employees: OK
Creating table departments: already exists.
Creating table salaries: already exists.
Creating table dept_emp: OK
Creating table dept_manager: OK
Creating table titles: OK
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:
$> tar xzf employees_db-dump-files-1.0.5.tar.bz2
$> cd employees_db
$> mysql employees < load_employees.dump
$> mysql employees < load_titles.dump
$> mysql employees < load_departments.dump
$> mysql employees < load_salaries.dump
$> mysql employees < load_dept_emp.dump
$> mysql employees < load_dept_manager.dump