BDE
НапредыдущихзанятияхспомощьюутилитыSQLExplorerмысоздавалипсевдоним(alias)базыданныхFirstIB.Этимпсевдонимоммытеперьивоспользуемся.Убедитесь,чтоонувассуществует,аеслинет-зарегистрируйтеего.СерверInterBaseприэтомдолженбытьвключен.
Приступимксозданиюприложения.ЗагрузитеDelphi.
СвкладкиDataControlsустановитенаформусеткуDBGridинавигаторDBNavigator,атакжеобычнуюкнопку.ДлясвязисбазойданныхнампотребуютсякомпонентыDatabase,TableиQueryсвкладкиBDE,атакжеDataSourceсвкладкиDataAccessдлясвязитаблицыссеткойинавигатором:
Рис.5.1.Формаприложения
Далее,выделитекомпонентDatabase.Здесьнамнужносделатьнекоторыенастройки:
- ВсвойствеAliasNameвыберитенашпсевдонимFirstIB.
- ВсвойствеDatabaseNameвпишитеназваниебазыданных.Ономожетбытьлюбым,например,DBase1.
- СвойствоLoginPromptпереведитевFalse,чтобыпрограммапризапускенезапрашивалаимяпользователяипароль.
- РаскройтесложноесвойствоParamsивпишитетудаследующиепараметры:
Рис.5.2.РедактированиесвойстваParams
ТеперьсвойствоConnectedможноперевестивTrue.Есливывсесделалиправильно,тоэтоудастся.Иначепосмотрите,запущенлиувассерверInterBase?
Далее,табличныйкомпонентпереименуйтевTTovar,акомпонентзапроса-вQ1(оннампонадобитсядляслужебныхцелей).УобоихэтихкомпонентоввсвойствеDatabaseNameвыберитетолькочтосозданноеимябазыданныхDBase1.Утаблицы,крометого,всвойствеTableNameвыберитеTOVAR,асвойствоActiveпереведитевTrue.
СеткуинавигаторподключитекDataSource1(черезсвойствоDataSource),аего,всвоюочередь,подключитектаблицеTTovar(черезсвойствоDataSet).Увасвсеткедолжнопоявитьсясодержимоетаблицы.Сохранитепроект,скомпилируйтеизапуститеполученнуюпрограмму.
Теперьпопробуйтедобавитьзаписьприпомощитаблицы,незаполняяполяID(онозаполняетсятриггером).Увасвыйдетошибка:
Рис.5.3.Ошибкаизмененияданныхтаблицы
Каквидите,утверждение,чтотриггерBEFOREINSERTсрабатываетПОСЛЕтого,кактаблицавыполнитметодPOST,подтвердилось.Здесьследуетсделатьоднозамечание.НаштриггервначаледелаетпроверкуназначениеNOTNULLвключевомполе.Есливэтомполебудетзначение,триггерничегоделатьнебудет.Однакозаполнятьавтоинкрементноеполевручнуюнельзя,таккакмынарушимработугенератора.Единственноеисключение-еслимыудалимзапись,азатемпожелаемвставитьнаееместодругуюзаписьстакимжезначениемвключевомполе.Вэтомслучаемыбудемвставлятьзапись,неизменяязначениягенератора;триггервэтомслучаенесработает.
НажмитеOK,апотомвыберитекомандуменюRun->Programreset,чтобызакрытьповисшееприложение.Итак,мыубедились,чтодобавлятьзаписьвтаблицусавтоинкрементнымполемспомощьютабличногокомпонентапроблематично.Затосуществующиезаписиможноредактироватьилиудалять.АдлядобавлениявоспользуемсякомпонентомзапросаQuery(которыйдлякраткостимыпереименоваливQ1).
Сгенерируйтеобработчикнажатиянакнопку"Добавитьзапись",котораянаходитсяподсеткой.Вполученнойпроцедуревпишемследующийкод:
procedureTfMain.Button1Click(Sender:TObject);
var
s:String;
tov,stoim:String;
begin
tov:='';
stoim:='';
//получимданныеотоваре:
ifnotInputQuery('Добавлениетовара',
'Введитеновыйтовар:',tov)thenExit;
ifnotInputQuery('Стоимостьтовара',
'Введитестоимостьтовара:',stoim)thenExit;
//формируемстрокузапроса
s:='InsertIntoTovar(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рублей.
Еслипользовательневведетназваниетовараилиегостоимость,происходитвыходизпроцедуры.
Получивданные,мыформируемстрокузапроса,вроде:
InsertIntoTovar(Nazvanie,Stoimost)Values('Крупапшенная',7.35);
ПослечегоприсваиваемэтустрокусвойствуSQLкомпонентаQ1.Апосколькузапросвыполняемый,товместометодаQ1.OpenмыиспользуемQ1.ExecSQL.ПослечегонамостаетсятолькообновитьотображаемыйнаборданныхвтаблицеTTovar.Теперьновыезаписидобавляютсябезпроблем,аудалениеиредактированиезаписейможноделатьспомощьюкомпонентовDBNavigatorиTable.
ПроблемырусскихбукввInterBase
Вообщето,этипроблемыкасаютсянетолькорусских,авообщелюбыхбукв,отличныхотанглийскогоалфавита.Здесьнужносделатьнесколькозамечаний:
- Наименованияидентификаторов(названий)таблиц,полей,индексовипроч.вInterBaseнедопустимодаватьрусскимибуквами.
- ПрисозданиибазыданныхнезабывайтеуказыватькодировкуWIN1251,каккодировкупоумолчанию.
- ЕсливыподключаетексерверучерезIBConsoleужесуществующуюбазуданных,такженезабывайтеуказыватьэтукодировку.
- ЕсливыподключаетеклиентскоеприложениекБДчерезBDE,достаточносоздатьпсевдонимБД,вкоторомвкачествеязыковогодрайверауказатьParadoxANSICyrillic,какэтомыделалираньше.
- ПриподключенииприложениякБДспомощьюмеханизмов"прямогодоступа",такихкакIBX,FIBPlusит.п.,вспискепараметровнужноуказатьдополнительныйпараметркодировки"lc_ctype=WIN1251",безэтоговысможетепросматриватьтаблицысрусскимтекстомвполях,нонесможетедобавлятьновыхзаписей,сделанныхкириллицей.
- ВInterBaseимеетсявстроеннаяфункцияUPPER,котораяпреобразуетсимволыстроковыхполейвзаглавныебуквы.Этувозможностьнередкоиспользуютдляпоискаданных.Однакоприработескириллицейонабудетработатькорректнолишьвтомслучае,еслистроковоеполебылосозданоскодировкойWIN1251ипорядкомсортировкиPXW_CYRL.Вслучаедругихсочетанийпараметров,функциянесможетправильноотображатьрусскийтекстзаглавнымибуквами.Например,отобразитьтекстполяNazvanieизтаблицыTovarзаглавнымибуквамиможноследующимзапросом:"SELECTUPPER(Nazvanie),StoimostFROMTovar"
- ЕсливсежевысоздалиполескодировкойWIN1251,нонеуказалисортировкуPXW_CYRL,авамтребуетсявыполнитьпоисксфункциейUPPER,товыможетесменитьпорядоксортировкиявно,прямовзапросе.Например,требуетсянайтизаписьсозначением"Сахар"вполеNazvanie.Приэтоммынезнаем,какпользовательвписалэтоназвание:"САХАР","Сахар"или"сахар".Сделатьпоиск,независящийотрегистраможнозапросом:"SELECT*FROMTovarWHEREUPPER(NazvanieCOLLATEPXW_CYRL)='САХАР'"
dbExpress
ТехнологияdbExpressреализуеттакназываемыйоднонаправленныйкурсор,тоесть,данныеможнобудетлистатьтолькосверху-вниз.Этосущественноускоряетработусбазойданных,новбольшинствеслучаевделаеттехнологиюнеудобнойдляклиентскихприложений.Правда,начинаясшестойверсииDelphi,вdbExpressпоявилсякомпонентTSimpleDataSet,которыйсоздаетдвунаправленныйкурсориснимаетбольшинствоограничений.Втожевремя,программалишаетсяпреимуществаскоростиоднонаправленногокурсора.Всеэтоприводитктому,чтотехнологиюdbExpressнапрактикеиспользуюткрайнередко.Темнеменее,рассмотримподключениепрограммыкбазеданныхспомощьюэтойтехнологии.
Создайтеновоеприложениеиспроектируйтеформутакойже,каквпредыдущемпримере,нобезкомпонентовBDE.Изкомпонентовдоступа,помимоDBNavigatorиDBGridнампонадобятся:DataSourceсвкладкиDataAccess;компонентыSQLConnection,SimpleDataSetиSQLQueryсвкладкиdbExpress.
SQLConnectionпредназначендляподключениякбазеданных,онявляетсяаналогомкомпонентаTDatabaseвBDE.Остальныекомпонентыподключаютсякбазечерезнего.
SimpleDataSetбудетигратьрольтаблицысдвунаправленнымкурсором,аSQLQueryпредставляетсобойобычныйкомпонентзапросов.
ВыделитекомпонентSQLConnection.ВегосвойствеConnectionNameвыберитеизспискавариантовподключенияIBConnection,приэтомавтоматическинастроятсянекоторыесвойства,специфичныедляInterBase.ДалеещелкнитепосложномусвойствуParams-загрузитсяокнопараметров,котороенужнонастроитьтак:
Рис.5.4.ОкнопараметровSQLConnection
ЗдесьнамнужнобудетвручнуювписатьадресиимяфайласбазойданныхвпараметрDatabase.ЗатемуказатьпараметрыServerCharSet(WIN1251)иSQLDialect(3).ПослечегокнопкойОКзакрытьокно.ДалееперевестисвойствоLoginPromptвFalse,чтобыпрограмманезапрашивалаимяипарольпользователя,асвойствоConnectedвTrue,чтобысоединитьсясбазойданных.
ВыделимкомпонентSimpleDataSet.ПереименуйтеегосвойствоNameвTTovar(мывыбралитакоежеимя,какутаблицыизпрошлогопримера,чтобынеменятькоднажатиянакнопку).ВсвойствеConnectionвыберитеSQLConnection1.РаскройтесложноесвойствоDataSet,иоткройтеподсвойствоCommandText.Откроетсяокноредактора,вкоторомнужнобудетсоставитьзапросвыборкивсехданныхизтаблицыTovar:
SELECT*FROMTOVAR:
Рис.5.5.Окноредакторазапросов
ЗатемкнопкойОКзакройтеокно,иможетезакрытьсложноесвойствоDataSet.АвотсвойствоActiveпереведитевTrue,чтобыоткрытьполученныйнаборданных.
ТеперьзаймемсякомпонентомSQLQuery1.СвойствоNameпереименуйтевQ1,всвойствеSQLConnectionвыберитеSQLConnection1.
НапоследоксоединитеDataSource1скомпонентомTTovar,асеткуинавигатор-сDataSource1.Данныеизтаблицыдолжныотобразитьсявсетке.
Коддлякнопкитакойже,каквпредыдущемпримере.Сохранитепроект,скомпилируйтеипопробуйтедобавитьпарунаименованийтовара.Каквидите,реализацияподключениянесколькосложней,чемвпредыдущемпримере,нозатонаклиентскийПКненужноустанавливатьBDE!
InterBaseExpress(IBX)
Этатехнологияявляется"родной"длясервераInterBase,иизстандартныхмеханизмовдоступанаиболееудобна.Азначит,чащевсегоиспользуютименноее.Вбудущихлекцияхмыпоработаемсэтиммеханизмомплотнее,апокавкратцерассмотримработуснимнапримеревсетогожеприложения.
Создайтеновоеприложение,иразместитенаформесеткуDBGrid,навигаторDBNavigatorикнопкутакже,каквпрошлыхпримерах.
НасеткупоместитеодинкомпонентDataSourceсвкладкиDataAccess,исвкладкиInterBaseследующиекомпоненты:IBDatabase,IBTransaction,IBTableиIBQuery.
КомпонентIBDatabaseвыполняетподключениекбазеданных,всеостальныекомпонентывкладкисоединяютсясБДчерезнего.
Вседействиясбазойданныхпроисходятнауровнетранзакций,компонентIBTransactionкакразобеспечиваеттакуютранзакцию.ВприложенииобязательнодолженбытьхотябыодинIBTransaction,соединенныйсIBDatabase.Всложныхмногозвенныхбазахданныхтакихтранзакцийможетбытьнесколько.Вообще,имеетсявозможностьдлякаждогонабораданных(IBTableилиIBQuery)использоватьсобственныйкомпонентIBTransactionсразличныминастройками.Однакоделатьтакнерекомендуется.Обычнонаборыданныхразделяютнагруппы,например,НДтолькодлячтения,НДтолькодлязаписи,НДдлячтения/записисмягкимиилижесткимиусловиямисоединения(обэтомвследующихлекциях).ВэтомслучаедлякаждойгруппынаборовданныхвыделяютсвойкомпонентIBTransaction.
КомпонентыIBTableиIBQueryпочтиничемнеотличаютсяотпростыхTableиQuery.