Подключение к базе данных в Delphi

Подключение Delphi к базе данных

Доброго времени суток, дорогие читатели!

Давайте рассмотрим как выглядит подключение к базе данных в Delphi. Начнем с некоторых базовых понятий.

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

Набор данных — это та же самая таблица, только хранится она не на жестком диске компьютера, а в оперативной памяти. То есть, есть такой объект, как набор данных. Мы его создаем (программно или просто кидаем на форму из панели инструментов) и в нем в специальном свойстве мы задаем команду SELECT на выборку из одной или нескольких объединенных таблиц базы данных. В результате чего мы получаем набор данных из физической таблицы. Но наш созданный набор хранится в оперативной памяти компьютера.

Это похоже на то, когда мы открываем файл MS Word и он загружается в нашу оперативную память. Мы работаем не с самим файлом, а с его копией, загруженной в оперативную память машины. А когда нажимаем на кнопку «Сохранить», то наша виртуальная копия перезаписывает ту, которая хранится на жестком диске.

В наборе данных тоже самое. Он виртуальный и мы работаем с его виртуальной копией. Если набор данных состоит из одной таблицы, то мы можем его изменять и эти изменения затем сохранить в физической таблице.

На форме может быть множество элементов управления. И с этими элементами управления может быть связано множество наборов данных. Это может быть один набор данных, а может быть три или четыре...

И чтобы сделать выборку из базы данных, каждый из этих наборов данных нужно подключить к базе данных.

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

Поэтому в Delphi существует такой объект как Connection. Он может немножко по разному называться в разных библиотеках. Например, в библиотеке ADO (которая также поддерживается в Delphi) данный объект называется adoConnection. Даже будем говорить, не объект, а класс. Тогда он будет именоваться, как принято в Delphi TadoConnection. Его аналогом в устаревшей BDE будет являться TDatabase, а в новой технологии доступа к данным FireDAC таким классом будет выступать TFDConnection.

Так вот все эти наборы данных следует связать с одним объектом Connection. Мне очень нравится библиотека ADO (ActiveX Data Objects) от фирмы Microsoft (не путать с ADO.NET — это разные библиотеки и развиваются они параллельно) и дальнейшие примеры я буду показывать на ее основе. В других библиотеках действия по подключению будут аналогичными.

Давайте приступим. Запустим Delphi. В моем примере это Delphi 10.4.2 Sydney. В других версиях пример абсолютно не отличается. Создадим проект, форму, набросаем на нее компоненты, которые будут отображать содержимое полей нашей таблицы базы данных.

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

Обычно более или менее среднее и крупное приложение удобно создавать в стили многодокументного приложения (MDI-интерфейс). Есть также SDI (однодокументный стиль).Тип приложения MDI представляет из себя родительскую форму, которая является главной. А уже в родительской форме расположены дочерние формы. Пример MDI приложения:

В данном примере есть одна общая форма (или окно) и в ней внутри содержится еще две формы, которые являются дочерними по отношению к этой главной форме. Это и есть MDI приложение.

Мы будем рассматривать пример подключения в таком типе приложений.

Так вот в таких типах приложений, а также в SDI удобно объект Connection располагать на главной форме. Все остальные объекты доступа к данным, которые будут располагаться на дочерних формах подключаются к одному объекту Connection.

Давайте посмотрим на упрощенную схему подключения:

Здесь е рассматриваются такие специфические объекты, как объекты управления транзакциями. Хотя они очень важны, но тем не менее пока для простоты и наглядности я не стал включать их в эту схему.

Справа на схеме находится база данных К ней подключается объект adoConnection. А уже к объекту adoConnection подключаются наборы данных adoQuery. Здесь и далее рассматриваются объекты наборы данных adoQuery. Эти объекты соответствую реляционному доступу к данным, то есть для получения данных они используют команду Select. Есть также adoTable (навигационный доступ к данным). Такие объекты для доступа к данным таблицы используют свойства, где указывается имя таблицы и так далее. Эти объекты следует использовать только для доступа к локальным базам данных. Для доступа к промышленным базам данных следует использовать только реляционный подход. Его же, кстати, можно использовать и для доступа к локальным (настольным) базам данных, что я и рекомендую делать.

У объекта adoConnection есть свойство ConnectionString. Данное свойство является строковым и в нем содержится строка подключения к базе данных. Это же свойство есть и у объектов adoQuery. Но как уже было сказано выше, не стоит каждый объект набора данных подключать отдельно к базе данных. Что содержит в себе свойство ConnectionString?

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

Чтобы нам подключиться к базе данных MS Access необходимо 2003 года необходимо использовать драйвер Jet 4.0. Эта версия СУБД давно устарела, но скорее морально, чем в практическом смысле. Одна вещь, которая является преимуществом использования Access 2003 является тем, что драйвер доступа к данным Jet 4.0 поставляется вместе ОС WIndows всех современных версий, начиная еще с Windows XP (если мне не изменяет память, то начиная с этой версии, но это не сильно важно). А, например, для MS Access 2007—2019 уже не поставляется. И этот драйвер нужно включать в дистрибутив при распространении приложения, либо включать его в требования, необходимые для функционирования приложения, что не есть удобно. Рассмотрим, как выглядит строка подключения для MS Access 2003:

sTekPapka:=getcurrentdir; //Путь к текущей папке
PathBD:=getcurrentdir+'\Database\DataBase.mdb'; //Путь к БД
ADOConnection1.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='''+PathBD+'''';

Здесь PathBD является переменной, содержащей путь к базе данных. В данном примере база данных содержится в корневом Корневой каталог/Database\DataBase.mdb.

Переменная PathBD может содержать в себе любой путь до базы данных.

Если необходимо подключиться к базам данных MS Access, например 2007, 2010 — 2016, то следует использовать новый драйвер, который пришел на замену Jet 4.0 и называется он: Microsoft.ACE.OLEDB.12.0. Его можно использовать и для версии 2003. Соответственно строка подключения будет выглядеть немного по другому:

ADOConnection1.ConnectionString:='Provider=Microsoft.ACE.OLEDB.12.0;Data Source='''+PathBD+'''';

Теперь давайте посмотрим как подключиться к базе данных MySQL. Для версии MySQL 5.2-5.5 подключение будет выглядеть следующим образом:

ADOConnection1.ConnectionString:='Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="Driver=MySQL ODBC 5.1 Driver;SERVER=127.0.0.1;UID='+sUser+';password='+sPassword+';Option=2;DATABASE=languageschool;PORT=3306;charset=cp1251;COLUMN_SIZE_S32=1"';

Подключение к MySQL имеет свою особенность в отличие от подключения к базе данных настольной СУБД. Здесь путь указывается в виде IP-адреса (либо можно указать localhost, если база данных расположена на одной машине с программой). Вообще удобно IP-адрес в этой строке также задавать в виде переменной, как это сделано для пользователя и пароля, а именно кусочек строки UID='+sUser+';password='+sPassword+'

Здесь не прописывается папка, в которой лежит база данных, а прописывается просто адрес компьютера в сети, имя пользователя и пароль к базе данных. Имя базы данных содержится в параметре DATABASE.

Для доступа к базе данных MySQL версии 8.0.28 и выше (может быть и ниже — не пробовал) строка подключения будет выглядеть так:

sConnection:='Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="Driver=MySQL ODBC 8.0 Unicode Driver;SERVER='+sServer+';UID='+sUser+';password='+sPassword+';Option=2;DATABASE=bus_station;PORT='+sPort+';charset=cp1251;COLUMN_SIZE_S32=1"';
ADOConnection1.ConnectionString:=sConnection;

Здесь для разнообразия я сделал немного по другому. Всю строку сформировал в переменной sConnection, а потом ее содержимое присвоил свойству ConnectionString. О том, как установить СУБД MySQL Server 8.0.28 написано вот в этой статье.

Здесь следует пояснить очень важную деталь. MySQL 8.0.28 — это 64-разрядная СУБД. Программы же мы пишем в большей части пока еще 32-х разрядные, потому что еще достаточно много компьютеров с установленной ОС WIndows 32-х разрядной версией. Поэтому драйвер доступа к данным MySQL (он же Connector ODBC) следует ставить не 64-разрядный, а 32-разрядный. Соответственно, если программа компилируется для 64-хразрядной версии Windows (Delphi один и тот же код компилирует и для 32-х разрядной и для 64-разрядной версии). тогда драйвер используется также 64-разрядный.

Вышеприведенный код удобно располагать в событии создания формы onFormCreate:

procedure TfrmMDI.FormCreate(Sender: TObject);
var
  iniF: TIniFile;//Создаем объект для доступа к INI-файлу
  sServer, sPort, sUser, sPassword, sConnection: string;//Переменные для строки подключения
begin
  sTekPapka:=getcurrentdir;//Получаем путь к текущему каталогу
  try
      ADOConnection1.Close;// Закрываем соединение с БД
      //Считываем данные из файла Config.ini.
      //Для этого создаем объект файла Config.ini
      iniF:=TiniFile.Create(sTekPapka+'\Config.ini');
      //Считываем содержимое файла Config.ini и заносим значения в форму
      sServer:=iniF.ReadString('DB', 'Server','');
      sPort:=iniF.ReadString('DB', 'Port','');
      sUser:=iniF.ReadString('DB', User,'');
      sPassword:=iniF.ReadString('DB', 'Password','');
      iniF.free;
      sConnection:='Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="Driver=MySQL ODBC 8.0 Unicode Driver;SERVER='+sServer+';UID=root;password='+sPassword+';DATABASE=shop_products;PORT='+sPort+';charset=cp1251;COLUMN_SIZE_S32=1"';
      ADOConnection1.ConnectionString:=sConnection;
      ADOConnection1.Open; // Открываем соединение
  except
    Application.CreateForm(TfrmPathDB,frmPathDB);
    frmPathDB.ShowModal;
  end;
    //Другие действия при создании формы.
    ......
end;

Давайте посмотрим на этот код. Сначала мы считываем данные с файла Config.ini и заносим их в переменные. После этого мы удаляем объект iniF, так как он нам больше не нужен. Для чего это нужно? Для того, чтобы хранить данные для подключения. Конечно для большей безопасности данные можно не хранить, а постоянно вводить. Но это необходимо не везде, поэтому такой подход тоже имеет место быть.

Затем эти переменные подставляются в выражение sConnection, которое является строкой подключения. После этого мы открываем соединение.

Вся конструкция записана в стеке обработки ошибок try ... except ... end. Поэтому, если соединение не будет установлено, то будет выполнено то, что написано в секции между except и end, а именно будет выведено модальное окно frmPathDB, в котором нужно будет правильно указать параметры подключения. Далее эти параметры в этом же модальном окне можно записать все в тот же Config.ini, чтобы при следующем запуске программы из него уже считались правильные данные, необходимые для подключения.

Таким образом, можно установить подключение к любой базе данных. Только для каждого типа СУБД потребуется своя строка подключения и свой драйвер доступа к данным (Коннектор).

Понравилась статья? Поделиться с друзьями:
Блог Алексея Иванкова
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: