» Работа с MySQL в С++ с использованием библиотеки mysql++ Базы данных. с++ и с #. . Блог программистов


Блог программистов




200916 Авг

Работа с MySQL в С++ с использованием библиотеки mysql++

Под впечатлением от этой статьи я решил написать свой небольшой мануал по работе с СУБД MySQL, используя библиотеку mysql++. Данная библиотека представляет собой кроссплатформенное решение, написанное на С++, предоставляет богатый набор классов и позволяет эффективные приложения. Т.к. моей основной операционной системой является Linux — я буду рассматривать процесс создания приложения под Unix платформу. Под платформу Windows все будет практически точно так же, за исключением собственно подключения библиотеки, ее заголовочных файлов к IDE (MS Visual studio, Dev-c++).
Для создания приложения в среде Unix наличие IDE, как и собственно графической оболочки не необходимо, процесс написания и компиляции может проходить в голой консоли.

Для начала необходимо скачать саму библиотеку, это можно сделать по следующим ссылкам:
Исходный код, для самостоятельной компиляции+документация

Бинарные RPM сборки (следует попробовать разные версии, т.к. некоторые могут не установиться):
RPM ver1
RPM ver2
RPM ver3

Версия для MS Visual C++

Я не буду описывать установку библиотеки для каждой платформы, т.к. это выходит за рамки данной статьи.

Теперь пришло время познакомится с библиотекой, рассмотреть ее классы и создать простое приложение, которое будет подключаться к базе данных и запрашивать данные из таблицы, добавлять новые, модифицировать существующие записи.

Для того, что бы воспользоваться возможностями библиотеки, следует подключить заголовочный файл mysql++.h и пространство имен mysqlpp.

Код:

#include <mysql++.h>
using namespace mysqlpp;

Далее воспользуемся классом Connection, который обеспечивает подключение и аунтефикацю на интересующей нас базе данных. Кратко рассмотрим этот класс и наиболее интересные его методы.
Класс имеет два конструктора:
Connection(bool te=true) — создание экземпляра класса, без подключения к бд
Connection (const char *db, const char *server=0, const char *user=0, const char *password=0, unsigned int port=0) — создание экземпляра класса с подключением к указанной бд по указанным параметрам. Думаю, что названия параметров говорят сами за себя и не требуют пояснений
client_version() — возвращает строку типа string, содержащую версию библиотеки.
connect (const char *db=0, const char *server=0, const char *user=0, const char *password=0, unsigned int port=0) — то же самое, что и описанный выше конструктор, применяется в случае использования конструктора Connection(true).
connected() — возвращает true, в случае если выполнено подключение к базе и false, если подключение не выполнено.
disconnect() — выполнить отключение от базы данных.
error() — возвращает последнюю ошибку.
query (const char *qstr=0) — возвращает объект типа query, позволяющий выполнить запрос (об этом ниже).
count_rows (const std::string &table) — возвращает результат типа unsigned long, количество строк в указанной таблице table.

Класс Connection имеет еще ряд методов, но они нам пока не интересны. Теперь рассмотрим класс query. В нем нас интересуют следующие методы:
store() — возвращает результат запроса, типа StoreQueryResult.
execute() — выполнить запрос, не требующий возвращения данных, метод возвращает результат SimpleResult.

Класс StoreQueryResult — именно он позволяет обратиться к запрошенной таблице, представленной как двумерный массив, получить количество вовращенных строк.
num_rows() — возвращает количество строк
empty() — возвращает true, в случае, если запрос ничего не вернул и false, если запрос вернул данные.

Класс SimpleResult, у этого класса нас может интересовать всего один единственный метод
rows() — возвращает количество строк, подвергшися изменению, во время вызова execute()
Данное приложения представляет собой очень простой и детально расписанный пример, который поможет разобраться новичкам.

Код:

//подключаем необходимые заголовочные файлы, пространства имен
#include <mysql++.h>
#include <iostream>
using namespace mysqlpp;
using namespace std;
//создаем экзмемпляры необходимых объектов
Connection conn;
StoreQueryResult queryres;
string querysring; 

int main()
{
	try
	{
		conn.connect("database", "dataserver", "datauser", "password"); //пробуем подключиться к базе
	}
	catch (ConnectionFailed err) //перехватываем возможное исключение типа ConnectionFailed
		{
			cout << "Не удалось подключится к базе данных, причина: " << err.what() << endl;
			return 1;
		}
	if(conn.connected()) //проверяем, подключены ли мы к базе данных
	{
		querystring = "SELECT * FROM Datatable"; //инициализируем строку запроса
		queryres = conn.query(querystring.c_str()).store(); //выполняем запрос
		if(!res.empty()) //если что-то вернулось
		{
			for(int rc = 0; rc < (int)queryres.num_rows(); ++i) //построчно выводим на экран
				cout << queryres[rc]["colname_one"] << queryres[rc]["colname_sec"] << endl;
		} else
			cout << "Запрос не вернул данных" << endl; //иначе сообщаем что ничего не вернулось
	 	conn.disconnect(); //отключаемся от базы данных		 
	} else
	{
		cout << "Подключение к базе данных потеряно..." << endl; //иначе сообщаем что коннект отвалился
		return 1;
	}
}

Как видно, программа очень проста и легка для понимания. В начале мы пробуем подключится к базе данных database, которая находится на сервере dataserver, как пользователь datauser с паролем password. В случае ошибки — перехватываем исключение типа ConnectionFailed, которое имеет метод what(), возвращающий текстовое описание проблемы
(так же у класса ConnectionFailed есть метод errnum (), возвращающий номер ошибки). После успешного подключения, проверяем еще раз, подключены ли мы, т.к. в случае нестабильной связи или по иным причинам — соединение может успеть отвалиться. В случае успешной проверки связи, инициализируем строку запроса querystring, наш запрос имеет вид: «SELECT * FROM Datatable», что означает вернуть все абсолютно все записи из некой таблицы Datatable. После этого вызываем метод query, класса соединения, и у возвращенного объекта, вызываем метод store(), возвращенный результат запроса сохраняем в queryres. Далее проверяем, не пуст ли результат. Если нет — построчно выводим записи на экран.
В классе StoreQueryResult, экземпляром которого является queryres, строки хранятся в виде двумерного ассоциативного массива, это дает возможность обратиться к соотвествующему столбцу по его имени. Как в данном случае: queryres[rc][«colname_sec»] — обращаемся к rc-ой строке и столбцу под названием colname_one.
После окончания работы с бд следует обязательно закрыт соединение, что мы и делаем вызывая метод disconnect().

В предидущем примере мы научились получать интересующие нас записи, теперь мы научимся добавлять и удалять их.
Я не буду повторять код всей программы, а просто лишь опишу способы, с помощью которых достигается нужный нам результат. В примере ниже показано, как можно добавить строку в нашу таблицу Datatable.
SQL запрос в данном случае выглядит как INSERT INTO Datatable(colname_one, colname_sec) VALUES(‘data1’, ‘data2’).
А для выполнения этого запроса будем использовать метод execute().

Код:

	querystring = "INSERT INTO Datatable(colname_one, colname_sec) VALUES('data1', 'data2')";
	cout << "Добавлено строк: " << conn.query(querystring).execute().rows() << endl; //выполнение запроса с выводом результата

Как видно, все очень и очень просто, инициализируем строку запроса, и вызываем метод execute(), который возвращает нам объект класса SimpleResult, и используя метод rows() последнего мы получаем сколько строк изменено, т.е. в данном случае добавлено. Полученный результат сразу же шлем в поток вывода. Я написал все без введения дополнительных, промежуточных, переменных, для компактности и экономичности.

Все прочие операции, модификация, удаление строк выполняются аналогично, отличия будут только в самом тексте SQL запроса:

Модификация:

Код:

	querystring = "UPDATE Datatable SET colname_sec = 'data3' WHERE colname_one = 'data1'";
	cout << "Изменено строк: " << conn.query(querystring).execute().rows() << endl; //выполнение запроса с выводом результата

Удаление:

Код:

	querystring = "DELETE FROM Datatable WHERE colname_one = 'data1'";
	cout << "Удалено строк: " << conn.query(querystring).execute().rows() << endl; //выполнение запроса с выводом результата

Случается, что запросы могут некорректно работать с кириллическими символами, для устранения этой возмутительной ошибки следует выполнит особый запрос:

Код:

	querystring = "SET CHARSET UTF8"; //задаем кодировку
	conn.query(querystring).execute(); //выполняем запрос

В данном примере указана кодировка UTF8, как основная на современных Linux системах. Вам следует задать кодировку вашей системы, для корретной обработки киррилицы.
Для компиляции программы следуюет выполнить команду:

Код:

c++ -o proga -I/usr/include/mysql -I/usr/include/mysql++ -lmysqlpp -L/usr/lib/mysql -L/usr/local/lib/mysql++ main.cpp

В этой команде файл с исходным кодом main.cpp компилируется, подключая необходимые библиотеки.

Заключение.
Выше были описаны примеры, позволяющие взаимодействовать с базой данных MySQL на различных платформах. Были затронуты лишь общие методы работы с библиотекой mysql++, список же классов и их методов намного обширнее, полностью ознакомится с ними можно на этой странице.
А здесь доступна полная документация, на английском языке, с различными примерами.

Комментарии

  1. Октябрь 28th, 2009 | 22:21

    спасибо за мануал — очень пригодился !!

  2. drugsmouse
    Январь 20th, 2010 | 17:54

    Блин. А у меня вот нифига не компилит…
    Говорит что /usr/bin/ld: cannot find -llibmysqlpp , хотя она лежит в /usr/local/lib….
    ничего не могу понять 😕

  3. Смит
    Март 16th, 2010 | 08:28

    А подскажите плиз, как сделать тоже самое только на С а не С++

  4. Март 31st, 2010 | 17:40

    > А подскажите плиз, как сделать тоже самое только на С а не С++
    Использовать _не обёртку_ к базе данных

    #include «mysql.h»

  5. Micro
    Ноябрь 6th, 2010 | 01:28

    Vsio ok, no kak biblioteku potkliucit? VS 6.0?

  6. qwerty
    Ноябрь 20th, 2010 | 23:27

    Народ плиз помогите вам всеравно это легко сделать,задачку на с++»1.На основе исходных массивов A[n] и B[m] (n и m – рабочие размеры массивов) сформировать двумерный массив C[n][m], элементы которого будут вычисляться по формуле: Cji = Ai + Bj. Вывести элементы массивов A, B и С на экран.
    Массивы A, B и C содержат вещественные числа. Значения m и n вводятся пользователем с клавиатуры. Значения элементов массивов A и B генерируются при помощи датчика случайных чисел. Перед формированием массива С, следует упорядочить массивы A и B по возрастанию, используя метод «пузырька».
    «2.»тоже самое ток с динамическим выделением памяти» ПОЖАЛУЙСТА

  7. Февраль 3rd, 2011 | 22:42

    За книжку и вперед!!