Эти примеры иллюстрируют, как разработать приложения Python и скрипты, которые соединяются с использованием MySQL Connector/Python.
Конструктор connect()
создает связь с сервером MySQL и возвращает объект
MySQLConnection
.
Следующий пример показывает, как соединиться с сервером MySQL:
import mysql.connector
cnx = mysql.connector.connect(user='scott', password='password
',
host='127.0.0.1',
database='employees')
cnx.close()
Раздел 7.1 описывает разрешенные аргументы соединения.
Также возможно создать объекты связи, используя класс connection.MySQLConnection():
from mysql.connector import (connection)
cnx = connection.MySQLConnection(user='scott', password='password
',
host='127.0.0.1',
database='employees')
cnx.close()
Обе формы (любое использование конструктора
connect()
или класса непосредственно)
действительны и функционально равны, но использование
connect()
предпочитается и используется
большинством примеров в этом руководстве.
Чтобы обработать ошибки связи, используйте
try
и ловите все ошибки при использовании
исключения errors.Error
:
import mysql.connector from mysql.connector import errorcode try: cnx = mysql.connector.connect(user='scott', database='employ') 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()
Определение аргументов соединения в словаре и использование оператора
**
:
import mysql.connector
config = {
'user': 'scott',
'password': 'password
',
'host': '127.0.0.1',
'database': 'employees',
'raise_on_warnings': True
}
cnx = mysql.connector.connect(**config)
cnx.close()
Connector/Python предлагает два внедрения: чистый интерфейс Python и
расширение C, которое пользуется библиотекой клиента (см.
главу 8). Это может формироваться во время
выполнения, используя параметр use_pure
.
Это по умолчанию False
с MySQL 8 означая, что
расширение C используется. Если расширение C недоступно на системе, тогда
use_pure
по умолчанию
True
. Установка
use_pure=False
заставляет связь использовать
расширение C, если ваша установка Connector/Python включает его, в то время
как use_pure=True
означает, что внедрение Python
используется при наличии.
Опция use_pure
и расширение C были добавлены
в Connector/Python 2.1.1.
Следующий пример показывает, как установить
use_pure
= False.
import mysql.connector
cnx = mysql.connector.connect(user='scott', password='password
',
host='127.0.0.1',
database='employees',
use_pure=False)
cnx.close()
Также возможно использовать расширение C непосредственно, импортируя
модуль _mysql_connector
вместо
mysql.connector
. Для получения дополнительной
информации посмотрите раздел
8.2.
Все запросы DDL (Data Definition Language) выполняются, используя структуру, известную как курсор. Следующие примеры показывают, как составить таблицы Employee Sample Database. Вам они нужны для других примеров.
В сервере MySQL таблицы очень долговечные объекты и часто нужен доступ многочисленным запросам, написанным на различных языках. Вы могли бы, как правило, работать с таблицами, которые уже есть, вместо того, чтобы создать их в рамках вашего собственного приложения. Не стои создавать и удалять таблицы много раз, поскольку это дорогая операция. Исключение: temporary tables, которые могут быть составлены и удалены быстро.
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")
Предыдущий код показывает, как мы храним запросы
CREATE
в словаре Python
TABLES
. Мы также определяем базу данных в
глобальной переменной DB_NAME
,
которая позволяет вам легко использовать различную схему.
cnx = mysql.connector.connect(user='scott') cursor = cnx.cursor()
Единственный сервер MySQL может управлять многократными базами данных. Как правило, вы определяете базу данных, чтобы переключиться на нее, соединяясь с сервером MySQL. Этот пример не соединяется с базой данных, чтобы можно было удостовериться, что база данных существует и создать ее, если ее еще нет:
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)
Мы сначала пытаемся перейти на конкретную базу данных, используя
свойство database
объекта связи
cnx
. Если есть ошибка, мы исследуем код ошибки,
чтобы проверить, не существует ли база данных. Если это так, мы вызываем
функцию create_database
, чтобы создать базу.
На любой другой ошибке приложение выходит и показывает сообщение об ошибке.
После того, как мы успешно создадим или переключимся на целевую базу
данных, мы составляем таблицы, повторяя по пунктам словарь
TABLES
:
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()
Чтобы обработать ошибку, когда таблица уже существует, мы уведомляем
пользователя, что это уже было там. Другие ошибки печатаются, но мы
продолжаем составлять таблицы. Пример показывает, как обращаться с условием
"табьлица уже есть" в целях иллюстрации.
В реальном применении мы, как правило, избегали бы состояния ошибки полностью
при помощи IF NOT EXISTS
в запросе
CREATE TABLE
.
Вывод был бы чем-то вроде этого:
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
Чтобы наполнить таблицы, используйте файлы дампа
Employee Sample Database. Обратите внимание на то, что вам нужны только
файлы дампа данных, которые вы найдете в архиве
employees_db-dump-files-1.0.5.tar.bz2
.
После загрузки файлов выполните следующие команды, добавив опции связи к
командам mysql, если надо:
shell>tar xzf employees_db-dump-files-1.0.5.tar.bz2
shell>cd employees_db
shell>mysql employees < load_employees.dump
shell>mysql employees < load_titles.dump
shell>mysql employees < load_departments.dump
shell>mysql employees < load_salaries.dump
shell>mysql employees < load_dept_emp.dump
shell>mysql employees < load_dept_manager.dump
Вставка или обновление данных также сделаны, используя структуру,
известную как курсор. Когда вы используете механизм системы хранения
транзакций, такой как InnoDB
(умолчание для
MySQL 5.5 и выше), необходимо
commit данные после последовательности
INSERT
,
DELETE
и
UPDATE
.
Этот пример показывает, как вставить новые данные. Второй
INSERT
зависит от значения недавно
созданного primary key первого. Пример также демонстрирует, как
использовать расширенные форматы. Задача состоит в том, чтобы добавить нового
сотрудника, начинающего работать завтра с зарплатой в 50000.
Следующий пример использует таблицы, составленные в
разделе 5.2.
Опция столбца AUTO_INCREMENT
для первичного ключа таблицы employees
важна, чтобы гарантировать надежные, легко доступные для поиска данные.
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()
Мы сначала открываем связь с сервером MySQL и сохраняем
объект соединения
в переменной cnx
.
Мы тогда создаем новый курсор, по умолчанию это объект
MySQLCursor,
используя метод связм
cursor()
.
Мы могли бы вычислить понятие "завтра", вызвав функцию базы данных, но для
ясности мы делаем это в Python, используя модуль
datetime
.
Оба запроса INSERT
сохранены в переменных add_employee
и
add_salary
. Отметьте что второй
INSERT
использует расширенные
коды формата Python.
Информация нового сотрудника хранится в кортеже
data_employee
. Запрос, чтобы ввести нового
сотрудника выполняется, и мы получаем недавно вставленное значение для
столбца emp_no
(столбец
AUTO_INCREMENT
) с использованием свойства
lastrowid
объекта курсора.
Затем мы вставляем новую зарплату для нового сотрудника, используя
переменную emp_no
в словаре, содержащем данные. Этот словарь передается к методу
execute()
курсора, если произошла ошибка.
Connector/Python по умолчанию выключает
autocommit, а MySQL 5.5 и выше используют транзакционные
таблицы InnoDB
. Поэтому необходимо явно передать
ваши изменения, используя метод commit()
.
Вы могли бы также
отменить их методом rollback()
.
Следующий пример показывает, как
запрос данных использует курсор, созданный с использованием
метода
cursor()
.
Возвращенные данные отформатированы и выведены на консоль.
Задача состоит в том, чтобы выбрать всех сотрудников, нанятых в 1999 году, и напечатать их имена и даты на консоль.
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()
Мы сначала открываем связь с сервером MySQL и сохраняем
объект соединения
в переменную cnx
. Затем создаем новый
курсор, по умолчанию это объект
MySQLCursor,
используя метод
cursor()
.
В предыдущем примере мы храним запрос SELECT
в переменной query
. Обратите внимание на то, что
мы используем %s
-маркеры без кавычек там,
где даты должны были быть. Connector/Python конвертирует
hire_start
и
hire_end
из типов Python
до типа данных, который MySQL понимает и добавляет необходимые кавычки.
В этом случае это заменяет первый %s
на
'1999-01-01'
, а второй на
'1999-12-31'
.
Мы тогда выполняем операцию, сохраненную в переменной
query
, используя метод
execute()
. Данные, раньше заменившие
%s
-маркеры в запросе, передаются как кортеж:
(hire_start, hire_end)
.
После выполнения запроса сервер MySQL готов послать данные.
Набор результатов может быть пустым, одной строкой или 100 миллионами строк.
В зависимости от ожидаемого объема можно использовать различные методы, чтобы
обработать этот набор результатов. В этом примере мы используем объект
cursor
как итератор. Первый столбец в строке
сохранен в переменной first_name
, второй в
last_name
, третий в
hire_date
.
Мы печатаем результат, форматируя вывод, используя встроенную функцию
Python format()
. Отметьте, что
hire_date
был преобразован автоматически
Connector/Python в объект Python datetime.date
.
Это означает, что мы можем легко отформатировать дату в более читаемой форме.
Вывод должен быть чем-то вроде этого:
... 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 ...