Работа с MySQL в С++ с использованием библиотеки mysql++
Под впечатлением от этой статьи я решил написать свой небольшой мануал по работе с СУБД MySQL, используя библиотеку mysql++. Данная библиотека представляет собой кроссплатформенное решение, написанное на С++, предоставляет богатый набор классов и позволяет эффективные приложения. Т.к. моей основной операционной системой является Linux — я буду рассматривать процесс создания приложения под Unix платформу. Под платформу Windows все будет практически точно так же, за исключением собственно подключения библиотеки, ее заголовочных файлов к IDE (MS Visual studio, Dev-c++).
Для создания приложения в среде Unix наличие IDE, как и собственно графической оболочки не необходимо, процесс написания и компиляции может проходить в голой консоли.
Для начала необходимо скачать саму библиотеку, это можно сделать по следующим ссылкам:
Исходный код, для самостоятельной компиляции+документация
Бинарные RPM сборки (следует попробовать разные версии, т.к. некоторые могут не установиться):
RPM ver1
RPM ver2
RPM ver3
Я не буду описывать установку библиотеки для каждой платформы, т.к. это выходит за рамки данной статьи.
Теперь пришло время познакомится с библиотекой, рассмотреть ее классы и создать простое приложение, которое будет подключаться к базе данных и запрашивать данные из таблицы, добавлять новые, модифицировать существующие записи.
Для того, что бы воспользоваться возможностями библиотеки, следует подключить заголовочный файл 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++, список же классов и их методов намного обширнее, полностью ознакомится с ними можно на этой странице.
А здесь доступна полная документация, на английском языке, с различными примерами.
спасибо за мануал — очень пригодился !!
Блин. А у меня вот нифига не компилит…
Говорит что /usr/bin/ld: cannot find -llibmysqlpp , хотя она лежит в /usr/local/lib….
ничего не могу понять 😕
А подскажите плиз, как сделать тоже самое только на С а не С++
> А подскажите плиз, как сделать тоже самое только на С а не С++
Использовать _не обёртку_ к базе данных
#include «mysql.h»
Vsio ok, no kak biblioteku potkliucit? VS 6.0?
Народ плиз помогите вам всеравно это легко сделать,задачку на с++»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.»тоже самое ток с динамическим выделением памяти» ПОЖАЛУЙСТА
За книжку и вперед!!