Учебная страница курса биоинформатики,
год поступления 2010
Изменение и добавление данных в MySQL. Работа с MySQL из Java.
В качестве примера на этом занятии мы будем работать с базой данных, являющейся чем-то вроде записной книжки. Обращаясь к ней из Java можно будет сделать интерактивную записную книжку, в которую можно будет добавлять и извлекать записи через какой-нибудь интерфейс (например, графический). Основная сущность в этой базе данных будет человек - Person, про которого есть разнообразная информация (имя, ДР, телефоны, эл.адреса, интересы...). Всю эту информацию можно будет редактировать и просматривать, а также осуществлять поиск человека по какой-то информации о нем.
Структура базы будет примерно такая.
MySQL
Основные типы данных
INTEGER (INT)
FLOAT, DOUBLE
DATE (yyyy-mm-dd)
VARCHAR (длина текста) (до 255 символов)
TEXT (до 65535 символов)
BLOB - для хранения бинарных банных (например, картинок)
Основные действия с данными
извлечение данных (SELECT, WHERE, ORDER, GROUP, INNER JOIN...) - см. предыдущее занятие
создание/изменение/удаление таблиц (CREAT/ALTER/DROP)
добавление/изменение/удаление записей в таблице (INSERT/UPDATE/DELETE)
Ключи, индексы и атрибуты
INDEX (синоним - KEY) используется для ускорения выполнения операций SELECT по проиндексированным полям. В MySQL могут быть проиндексированы столбцы всех типов. Может быть несколько столбцов в индексе. Для столбцов типов CHAR и VARCHAR можно индексировать префикс столбца.
UNIQUE [INDEX] - индекс, для которого вводится ограничение на уникальность для значений полей, перечисленных в индексе. После этого СУБД будет следить за тем, чтобы не появилось двух записей, для которых в этих полях стоит одинаковый набор значений.
Первичный ключ таблицы (PRIMARY KEY) - особый тип уникального индекса - может быть только один в таблице (но при этом включать несколько полей). Используется для однозначной организации связи между таблицами и ускорения поиска.
AUTO_INCREMENT (атрибут для целочисленных столбцов). При записи величины NULL (рекомендуется) или 0 в этот столбец, автоматически создается значение на 1 больше предыдущего. В таблице может быть только один столбец AUTO_INCREMENT, и он должен быть индексирован (как правило это PRIMARY KEY).
Атрибут NOT NULL. Если в ячейке значения нет, то там находится специальное значение NULL. (Или то, что вы указали в DEFAULT). Ограничение NOT NULL вводится для поля на этапе создания таблицы. После этого СУБД следит за тем, чтобы для каждой записи в данном поле присутствовало какое-то ненулевое значение.
FOREIGN KEY - внешний ключ (может быть несколько в таблице). Служит для того, чтобы обозначить связь между полем-ссылкой данной таблицы и первичным ключом другой таблицы. Задавая внешний ключ, мы возлагаем на СУБД заботу о проверке целостности связи. Т.е. если мы пытаемся добавить запись в таблицу с внешним ключом, и эта запись ссылается на несуществующую запись в таблице, на которую мы ссылаемся, то будет выдано сообщение об ошибке. Также СУБД должна сообщить об ошибке, если попытаться удалить запись из одной таблицы, на которую ссылаются некоторые записи из таблицы с внешним ключом. Для использования этой опции необходимо использовать архитектуру InnoDB, причем обе таблицы должны быть InnoDB-типа; обязательно также наличие индекса, в котором внешний ключ и ссылочный ключ должны находиться в первых столбцах (индексы не создаются автоматически: их создание требуется задавать явно).
Создание таблицы
Пример создания таблицы person:
CREATE TABLE person (person_id INT NOT NULL AUTO_INCREMENT, nick VARCHAR(50) NOT NULL, surname VARCHAR(50), name VARCHAR(50), second_name VARCHAR(50), birthday DATE, PRIMARY KEY (person_id), UNIQUE (nick), INDEX (surname) )DEFAULT CHARSET=utf8; // для поддержки русского языка, но места занимает больше (+ не факт, что все сработает)
с внешним ключом:
CREATE TABLE email ( person_id INT NOT NULL, email VARCHAR(50) NOT NULL, FOREIGN KEY (person_id) REFERENCES person (person_id), UNIQUE(person_id,email) INDEX (email) )DEFAULT CHARSET=utf8;
Синтаксис определения FOREIGN KEY, задающий действия при попытках удаления/изменения данных, приводящих к нарушению целостности данных:
...FOREIGN KEY (...) REFERENCES ... (...) [ON DELETE reference_option] [ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION
Добавление индексов
Пример:
CREATE INDEX birthday ON person (birthday);
Синтаксис:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [index_type] ON tbl_name (index_col_name,...) [index_type] index_col_name: col_name [(length)] [ASC | DESC] index_type: USING {BTREE | HASH | RTREE}
Просмотр индексов таблицы:
SHOW INDEX FROM person;
Добавление записей
INSERT INTO person (nick, surname, name, birthday) VALUES ('musya', 'Иванова','Маша','1998-10-10');
Если происходит вставка значений всех полей, то имена полей можно не указывать. Тогда порядок значений должен соответствовать порядку соответствующих столбцов в таблице.
Изменение записей
UPDATE person SET nick= 'mila' WHERE nick = 'musya';
или
UPDATE person SET second_name = 'Владимировна' WHERE nick = 'mila';
Удаление записей
DELETE FROM person WHERE person_id = 2;
Изменение структуры таблицы
ALTER TABLE ADD/RENAME/DROP/CHANGE COLUMN/INDEX/PRIMARY KEY...
Работа с MySQL из Java
Для того, чтобы подключиться к СУБД нам нужно следующее:
иметь java-библиотеку (.jar файл), предоставляемую разработчиком СУБД, которая является клиентом подключения к СУБД. В нашем случае это файл mysql*.jar (скачать можно тут). Его нужно подсоединить к проекту.
знать полное имя главного класса драйвера, хранящегося в этой библиотеке. В нашем случае это org.gjt.mm.mysql.Driver.
знать, по какому принципу строится текстовый путь к СУБД данного производителя, обычно включающий сетевое имя машины сервера, сокетный порт, иногда имя экземпляра СУБД, имя базы данных. В нашем случае это: jdbc:mysql://db.bioinf.fbb.msu.ru:3306/student3_db (имя пользователя: student, пароля нет).
Для открытия соединения нужно выполнить следующий код:
1 import java.sql.*;
2 …
3 try{
4 Class.forName("org.gjt.mm.mysql.Driver");
5 }catch(Exception ex) {
6 ex.printStackTrace();
7 }
8 try {
9 String url = "jdbc:mysql://db.bioinf.fbb.msu.ru:3306/student3_db";
10 Connection conn = DriverManager.getConnection(url,"student","");
11 Statement stmt = conn.createStatement();
12 … // что-то делаем с базой
13 stmt.close();
14 conn.close();
15 }catch(SQLException ex) {
16 …
17 }
Далее, если мы хотим выбрать данные из базы, то мы должны отправить на сервер запрос, и получить обратно объект типа ResultSet. Этот объект позволяет работать с каждой ячейкой каждой вернувшейся записи:
Метод rs.next() устанавливает указатель текущей записи на следующую запись. В самом начале, сразу после того, как мы получили объект ResultSet, его указатель стоит перед первой записью. Так что первый вызов rs.next() поставит указатель на первую запись.
Методы rs.get<тип>(<номер>/<имя>) возвращают значения, находящиеся в ячейках текущей записи. Тип бывает Int, Double, String, и т.д. Номер ячейки нумеруется с единицы.
Если команда не должна возвращать данных (например, команда INSERT), то нам нужно использовать метод класса Statement execute(<запрос>).
Если нужно узнать, какой AUTO_INCREMENT ID только что вставился (при выполнении вставки нулевого значения в поле AUTO_INCREMENT) можно использовать метод getGeneratedKeys():
Очень важно не забывать закрывать соединение (connection) и statement, когда они больше не нужны:
stmt.close(); conn.close();
И нужно иметь в виду, что у одного объекта Statement может быть только один открытый ResultSet: при совершении следующего запроса у данного объекта Statement, предыдущий ResultSet закрывается. В этом случае выпадает ошибка:
1 java.sql.SQLException: Operation not allowed after ResultSet closed