Quick Guide: dbExpress

Ответы на часто задаваемые вопросы

Алексей Макаренко
Олег Перехрест
27 апреля 2004г

Q. Что нового в технологии dbExpress в связи с выходом Delphi7

A. Обновлены драйвера dbExpress для Informix SE, Oracle 9i, DB2 7.2, InterBase 6.5, MySQL 3.23.49 и для MS SQL Server 2000. А вот SQL Links Borland не рекомендует использовать, более того - работа над усовершенствованием SQL Links прекращается. Сообщается также, что эта технология не будет поставляться вместе с Delphi после 2002 года. В виде замены рекомендовано использовать dbExpress для доступа к базам данных SQL серверов. Прекращена также поддержка CORBA-соединений компонентами DataSnap.
Закладка dbExpress включает новый компонент TSimpleDataSet для использования с простыми, двухуровневыми приложениями баз данных (TSimpleDataSet заменил собой TSQLClientDataSet).
 

Q. Какие преимущества технологии dbExpress

A. Данная технология обладает следующими важными преимуществами:

Q. Какие отличия dbExpress от остальных механизмов доступа к данным, и в первую очередь от BDE

A.

Q. Что такое однонаправленный набор данных

A. Суть однонаправленных наборов данных заключается в том, что они не буферизируют данные при навигации или модификации. В отличии от используемых в BDE двунаправленных наборов данных с буферизацией в оперативной памяти, однонаправленные наборы отличаются большей эффективностью, но обладают и некоторыми ограничениями:

Q. Что такое provider/resolver

A. Это механизм, который отвечает за выдачу данных по запросу пользователя и проведение изменений в базе данных. Данный механизм состоит из двух частей:

Q. Какие преимущества использования механизма provider/resolver

A.

Q. Соответствие компонентов доступа к базам данных, различных технологий

A. 

InterBase Express  ADO  BDE  dbExpress  Комментарий 
TIBDatabase TADOConnection TDatabase TSQLConnection Установление соединения с БД.
TIBTable TADOTable TTable TSQLTable Однонаправленный не редактируемый набор данных.
TIBQuery TADOQuery TQuery TSQLQuery Однонаправленный не редактируемый набор данных.
TIBStoredProc TADOStoredProc TStoredProc TSQLStoredProc Однонаправленный не редактируемый набор данных.
TIBDataSet TADODataSet нет аналога TSQLDataSet TSQLDataSet объединяет в себе возможности компонентов SQLTable, SQLQuery и SQLStoredProcedure.
TIBSQLMonitor нет аналога утилита SQL Monitor TSQLMonitor Отслеживает все инструкции SQL, проходящие между компонентом SQLConnection и сервером базы данных, к которому он подключен.
нет аналога нет аналога TBDEClientDataSet TSimpleDataSet Используется при разработке 2-ух уровневых приложений. Является комбинацией SQLDataSet, DataSetProvider, ClientDataSet и позволяет читать и редактировать данные.
нет аналога нет аналога TBatchMove нет аналога При необходимости, придется повторить данную функциональность.
&hbsp;   TSession нет аналога Механизм TSession в технологии dbExpress не нужен.
    TUpdateSQL нет аналога Возможности TClientDataSet заменяют механизм CachedUpdates.
    TNestedDataSet нет аналога Возможность обработки вложенных наборов данных встроена в TDataSetProvider и TClientDataSet. 

Q. Что такое Borland MyBase

A. Данные содержащиеся в ClientDataSet могут быть сохранены или загружены как дисковый файл в двоичном, либо в XML формате. Это позволяет ClientDataSet функционировать как однопользовательская система реляционной базы данных. Данную возможность можно использовать следующим образом:

Недостатки:

Q. Где можно найти альтернативные драйвера для dbExpress

A.

dbExpress driver name  Platforms supported  Database supported  Download URL 
MySQL dbExpress  N/A  MySQL 3.22.x 

http://sourceforge.net/projects/freeclx/ 

DbxSQLite  N/A  SQLite 2.8.0  www.sqlite.org
www.bcp-software.nl
 
dbExpress Pervasive 2000i SQL  Windows  Pervasive 2000i SQL  marcin@festus.com.pl 
pgExpress Driver  Windows/Linux  PostgreSQL  http://www.vitavoom.com 
dbExpress for Client Access/400, dbexpca400.dll  Windows 9x/NT/2k with Client Access installed  DB2/400 (AS/400 databases)  http://www.sawatzki.de
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=15909
 
SQLTHINK.DLL / libsqlthink.so.0  Windows, Linux  ThinkSQL RDBMS  http://www.thinksql.co.uk 
dbExpress for ADO  Windows 9x/NT/2K with MDAC  Anything with an OLEDB provider  http://islamov.com/dbexpress/ 
dbExpress for ODBC  Windows 9x/NT/2K with ODBC  Anything with an ODBC driver  http://islamov.com/dbexpress/ 
dbExpress for MS SQL  Windows 9x/NT/2K with DB-LIB  MS SQL Server 7/2K  http://islamov.com/dbexpress/ 
dbxoodbc - Open Source DbExpress driver for ODBC  Microsoft Windows. May work on Linux, but untested  Any ODBC compliant database

  

http://sourceforge.net/projects/open-dbexpress/

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/open-dbexpress/dbxoodbc/ 

dbExpress for Informix  Windows 9x/NT/2K, Linux  Informix 7,9  http://www.luxena.com/download.htm 
Easysoft dbExpress-ODBC Gateway  Microsoft Windows. Linux.  Any ODBC compliant database.  http://www.easysoft.com/products/9999/platforms.phtml?product=2202 
dbExpress Driver for Sybase  Windows 9x/NT/2K  Sybase ver.: 11, 12.0, 12.5  http://www.visoco.com/download/ 
dbExpress Driver for Oracle  Windows 9x/NT/2K/Linux  Oracle 9i, Oracle 8i, Oracle 8 and Oracle 7  http://www.crlab.com/dbexp.html 
dbExpress for MS SQL Server  Windows 9x/NT/2K  MS SQL Server 2000 and MS SQL Server 7  http://www.crlab.com/download.html#dbx 
dbExpress Informix IDS 9.2 driver  Windows 9x/NT/2K  Informix IDS 9.2  http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=17693 

Иногда имеет смысл исправлять ошибки и в midas: http://www.distribucon.com/midasbug/

Midas.dll Memory Manager Patch Version 2.04: http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20524

Q. В некоторых примерах, имеются упоминания о компоненте TSQLClientDataSet, но Delphi7 и Help его не находят

A. В Delphi7 данный компонент, не рекомендуется к использованию, он заменен на TSimpleDataSet. Для поддержки старых приложений, исходники компонента TSQLClientDataSet размещены в каталоге "...\Demos\Db\SQLClientDataset".
 

Q. Для чего нужен компонент TSimpleDataSet

A. Данный компонент появился в Delphi7, как замена TSQLClientDataSet. Он комбинирует в себе TSQLDataSet, TDataSetProvider и TClientDataSet и является простой заменой TQuery при переходу с BDE на dbExpress. Также экономится время в процессе разработки, так как вместо трех компонент используется один. Однако данный компонент имеет недостатки:

Q. Как обойти недостатки компонента TSimpleDataSet

A. Необходимо разместить компоненты TSQLQuery, TDataSetProvider и TClientDataSet на форму или модуль данных. Установить свойство DataSetProvider.DataSet на SQLQuery, ProviderName на ClientDataSet. Выбрать все три компонента, и в главном меню среды выбрать - Component | Create Component Template. Указать имя класса, компонента и палитры для нового шаблона. Теперь можно использовать три компонента так же легко как один компонент TSimpleDataSet.
 

Q. Почему появились новые типы данных TFMTBCDField и TSQLTimeStampField

A. 

TFMTBCDField - в этот объект помещаются все числовые значения, которые не вмещаются в double precision. Внутри данные хранятся, в переменной типа TBCD, являющийся настоящим числом BCD с максимальной точность 32 цифры. Для выполнения математических операций на данным типом столбца, используется свойство asVariant.

TSQLTimeStampField - используется для хранения даты и времени. Внутри данные хранятся, в переменной типа TSQLTimeStamp (это запись с отдельными полями для года, месяца, дня, часов, минут, секунд и миллисекунд), что предотвращает потерю точности. TSQLTimeStampField имеет методы as.... для конвертации даты и времени в другие типы данных.

Q. Как управлять транзакциями

A. Класс TSQLConnection имеют методы StartTransaction, Commit, Rollback и позволяет работать с несколькими транзакциями, активными в один и тот же момент. Для поддержки такого режима методы StartTransaction, Commit и Rollback принимают параметр TTransactionDesc, объявленный следующим образом:

    TTransactionDesc = packed record
        TransactionID : longword;
        GlobalID : longword;
        IsolationLevel : TTransactionIsolationLevel;
        CustomIsolation: longword;
    end;

Для каждой отдельной транзакции необходим объявить переменную типа TTransactionDesc и установить TransactionId в число, которое должно быть уникально между всеми активными транзакциями. Поле GlobalId используется только в Oracle для распределенных транзакций. IsolationLevel может быть xilDirtyRead, xilReadCommitted или xilRepeatableRead. Поле CustomIsolation пока не поддерживается.

Пример:

var
  T: TTransactionDesc;
begin
  T.TransactionID := 1;
  T.IsolationLevel := xilREADCOMMITTED;
  SQLConnection.StartTransaction(T);
end;

Для обеспечения одного из главных достоинств dbExpress - короткое время жизни транзакции, необходимо придерживаться следующей схемы:

Q. Как управлять загрузкой параметров подключения во время выполнения приложения

A. Для загрузки значений параметров подключения во время выполнения приложения необходимо присвоить значение True свойству LoadParamsOnConnect. При загрузке приложения компонент класса TSQLConnection определяет размещение файла dbxconnections.ini на основании содержимого ключа системного реестра Connection Registry File в ветви HKEY_CURRENT_USER\Software\Borland\DBExpress. Изменение значения этого ключа можно сделать в момент установки приложения, а также не забыть включить в поставку сам файл dbxconnections.ini.
 

Q. Как отсортировать записи в TSQLDataSet

A. Для типа команды:

Q. Как выполнять команды DDL и DML

A. Для выполнения команд DDL и DML, в TSQLConnection имеется два метода:

При многократном исполнении одних и тех же SQL команд, их следует параметризировать. Для облегчения заключения текстовых значений в кавычки, следует использовать функцию QuotedStr.

Пример:

SQLDataSet1 := TSQLDataSet.Create(nil);
try
  SQLConnection1.Execute('select * from filials', nil, SQLDataSet1);
  ...
finally
  SQLDataSet1.Free;
end;
 

Q. Как создать базу данных в InterBase

A. Так как с помощью метода ExecuteDirect не удается создать базу данных, то можно воспользоваться следующим способом (или низкоуровневым API):

Пример:

{$R EmptyDB.RES}

procedure CreateDB(const DatabaseName: string);
var
  HRsrc: THandle;
  Stream: TResourceStream;
begin
  HRsrc := FindResource(HInstance, PChar('EMPTYDB'), RT_RCDATA);
  if HRsrc <> 0 then
  begin
    Stream := TResourceStream.Create(HInstance, 'EMPTYDB', RT_RCDATA);
    try
      Stream.SaveToFile(DatabaseName);
    finally
      Stream.Free;
    end;
  end;
end;
 

Q. Как TDataSetProvider определяет изменена ли запись другим пользователем

A. Для этих целей компонент DataSetProvider имеет свойство UpdateMode. Когда провайдер генерирует операторы SQL для обновления базы данных, каждый оператор UPDATE или DELETE включает условие WHERE для идентификации записи. Если UpdateMode установлен в:

Q. Как обновлять результаты многотабличных выборок, процедур и не редактируемых view

A. Имеется три метода:

Пример:

procedure TForm1.DataSetProvider1BeforeUpdateRecord(Sender: TObject;
  SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
  UpdateKind: TUpdateKind; var Applied: Boolean);
var
  SQL: string;
  Connection: TSQLConnection;
begin
  //Будем использовать соединение переданного набора данных
  Connection := (SourceDS as TCustomSQLDataSet).SQLConnection;

  case UpdateKind of
    ukInsert: begin
      SQL := 'Вставка записи в 1-ую таблицу';
      Connection.Execute(SQL, nil, nil);

      SQL := 'Вставка записи в 2-ую таблицу';
      Connection.Execute(SQL, nil, nil);
    end;

    ukModify: begin
      SQL := 'Изменение 1-ой таблицы';
      Connection.Execute(SQL, nil, nil);

      SQL := 'Изменение 2-ой таблицы';
      Connection.Execute(SQL, nil, nil);
    end;

    ukDelete: begin
      SQL := 'Удаление из 1-ой таблицы';
      Connection.Execute(SQL, nil, nil);

      SQL := 'Удаление из 2-ой таблицы';
      Connection.Execute(SQL, nil, nil);
    end;
  end;

  //Уведомляем провайдер, что изменения выполнены вручную
  Applied := True;
end;
 

Q. Где разместить бизнес-логику

A. Так как в обработчике BeforeUpdateRecord провайдера имеется возможность проверять запись перед ее обновлением, и изменять значения полей - то это лучшее место для размещения бизнес логики. Если в данном обработчике будет производиться модификация полей, перед отправкой на сервер базы данных, то необходимо установить poPropogateChanges в True. Теперь провайдер будет отсылать изменения обратно в ClientDataSet для обновления записей, хранимых в памяти.
 

Q. Что такое клонирование данных

A. Это способность клиентского набора данных TClientDataSet, клонировать информацию из другого набора данных. При этом создается только одна физическая копия данных, к которой получают доступ два и более различных наборов данных.  Изменения в одном наборе данных немедленно отражаются на представлении данных другого набора. Зачем это надо:

Пример:

var 
  cdsClone: TClientDataSet;
begin 
  cdsClone := TClientDataSet.Create(nil);
  try
    cdsClone.CloneCursor(ClientDataSet1, False, False);
    ...
  finally
    cdsClone.Free;
  end;
end;

Q. Какие функции доступны для локальной фильтрации клиентских наборов данных TClientDataSet

A.

Функция  Описание  Пример 
=  Проверка равенства  ID=100 
<>  Проверка неравенства  ID<>100 
<  Меньше чем  ID<100 
>  Больше чем  ID>100 
<=  Меньше или равно  ID<=100 
>=  Больше или равно  ID=>100 
BLANK  Пустое строковое поле (не тоже что NULL)  Name=BLANK 
IS NULL  Проверка на нулевое значение  ID IS NULL 
IS NOT NULL  Проверка на ненулевое значение  ID IS NOT NULL 
AND  Логическое И  (ID=100) AND (Name=BLANK) 
OR  Логическое ИЛИ  (ID=100) OR (Name=BLANK) 
NOT  Логическое ОТРИЦАНИЕ  NOT (Name=BLANK) 
+  Сложение (чисел, строк и дат/времени)   
-  Вычитание (чисел и дат/времени)   
*  Умножение (чисел)   
/  Деление (чисел)   
Upper  Верхний регистр  Upper(Name)='PEGAS' 
Lower  Нижний регистр  Upper(Name)='pegas' 
SubString  Вырезать подстроку  SubString(Name, 3)='AS' 
Trim  Вырезание начальных и конечных символов строки  Trim(Name) или Trim(Name, '.') 
TrimLeft  Вырезание начальных символов строки  TrimLeft(Name) или TrimLeft(Name, '.') 
TrimRight  Вырезание конечных символов строки  TrimRight(Name) или TrimRight(Name, '.') 
Year  Возвращает год из значения даты  Year(BDay)=2003 
Month  Возвращает месяц из значения даты  Month(BDay)=4 
Day  Возвращает дня из значения даты  Day(BDay)=8 
Hour  Возвращает часы (24 часовой формат) из значения времени  Hour(MTime)=14 
Minute  Возвращает минуты из значения времени  Minute(MTime)=40 
Second  Возвращает секунды из значения времени  Second(MTime)=0 
GetDate  Возвращает текущую дату и время  BDayTime < GetDate 
Date  Возвращает дату из значения дата/время  Date(BDayTime) 
Time  Возвращает время из значения дата/время  Time(BDayTime) 
LIKE  Частичное сравнение строк  Name LIKE '%PEGAS%' 
IN  Поиск во множестве значений  Month(BDay) IN (10, 11, 12) 
*  Частичное сравнение строк  Name = '*AS' 

Q. Зачем и как использовать свойство SchemaName

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

SchemaName.TableName или SchemaName.ProcedureName

Для СУБД Informix, в данном свойстве можно указать: Имя_базы:владелец_таблицы. И тогда запрос к таблице access с SchemaName=odessa9:informix, будет выглядеть так: select * from odessa9:informix.access.

Q. Как работать с BLOB полями

A. Для работы с BLOB полями посредством технологии dbExpress, Delphi предоставляет два класса TBlobField (и его наследники TGraphicField и TMemoField) и TClientBlobStream (для поддержки метода TCustomClientDataSet.CreateBlobStream).

Для примера создадим в Oracle таблицу:

CREATE TABLE TEST ( 
  ID NUMBER, 
  BL BLOB,
  CL CLOB); 

Запись в BLOB поле:

var
  Stream: TStream;
begin
  with ClientDataSet1 do
  begin
    Open;
    Insert;
    FieldByName('ID').AsInteger := 1;
    Stream := CreateBlobStream(FieldByName('BL'), bmWrite);
    try 
      Image1.Picture.Bitmap.SaveToStream(Stream);
    finally
      Stream.Free;
    end;
    Post;
    ApplyUpdates(0);
  end;
end;

Важно: Необходимо освобождать поток созданный CreateBlobStream, до вызова метода Post. Так как именно в деструкторе происходит физическая запись данных потока в в буфер TCustomClientDataSet.

или так 

var
  Stream: TMemoryStream;
begin
  with ClientDataSet1 do
  begin
    Open;
    Insert;
    FieldByName('ID').AsInteger := 1;
    Stream := TMemoryStream.Create;
    try
      Image1.Picture.Bitmap.SaveToStream(Stream);
      TBlobField(FieldByName('BL')).LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    Post;
    ApplyUpdates(0);
  end;
end;

или так 

var
  myParams : TParams;
  cSQL : string;
  FileStream : TFileStream;
begin
  SQLConnection1.ExecuteDirect('DELETE FROM BLOBS');
  SQLConnection1.ExecuteDirect('INSERT INTO BLOBS(MYNUM, MYID) VALUES(1, "PEGAS")');

  cSQL := 'UPDATE BLOBS SET MYBLOB = :BlobParam WHERE MYNUM = 1';
  myParams := TParams.Create;
  myParams.Clear;
  myParams.CreateParam(ftBlob, 'BlobParam', ptInput);
  FileStream := TFileStream.Create('d:\tp38.bmp', fmOpenRead);
  myParams.ParamByName('BlobParam').LoadFromStream(FileStream, ftBlob);
  FileStream.Free;
  SQLConnection1.Execute(cSQL, myParams);
  myParams.Free;
end;

Чтение из BLOB поля:

var
  Stream: TStream;
begin
  with SQLQuery1 do
  begin
    Close;
    Open;
    Stream := CreateBlobStream(FieldByName('BL'), bmRead);
    try
      Image1.Picture.Bitmap.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
  end;
end;

В случае CLOB полей, можно обращаться напрямую к свойству Value поля.

Запись: FieldByName('CL').Value := Memo1.Lines.Text;
Чтение: Memo1.Lines.Text := FieldByName('CL').Value;

Для Informix, описанные выше подходы работоспособны, если:

 

Если свойство poFetchBlobsOnDemand компонента TDataSetProvider установлено в True, данные BLOB полей не будут передаваться в пакете данных. Для получения всех BLOB полей текущей записи необходимо явно вызвать метод TClientDataSet. FetchBlobs.

Если свойство TClientDataSet.FetchOnDemand установлено в True, то клиентский набор данных вызывает метод FetchBlobs автоматически. Для извлечения BLOB полей вручную следует установить poFetchBlobsOnDemand в True, а FetchOnDemand в False.

Q. Способы развертывания приложения, использующего dbExpress

A. Имеется два способа: в виде автономного единого EXE файла, либо используя динамически подключаемые библиотеки DLL.

Для создания автономного файла, необходимо добавить в оператор USES ссылку на три DCU файла, находящихся в директории Lib.

Модуль  Необходимо включить 
dbExpInt Если приложение подключается к базе данных InterBase
dbExpOra Если приложение подключается к базе данных Oracle
dbExpDb2 Если приложение подключается к базе данных DB2
dbExpMySQL Если приложение подключается к базе данных MySQL 3.23.x (dbExpMyS для версии 3.22.x)
Crtl, MidasLib Если приложение dbExpress использует клиентские наборы данных. Лучше подключать всегда, так как без них у Delphi7 - случается внутренняя ошибка компиляции приложения

Для Informix и MS SQL невозможно создать автономный файла, так как поставляются только *.dll.

Использование динамически подключаемыех библиотек DLL.
Работу механизма dbExpress в программе выполняют две библиотеки. Их имена совпадают с именами DCU файлов.

Библиотека DLL  Используется 
dbExpInt.dll Если приложение подключается к базе данных InterBase
dbExpOra.dll Если приложение подключается к базе данных Oracle
dbExpInf.dll Если приложение подключается к базе данных Informix
dbExpMSS.dll Если приложение подключается к базе данных MS SQL
dbExpDb2.dll Если приложение подключается к базе данных DB2
dbExpMySQL.dll Если приложение подключается к базе данных MySQL 3.23.x (dbExpMyS.dll для версии 3.22.x)
Midas.dll Если приложение dbExpress использует клиентские наборы данных. Также данную библиотеку необходимо регистрировать в реестре.

Все дополнительные библиотеки должны находится либо в директории вашей программы, либо в директориях указанных в переменной PATH.

Q. Распространение библиотеки MIDAS.DLL и совместимость с предыдущими версиями
A. По утверждению Borland наилучшим вариантом есть поставка MIDAS.DLL из поставки Delphi7.

"Version of MIDAS.DLL from Delphi 7 (7.0.4.453). Fixes many bugs, and is backwards compatible with Delphi 5 and 6 (a claim has been made that TByteField is not backwards compatible, and XML files saved in prior versions need to be regenerated with this DLL)."

Имеется два пути распространения:

Q. Для компиляции полностью автономного приложения, в раздел Uses был добавлен модуль dbExpress соответствующей СУБД. Но при компиляции выдается ошибка "[Fatal Error] Internal error: L3169"

A. В раздел Uses, необходимо вручную добавить модули Crtl, MidasLib.

Q. Ошибка "ORA-01722: invalid number"

A. Происходит при попытке записи в базу числовых значений. Такое происходит если разделителем целой и дробной части числа является запятая. Для решения проблемы надо устанавливать параметр сессии NLS_NUMERIC_CHARACTERS='.'.

Q. Ошибка "DBXError: Invalid Field Type", при работе с ORACLE и использования параметров типа число или дата

A. Для решения проблемы необходимо конвертировать все числовые типы полей в тип ftBCD, ftFMTBCD или в ftString. Остальные числовые типы полей драйвером Oracle не поддерживаются (также смотри Ошибка "ORA-01722: invalid number"). Или перейти на драйвер стороннего производителя (например http://www.crlab.com/dbx/dbxoda.exe, trial версия ограничена выборкой 6-и полей).

Пример работы с параметрами:
    for i := 0 to Params.Count - 1 do
    begin
        case VarType(Params[i].Value) of
        varInteger,
        varSmallInt,
        varShortInt,
        varWord,
        varByte,
        varLongWord: 
            Params[i].AsString := VarToStr(Params[i].Value);
        varSingle,
        varDouble,
        varCurrency: 
            Params[i].AsBCD := StrToCurr(VarToStr(Params[i].Value);
        varDate: 
            Params[i].AsSQLTimeStamp := DateTimeToSQLTimeStamp(VarToDateTime(Params[i].Value));
    end;

  

Q. Ошибка "Access violation at address 77FCBF00 in module 'ntdll.dll'. Write of address FB426801"

A. Происходит при использовании драйвера dbexpora.dll (из Delphi 7.0 (Build 4.453), размер файла 171008 байт) в многопоточных приложениях, при открытии и закрытии соединений с базой данных. Данная ошибка проявляется, если установлен клиент Oracle 8.1.6. Для решения данной проблемы рекомендуется обновить версию клиента Oracle до версии 8.1.7 или использовать dbexpora.dll из поставки C++ Builder 6.0 (размер файла 166400 байт).

Q. Ошибка "The ordinal 960 could not be located in the dynamic link library ISQLT09A.DLL", при подключении к Informix

A. Необходимо обновить клиента Informix, по крайней мере до версии 2.70.

Q. Ошибка "dbExpress Error: Invalid Username/Password.", при подключении к Informix

A. Следует убедиться что в параметрах соединения "User_Name", "Password" - заданы корректные значения. К сожалению, данная ошибка также выдается, и в других случаях. Также следует убедиться, что корректны параметры "HostName" (должен соответствовать значению параметра "Informix Server", созданного с помощью утилиты Setnet32) и "DataBase".

Q. Ошибка "Not in transaction" на Informix

A. Это ошибка в поставляемом драйвере (все таки beta версия). Происходит так как метод StartTransaction(T), выдает команду COMMIT без BEGIN WORK (на Oracle это допустимо, на Informix нет). Данная ошибка обходится вызовом: SQLConnection1.ExecuteDirect('begin work'); К сожалению придется данную команду вставлять везде, перед редактированием наборов данных, так как вызов ApplyUpdates(0) автоматически посылает COMMIT. На драйвере от Luxena данной ошибки нет.
 

Q. Компонент TSQLStoredProc, подключенный к СУБД Informix, в DesignTime показывает пустой список процедур в свойстве StoredProcName

A. Драйвер поставляемый Borland ориентирован на 9-ю версию Informix. Поэтому на 7-ой версии, список процедур недоступен. Следует использовать альтернативные драйвера для Informix. Возможно при динамическом создании данного класса, и заполнения его свойств - все будет работать.

Q. Ошибка "Error loading MIDAS.DLL"

A. Если приложение использует дополнительные DLL, то при первом запуске приложения в реестре добавляются ссылки на файл Midas.dll. При перемещении или удалении файла из данного места все приложения использующие Midas.dll перестают работать. Для восстановления работоспособности необходимо вручную удалить данные записи из реестра или выполнить повторную регистрацию: regsvr32.exe Midas.dll.

Q. Ошибка "Operation not applicable"

A. Данная ошибка проявляется, если на компьютере зарегистрирована версия Midas.dll поставляемая например с Delphi5 (другие приложения разработанные в Delphi5 или установлена среда Delphi5), а приложение было разработано на Delphi7. Так как Midas.dll реализует com-сервер, который регистрируется в реестре, то единственным выходом является переход к использованию Midas.dll поставляемой с Delphi7. Рекомендуется скопировать/заменить файл Midas.dll расположенный в каталоге %SystemRoot%\System32. А также выполнить регистрацию: regsvr32.exe Midas.dll.

Q. Ошибка "dbExpress Error: Operation Not Supported", при вызове TSQLQuery.RecordCount.

A. Для драйвера Oracle, также предшествует ошибка "ORA-00942: table or view does not exists". Имена таблиц рекомендуется брать в двойные кавычки и писать заглавными буквами, так как имена чувствительны к регистру. Так как на Informix такое не наблюдается, то есть вероятность, что это ошибка драйвера, и возможно в дальнейшем будет исправлено.

Также нельзя пользоваться свойством RecordCount, если:

Q. Ошибка "List index out of bounds (-1)"

A. Выдается компонентом TClientDataSet при присвоении ему данных, которые были получены при использовании аналитических функций Oracle 8i производящих неявную сортировку данных. Для решения проблемы, необходимо установить свойство poRetainServerOrder в True у TDataSetProvider. 

Q. Как можно понять, ошибка ли в настройке свойств драйвера или это его "фича"

A. Это легко сделать с помощью компонента TSQLMonitor. С его помощью можно контролировать все операторы SQL, передаваемые компонентом SQLConnection серверу баз данных. Информация может быть сохранена в файл, компонент TMemo, или обработана любым другим способом. Аналогом для BDE была утилита SQL Monitor.

На примере вопроса "Компонент TSQLStoredProc, подключенный к СУБД Informix, в DesignTime показывает пустой список процедур в свойстве StoredProcName", выясняется что на сервер Informix посылается запрос вида:

select 0, '', t.owner, t.procname, t.isproc, t.numargs, t.numargs, t.procid from informix.sysprocedures t where ( ( t.procid > 175) ) order by t.procname ASC, t.procid ASC 

Из него видно что из системной таблицы informix.sysprocedures запрашивается поле isproc - которое на 7-ой версии не существовало, поэтому запрос оказывается не работоспособным.

Copyright © 2004 Алексей Макаренко&Олег Перехрест  Специально для Delphi Plus

Rambler's Top100