пятница, 6 января 2012 г.

C/C++ работа с базой данных MySQL

Итак :-) Ниже будет пост, бьющий все рекорды просмотров на codepaste. В свое время я почему-то ничего толкового не нашел, было много экспериментов. Теперь я хочу показать тебе маленький, но очень гордый проект для работы с БД MySQL

Предисловие и приготовления

Итак, значит, дошли мы до серьезного приложения, где необходимо использовать полноценную БД?) Ок. Подготовка состоит из следующих этапов:

  1. Скачивание и установка MySQL-сервера (если приложение работает с локальной базой)
  2. Конфигурация графического интерфейса БД (phpMyAdmin - веб-морда, пригодится, если помимо MySQL-сервера у нас стоит еще и http-сервер(Apache, например). Так будет, если вы берете MySQL из состава Denwer. Иначе, если тебя интересует только БАЗА, то рекомендую dbForge Studio for MySQL)
  3. Конфигурация базы (собственно, описание ее структуры, связей, типов, состава полей и т.п...) или перенос дампа с существующей базы
  4. Написание программы-клиента.
Если ты не олух и баловался хотя бы с PHP (в противном случае советую найти где-нибудь нахаляву в торрентах диск тов.Попова "PHP и MySQL за 22 часа"...или фиг знает сколько часов. Но курс хороший. Даст базовые понятия PHP и обращения с нашей БД), то не будем заниматься глупостями и перейдем сразу к крайнему пункту. Необходимо изначально скачать MySQL-сервер с официального сайта, установить все компоненты, включая Development Components. (Аналогично вот этой статье) В проекте (под MVS2010) указать пути к заголовочным файлам:в верхнем меню Projects-> Project_name Properties... Там раскрыть категорию "Configuration Properties", справа найти "Include Directories" , в выпадающем списке выбрать добавить путь к папке (по дефолту: C: Program Files MySQL MySQL Server 5.0 include ) Помимо прочего, необходимо найди и подключить в коде (хотя, можно и в проекте, но я покажу наглядно с помощью pragma comment) статическую библиотеку libmysql.lib и кинуть libmysql.dll в
  • C:\Windows\System32\
  • О компоновке проекта можно почитать здесь

    Реализация

    Ок, все вводые выполнили, теперь можно приступать. Извращаться не будем, для наглядности пишем в одном файле. Сначала ничего интересного - описываем подключаемые библиотеки, файлы и пространства имен:

      // Указываем статическую библиотеку mysql
      #pragma comment(lib, "C:\Program Files\MySQL\MySQL Server 5.0\lib\debug\libmysql.lib")
    
      // Пригодится в программе далее
      #include <iostream>
      #include <cstring>
    
      // Файлы с интерфейсами mysql
      #include <my_global.h>
      #include <mysql.h>
    
    
      using namespace std;
    

    А вот теперь заполняем основные константы для подключения к базе и переходим к телу функции main. (Знатоков PHP сейчас начнет хватать за пятку де-жа-вю)

      // Зададим глобальные константы, которые понадобятся при подключении
    
      // Хост, где стоит MySQL (имя компьютера в сети / IP-адрес и т.п.),
      // в нашем случае - наш локальный компьютер
      const char Host[] ={"localhost"};
      // Имя пользователя MySQL, пусть будет root
      const char User[] = {"root"};
      // Пароль пользователя (ВНИМАНИЕ! Для Denwer и, если доступ к
      // базе настроен без пароля, указывать
      // вместо него в функции соединения 0 (без ковычек))
      const char Pass[] = {"123"};
      // Имя базы данных, с которой будем работать
      const char DBase[] = {"Base_primer"};
    
      // Начало функции main
      int main()
      {
      // Научим консоль понимать кириллицу (кодировка cp1251,
      // которую мы, кстати, должны были указать при установки БД)
      setlocale (LC_ALL,".1251"); 
    
      /* Указатель на соединение (дескриптор). Мы можем открывать много соединений,
      а он будет своего рода идентификатором конкретного соединения для операции.*/
      MYSQL *link; 
    
      // Инициализация нового подключения. Учи как китайскую грамоту.
      link = mysql_init(0);
    
      // Подключение к БД
      mysql_real_connect(link,Host,User,Pass,DBase,0,0,0);
    
      MYSQL_RES *result = 0; // Указатель на результат запроса
      MYSQL_ROW row;            // Переменная, из которой будем читать результат
    
      mysql_query(link, "SET NAMES 'cp1251'"); // Задаем кодировку соединения
    

    Итак, обращу твое внимание. Мы подключились к базе, уже без палева провели первый запрос. Да. Это функция mysql_query(дескриптор,"Запрос");. В данном случае, мы подключились и сказали:"Дорогая База Данных! Пожалуйста, сформируй кодировку вывода для соединения link как кириллическую (cp1251)". Тем самым мы, консоль и база говорят на одном языке (кодировке). Теперь можем смело приступать к более осмысленным вещам.

    Пусть у тебя есть некая таблица со статьями (articles), в ней есть поля автор (Authors) и название стати (Title). Попробуем "вытащить" из базы названия всех статей, автор которых, к примеру...Хватит это терпеть! Пусть будет Жириновский.

      // Напишем строку запроса
      // Обратите внимание на использование "прямых" и "косых" одиночных ковычек
      string  query = "SELECT `Title` FROM `articles` WHERE `Authors`='Жириновский'";
    
      // Теперь сделаем запрос к базе функцией 
      // mysql_query(указатель_соединения, запрос)
    
      mysql_query(link,query.c_str());
    
      // Извлечение результатов запроса
      result = mysql_store_result(link);
    
      // Если у нас база нашла хотя бы одну подходящую запись...
      if(mysql_num_rows(result) > 0)
      {
      /*
      "Расшифровываем" результат запроса в row (это массив строк,
      в которых каждый элемент - запрашиваемый параметр, у нас он
      только один, так как мы выбирали только 'Title')
      */
      while (row = mysql_fetch_row(result))
      {
      /*
      Выведем в цикле в консоль первую запись из всех найденых
      строк (она единственная, т.к. мы выбрали только 'Title')
      */
      cout << row[0] << endl;
    }
    }
    else
    {
      cout << "Не найдено ни одной статьи этого автора";
    }
    
    // После использования результата
    // обязательно освободи ресурсы перед следующим запросом!
    mysql_free_result(result);
    
    mysql_close(link); // Закрываем соединение
    
    system("PAUSE");
    return 0;
    }
    

    Это не безопасный вариант кода, если у нас какая-то операция не удастся, то программа вылетит с ошибкой. Давай еще раз то же самое, но с проверкой на успешность.

    #pragma comment(lib, "C:\Program Files\MySQL\MySQL Server 5.0\lib\debug\libmysql.lib")
      #include <iostream>
      #include <cstring>
      #include <my_global.h>
      #include <mysql.h>
    
      using namespace std;
    
      const char Host[] ={"localhost"};
      const char User[] = {"root"};
      const char Pass[] = {"123"};
      const char DBase[] = {"Base_primer"};
    
      int main()
      {
      setlocale (LC_ALL,".1251"); 
      MYSQL *link; 
    
      link = mysql_init(0);
      if (!link)
      {
      cout << "Невозможно получить дескриптор подключения к базе данных!"<<endl;
      system("PAUSE");
      return 1;
    }
    
    // Соединение
    if (!mysql_real_connect(link,Host,User,Pass,DBase,0,0,0))
    {
      cout << "Невозможно подключиться к базе данных!"<< endl;
      system("PAUSE");
      return 1;
    }
    
    MYSQL_RES *result = 0; 
    MYSQL_ROW row;            
    
    string  query = "SELECT `Title` FROM `articles` WHERE `Authors`='Жириновский'";
    
    cout << query << endl; 
    
    // Проведение запроса
    // Обратите внимание, когда все хорошо - возврашает 0
    if(mysql_query(link, "SET NAMES 'cp1251'") != 0)
    {
      cout << "Невозможно провести запрос!" << endl;
      mysql_close(link);
      system("PAUSE");
      return 1;
    }
    
    if ( mysql_query(link,query.c_str()) )
    // c_str() для string возвращает char-строку
    {
      cout << "Невозможно провести запрос!" << endl;
      mysql_close(link);
      system("PAUSE");
      return 1;
    }
    
    // Извлечение результата
    result = mysql_store_result(link);
    if (!result)
    {
      cout << "Извлечение результатов запроса завершилось аварийно!" < 0)
      {
      while (row = mysql_fetch_row(result))
      {
      cout << row[0] << endl; 
    }
    }
    else
    {
      cout << "Не найдено ни одной статьи этого автора" << endl;
    }
    
    // Закрытие соединения
    mysql_close(link);
    
    system("PAUSE");
    return 0;
    }
    

    Постскриптум

    Функций, доступных разработчикам, много. Мануалы по конкретным задачам гуглятся на ура. Я же ставил себе целью показать некий "Hello, World!", маленький, но уже обросший всем необходимым, 100% рабочий проект.



    1 комментарий:

    1. Здравствуйте, подскажите пожалуйста, а как можно создать базу данных в самой программе? Просто здесь в примере сразу подключение к БД, а есть ли возможность именно создать её?

      ОтветитьУдалить