![]()  | 
| Главная > Программирование > Работа с базами данных > | 
Delphi, C++Builder и базы данных: вопросы и ответы | 
Наталия Елманова
  Компьютер Пресс - CD, 1999, N 8 
  Copyright N.Elmanova & ComputerPress Magazine. 
После публикации в 1997-98 гг. цикла статей, посвященных C++Builder, в адрес редакции поступило много вопросов, связанных с проблемами использования баз данных в приложениях Delphi и C++Builder. Данная статья посвящена ответам на некоторые наиболее часто встречающиеся из них.
В статье "Создание серверов приложений с помощью Delphi 3" вы написали, что подключались к Personal Oracle с помощью BDE. Я очень прошу вас рассказать, как вы это сделали. Для меня пока это остается загадкой.
Доступ к Personаl Oracle (как и к любой другой версии этой СУБД) осуществляется
  следующим образом.
  Сначала нужно запустить сервер (в случае Personal Oracle для Windows 95 это
  отдельное приложение, в случае Oracle для Windows NT - набор сервисов, обслуживающих
  конкретную базу данных) и настроить клиентскую часть Oracle. Для этого следует
  запустить утилиту SQLNet Easy configuration (в случае Oracle 8 - Oracle Net8
  Easy Config) и с ее помощью создать описание псевдонима базы данных Oracle (для
  него, как и в BDE, используется термин alias, но это не то же самое, что псевдоним
  BDE). При создании этого описания важны три параметра. Первый из них - сетевой
  протокол, с помощью которого осуществляется доступ к серверу Oracle (IPX/SPX,
  TCP/IP и др.). Второй параметр - местоположение сервера в сети. В случае Personal
  Oracle это обычно компьютер с IP-адресом 127.0.0.1 (это специальный адрес для
  доступа к локальному компьютеру, так называемый TCP loopback address). Третий
  параметр - имя базы данных. По умолчанию в случае Personal Oracle она называется
  ORCL. В общем случае имя может быть любым, но это должно быть имя уже существующей
  базы данных, с которой вы собираетесь работать. В принципе все описания псевдонимов
  Oracle хранятся в текстовом файле TNSNAMES.ORA, и можно редактировать его вручную.
  
  Далее следует запустить утилиту SQL Plus и проверить соединение клиента с сервером.
  Обычно в качестве имени пользователя используется имя SYSTEM и пароль MANAGER
  (если вы сами администрируете сервер). Если же сервер был установлен раньше,
  есть смысл узнать у администратора базы данных, каким именем и паролем следует
  воспользоваться. Помимо имени пользователя и пароля, SQL Plus запросит так называемую
  строку связи, в которой должно содержаться имя сервиса, который был создан вами
  перед этим. При удачном соединении в SQL Plus появится соответствующее сообщение.
  Отметим, что утилита Oracle Net8 Easy Config позволяет протестировать соединение
  непосредственно в процессе создания описания сервиса. Если соединение с сервером
  было неудачным, стоит проверить, поддерживается ли указанный сетевой протокол
  и виден ли в сети компьютер, на котором установлен сервер, и, если нужно, внести
  изменения в описание сервиса.
  Далее можно, наконец, заняться настройкой BDE. В качестве Server Name следует
  указать имя псевдонима Oracle (его можно просто выбрать из выпадающего списка,
  так как BDE Administrator также обращается к файлу TNSNAMES.ORA). После этого
  нужно проверить соединение с сервером через BDE с помощью BDE Administrator
  или SQL Explorer.
  Если соединение не устанавливается и появляется сообщение "Vendor initialization
  failed", стоит убедиться, что динамическая загружаемая библиотека, указанная
  в параметре Vendor Init драйвера Oracle, действительно присутствует на данном
  компьютере. На всякий случай стоит скопировать ее в Windows\System, так как
  некоторые ранние версии BDE в Windows 95 не находят эту библиотеку в подкаталоге
  Bin каталога, в котором установлен клиент Oracle, в силу ограничений, налагаемых
  этой операционной системой на длину переменной окружения PATH. Отметим также,
  что при использовании Oracle 8 следует использовать версию не ниже 8.0.4; в
  случае использования более ранней версии следует обновить ее до 8.0.4.
Недавно я перешел на использование Oracle, и все мои попытки использовать компонент TStoredProc кончаются неудачей. Почему?
Причины неработоспособности компонента TStoredProc могут быть следующими. Во-первых,
  при использовании ODBC-доступа может оказаться, что применяемый вами ODBC-драйвер
  не поддерживает хранимые процедуры (как известно, не все ODBC-драйверы их поддерживают).
  
  И во-вторых, имеется известная проблема, описание которой содержится в разделе
  Developers support корпоративного сайта Inprise. Дело в том, что число параметров
  хранимой процедуры, с которой взаимодействует компонент TStoredProc, не должно
  превышать 10. В случае, если реальное число параметров превышает 10, многие
  разработчики переписывают хранимые процедуры так, чтобы они использовали строковые
  параметры, содержащие по несколько реальных параметров.
Есть ли возможность в Delphi как-то корректно прервать выполнение SQL запроса к серверу Oracle с помощью BDE? Например, при использованиис SQL Plus после отправки на выполнение SQL-запроса на экране появляется окно с кнопкой Cancel, благодаря чему мы имеем возможность в любой момент прервать выполнение этого запроса. Можно ли что-то подобное сделать в Delphi?
Насколько мне известно, для этой цели лучше всего использовать функции Oracle
  Call Interface (низкоуровневый API Oracle). В комплекте поставки Oracle есть
  соответствующие примеры для C, и переписать их на Pascal несложно.
  Некоторые драйверы SQL Link позволяют прекратить выполнение запроса, если время
  его выполнения превышает заранее заданное значение (параметр MAX QUERY TIME
  соответствующего драйвера). Однако драйвер ORACLE, к сожалению, не входит в
  их число.
Что необходимо предпринять, чтобы сгенерировать из ERwin таблицы для локальной базы данных Paradox 5.0? На компьютере установлены Delphi 4.0 и MetaBase.
Для этого требуется установить ODBC-драйвер для этой версии Paradox той же разрядности, что и ERwin. Затем нужно описать соответствующий ODBC-источник, и он будет доступен в ERwin.
Не могли бы Вы мне подсказать, как заблокировать функцию вставки записи непосредственно в компоненте TDBGrid с сохранением всех остальных возможностей редактирования таблицы.
Наиболее разумным представляется создать обработчик события BeforeInsert компонента TTable, TQuery или TClientDataSet, данные из которых отображаются в TDBGrid. Сам компонент TDBGrid не имеет подходящего события для обработки, так как это компонент, предназначенный только для создания пользовательского интерфейса, а в данном случае следует, по существу, запретить добавление записей в таблицу.
У меня в комплект Borland C++ Builder не входит Visual Query Builder. Могу ли я связать две таблицы без него?
Безусловно, можно связать две таблицы и без VQB. Самый простой способ - запустить
  Database Form Wizard и связать две таблицы, используя TQuery. Те два запроса,
  которые при этом получатся (один из них - параметризованный), можно использовать
  как образец.
  Кроме того, можно просто написать вручную необходимый запрос к любому числу
  таблиц и поместить его в свойство SQL компонента TQuery. Все инструменты для
  генерации запросов (Visual Query Builder, SQL Builder и др.) просто предоставляют
  для этого визуальные средства, а результатом их работы является именно текст
  запроса, помещаемый в это свойство.
Я установил Borland C++ Builder 3.0 Client/Server Suite и InterBase Server 5.1.1. (автоматически с ним установился InterBase 5.x Driver by Visigenic). Но у меня не работают хранимые процедуры. То есть процедура правильно откомпилирована, и вызов ее из C++ Builder осуществляется с помощью выполнения оператора
StoredProc1->ExecProc();
При этом возникает следующая ошибка : "Capability not supported. General SQL error. [Visigenic][ODBC InterBase 4.x Driver] Driver not capable".
ODBC-драйвер может не поддерживать хранимые процедуры. В этом случае стоит
  попытаться использовать драйвер SQL Link (он должен быть в C++ Builder 3.0 Client/Server
  Suite). Для этого нужно создать для вашей базы данных псевдоним типа INTRBASE.
  В этом случае хранимые процедуры должны работать.
  Если хранимые процедуры тем не менее остаются недоступными, стоит проверить,
  что и в какой последовательности было установлено на ваш компьютер. Такие неприятности
  могут быть, если, например, вы установили какой-либо продукт, написанный на
  Delphi 2, после C++Builder 3. В этом случае можно переустановить BDE, взяв его
  последнюю версию на сайте Inprise- все зарегистрированные пользователи C++ Builder
  3.0 Client/Server Suite имеют право это сделать.
При удалении записей из таблицы dBase с помощью компонента TTable они просто приобретают признак удаления, и я никак не могу добиться их физического удаления. Как быть?
Ваша проблема решается просто - для физического удаления записей нужно использовать функцию DbiPackTable (ее описание есть в справочном файле BDE).
При добавлении новых записей с помощью TTable.AppendRecord в индексированную таблицу FoxPro через какое-то время (то есть при добавлении сразу большого количества записей) возникает ошибка: "Access to table disabled because of previous error. Read failure. File" <имя_файла.cdx>..
Возможно, причина заключается в том, что операции чтения-записи в файл, содержащий
  таблицу FoxPro, особенно при использовании кэширования, предоставляемого операционной
  системой, конфликтуют с содержимым индексного файла (это часто происходит при
  многопользовательской работе). Дело в том, что ранние версии dBase, FoxPro,
  Clipper работали с неподдерживаемыми индексами, то есть индексные файлы не обновлялись
  одновременно с таблицей, и для их синхронизации требовалось выполнять специальные
  операции. Но соответствующие средства разработки, применяемые в то время, обычно
  не поддерживали никаких аналогов транзакций - записи обычно вставлялись по одной.
  
  В случае применения старых версий формата FoxPro следует избегать кэширования
  при выполнении дисковых операций с файловым сервером, содержащим базу данных
  FoxPro. Кроме того, следует проверить и, если необходимо, изменить в настройках
  BDE параметры MINBUFSIZE, MAXBUFSIZE, LOCAL SHARE - возможно, проблема заключается
  в недостаточной величине буферов BDE для кэширования данных или в одновременном
  доступе к данным приложений, использующих и не использующих BDE. 
  Еще одним из способов решения этой проблемы (самым радикальным) является замена
  FoxPro на какую-нибудь из серверных СУБД. Например, IB Database неплохо справляется
  с одновременным вводом большого количества записей благодаря некоторым специфическим
  особенностям архитектуры этого сервера.
Позволяет ли QuickReport выгружать данные в формате Microsoft Excel?
 Quick Report не позволяет выгружать данные в формате Microsoft Excel. Но последние
  его версии позволяют сохранять отчеты в формате CSV (Comma Separated Value)
  и HTML, и оба эти формата можно прочесть с помощью Excel. 
  Помимо этого, для генерации отчета можно использовать автоматизацию Excel, вообще
  не прибегая к использованию QuickReport.
Как можно создать свою форму просмотра отчетов QuickReport в С++Builder?
Для создания собственных окон просмотра отчета можно использовать компонент TQRPreview. Для этой цели следует создать форму (назовем ее PreviewForm), поместить на нее компонент TQRPreview, сослаться на нее в форме, содержащей отчет, и в форме, из которой вызывается просмотр отчета. Код для показа отчета выгладит примерно так:
 void __fastcall TForm1::Button1Click(TObject *Sender)
{
      PreviewForm->Show();
      QuickReport1->Preview();
}
Далее создадим обработчик события OnPreview компонента TQuickRep:
 void __fastcall TQuickReport1::QuickReport1Preview(TObject *Sender)
{
      PreviewForm->QRPreview1->QRPrinter  = QuickReport1->QRPrinter;
}
После этого данный отчет будет появляться не в стандартном окне просмотра, а в форме PreviewForm.
Возможно ли использование компонентов Decision Support System при генерации отчетов в QuickReport и, если можно , то каким образом? Если QuickReport не подходит для этих целей, то какие другие варианты Вы можете посоветовать?
Самый простой способ - использовать компоненты TQRLabel, текст в которых динамически меняется во время печати (то есть способ, которым можно напечатать все, что угодно, написав при этом немного кода). В принципе можно двумерное сечение куба записать во временную таблицу или в компонент TClientDataSet, написав соответствующий цикл, и сделать отчет на ее основе. Использование DecisionQuery в качестве источника данных для отчета также вполне возможно. Другие возможные варианты - это использование автоматизации Word или Excel, либо вычисление сумм внутри отчета. Можно также использовать другие генераторы отчетов - например, с помощью Crystal Reports можно создавать отчеты, содержащие кросс-таблицы.
Как корректно подключить Crystal Reports к Delphi ?
В составе Crystal Reports Professional имеется VCL-компонент для Delphi, элемент управления ActiveX, модуль CRPE32.PAS, котором объявлены все функции и структуры Print Engine API, и описание опубликованных методов Crystal Reports как сервера автоматизации. Соответственно есть следующие возможности подключения Crystal Reports к Delphi:
1. Использование функций Report Engine API из библиотеки CRPE32 DLL. В этом случае следует добавить в проект модуль CRPE32.PAS и сослаться на этот модуль в предложении uses. Ниже приведен пример соответствующего кода:
 procedure TForm1.Button1Click(Sender: TObject);
VAR RepNam:PChar;
begin
if   OpenDialog1.Execute then
begin
If PEOpenEngine then
     begin RepNam := StrAlloc(80);
        StrPCopy(RepNam, OpenDialog1.Filename);
        JN := PEOpenPrintJob(RepNam);
          if JN   = 0 then
               ShowMessage('Ошибка открытия отчета');
            StrDispose(RepNam);
            end
         else
             ShowMessage('Ошибка открытия отчета');
end;
 end;
procedure TForm1.Button2Click(Sender:  TObject);
begin
PEClosePrintJob(JN);
PECloseEngine;
Close;
end;
procedure TForm1.Button3Click(Sender:   TObject);
begin
PEOutputToWindow(jn,'Пример использования Crystal Reports Print
Engine',30,30,600,400,0,0) ;
     if PEStartPrintJob(JN, True) = False then
          ShowMessage('Ошибка   вывода отчета');
end;
end.
Следует помнить, что строковые параметры, передаваемые в функции Print Engine API, представляют собой тип данных PChar, а не стандартные строки, используемые в Pascal, поэтому для передачи таких параметров, как, например, имя отчета, следует осуществить преобразование типов с помощью функции StrPCopy. Для успешной компиляции подобных приложений файл CRPE32.PAS должен находиться в том же каталоге, что и разрабатываемое приложение, либо в каталоге Delphi\Lib.
2. Использование VCL-компонента и комплекта поставки (для этого следует установить его в палитру компонентов Delphi). Естественно, этот компонент инкапсулирует те же самые функции Print Engine API. Существуют также аналогичные компоненты третьих фирм (например, компонент от SupraSoft Ltd., http://www.suprasoft.com).
3. Использование элемента управления Crystal Reports ActiveX. Этот элемент управления может быть установлен в палитру компонентов Delphi. Он обладает набором свойств и методов, более или менее сходным с соответствующим VCL-компонентом из комплекта поставки Crystal Reports Professional.
5. Использование Crystal Reports как сервера автоматизации. В справочной системе Crystal Reports имеется подробное описание иерархии вложенных объектов и их методов (и внушительный набор примеров для Visual Basic, аналоги которых несложно создать и на Pascal). Ниже приведен пример соответствующего кода:
procedure TForm1.Button1Click(Sender: TObject);
var r,rep: Variant;
begin
     rep:=CreateOleObject('Crystal.CRPE.Application');
     r:=rep.OpenReport('d:\Report2.rpt');
     r.RecordSelectionFormula := '{items.ItemNo} = '+Edit1.Text;
     r.Preview;
     r:=Unassigned;
     rep:=Unassigned;
end; 
6. Можно также сделать отчет в виде исполняемого файла и вызвать его из приложения. Но в этом случае в отчет не удастся передать параметры.
Координаты автора:
  http://www.geocities.com/SiliconValley/Way/9281
| Вернуться в раздел "Работа с базами данных" - Обсудить эту статью на Форуме | 
| Главная - Поиск по сайту - О проекте - Форум - Обратная связь |