В лекции №2 вставляю модуль данных. При попытке заменить name на fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? |
Соединение с БД клиентской программы. Проблемы русских букв в InterBase
Соединение клиентской программы с базой данных производится с помощью одного из механизмов управления БД. Из стандартной библиотеки компонентов это, как правило, BDE, dbExpress и InterBase Express (IBX). Нередко используют и компоненты сторонних разработчиков, например FIBPlus, но в данном курсе мы не будем рассматривать работу с нестандартными компонентами.
Что касается ADO, тут ситуация несколько сложней. Корпорация Microsoft не очень жалует сторонних разработчиков, особенно популярных, поэтому соединиться с базой данных InterBase через механизм ADO довольно проблематично. Встроенных в Windows средств для этого не существует, а искать и устанавливать драйверы InterBase для ODBC - хлопотно. Поэтому мы не будем рассматривать способы соединения с InterBase через ADO, тем более что для этого существует немало других, гораздо более удобных и прозрачных инструментов.
Вкратце все же заметим, что для нормальной работы с InterBase через ADO нужен ODBC -драйвер Intersolv, который ранее входил в поставку InterBase 5.5, 5.6 или драйвер EasySoft, поставляемый отдельно. Эти драйверы позволяют установить на уровне настроек нужную кодировку, например WIN1251. Отдельно драйвер Intersolv не продается, не поставляется, и более не поддерживается с момента выхода InterBase 6. А вот "устаревший" механизм BDE позволяет соединиться с БД InterBase без всяких проблем. На этой лекции мы вкратце рассмотрим способы связывания приложения с БД через стандартные механизмы.
BDE
В "Технические характеристики. Создание и перенос базы данных" с помощью утилиты SQL Explorer мы создавали псевдоним ( alias ) базы данных FirstIB. Этим псевдонимом мы теперь и воспользуемся. Убедитесь, что он у вас существует, а если нет - зарегистрируйте его, как описано в "Технические характеристики. Создание и перенос базы данных" . Сервер InterBase при этом должен быть включен.
Приступим к созданию приложения. Загрузите Delphi.
С вкладки Data Controls установите на форму сетку DBGrid и навигатор DBNavigator, а также обычную кнопку. Для связи с базой данных нам потребуются компоненты Database, Table и Query с вкладки BDE, а также DataSource с вкладки Data Access для связи таблицы с сеткой и навигатором:
Далее, выделите компонент Database. Здесь нам нужно сделать некоторые настройки:
- В свойстве AliasName выберите наш псевдоним FirstIB.
- В свойстве DatabaseName впишите название базы данных. Оно может быть любым, например, DBase1.
- Свойство LoginPrompt переведите в False, чтобы программа при запуске не запрашивала имя пользователя и пароль.
- Раскройте сложное свойство Params и впишите туда следующие параметры:
Теперь свойство Connected можно перевести в True. Если вы все сделали правильно, то это удастся. Иначе посмотрите, запущен ли у вас сервер InterBase?
Далее, табличный компонент переименуйте в TTovar, а компонент запроса - в Q1 (он нам понадобится для служебных целей). У обоих этих компонентов в свойстве DatabaseName выберите только что созданное имя базы данных DBase1. У таблицы, кроме того, в свойстве TableName выберите TOVAR, а свойство Active переведите в True.
Сетку и навигатор подключите к DataSource1 (через свойство DataSource ), а его, в свою очередь, подключите к таблице TTovar (через свойство DataSet ). У вас в сетке должно появиться содержимое таблицы. Сохраните проект, скомпилируйте и запустите полученную программу.
Теперь попробуйте добавить запись при помощи таблицы, не заполняя поля ID (оно заполняется триггером). У вас выйдет ошибка:
Как видите, утверждение, что триггер BEFORE INSERT срабатывает ПОСЛЕ того, как таблица выполнит метод POST, подтвердилось. Здесь следует сделать одно замечание. Наш триггер вначале делает проверку на значение NOT NULL в ключевом поле. Если в этом поле будет значение, триггер ничего делать не будет. Однако заполнять автоинкрементное поле вручную нельзя, так как мы нарушим работу генератора. Единственное исключение - если мы удалим запись, а затем пожелаем вставить на ее место другую запись с таким же значением в ключевом поле. В этом случае мы будем вставлять запись, не изменяя значения генератора; триггер в этом случае не сработает.
Нажмите OK, а потом выберите команду меню Run -> Program reset, чтобы закрыть повисшее приложение. Итак, мы убедились, что добавлять запись в таблицу с автоинкрементным полем с помощью табличного компонента проблематично. Зато существующие записи можно редактировать или удалять. А для добавления воспользуемся компонентом запроса Query (который для краткости мы переименовали в Q1).
Сгенерируйте обработчик нажатия на кнопку "Добавить запись", которая находится под сеткой. В полученной процедуре впишем следующий код:
procedure TfMain.Button1Click(Sender: TObject); var s: String; tov,stoim: String; begin tov := ''; stoim := ''; //получим данные о товаре: if not InputQuery('Добавление товара', 'Введите новый товар:', tov) then Exit; if not InputQuery('Стоимость товара', 'Введите стоимость товара:', stoim) then Exit; //формируем строку запроса s:= 'Insert Into Tovar(Nazvanie, Stoimost) '+ 'Values (' + QuotedStr(tov) + ',' + stoim + ')'; //вписываем и выполняем запрос: Q1.SQL.Clear; Q1.SQL.Add(s); Q1.ExecSQL; //обновим таблицу: TTovar.Refresh; end;
Для демонстрации работы BDE мы использовали простейший интерфейс, без проверки введенных значений на правильность. Вначале функцией InputQuery мы запрашиваем наименование нового товара, здесь вам придется следить, чтобы вписать не более 20 символов (длина поля Nazvanie ). Затем, вводя стоимость товара, нужно следить за тем, чтобы сумма вводилась в формате
xxx.xxx
То есть, разделителем между целой и дробной частью числа должна быть точка, как того требует синтаксис InterBase. В сетке DBGrid, тем не менее, разделителем будет отображаться запятая. Однако сумма может быть и без дробной части, если товар, например, стоит ровно 10 рублей.
Если пользователь не введет название товара или его стоимость, происходит выход из процедуры.
Получив данные, мы формируем строку запроса, вроде:
Insert Into Tovar(Nazvanie, Stoimost) Values ('Крупа пшенная', 7.35);
После чего присваиваем эту строку свойству SQL компонента Q1. А поскольку запрос выполняемый, то вместо метода Q1.Open мы используем Q1.ExecSQL. После чего нам остается только обновить отображаемый набор данных в таблице TTovar. Теперь новые записи добавляются без проблем, а удаление и редактирование записей можно делать с помощью компонентов DBNavigator и Table.