Вопрос по работе DBF

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Вопрос по работе DBF

Сообщение Ichthyander » 22.01.2009 04:50:02

С базами данных до сих пор вплотную не сталкивался. Помогите разобраться, пожалуйста!
Не понял принцип работы формата DBF (или работы Lazarus'а с этим DBF).
Свойство Level компонента типа TDBF ставлю в 4 (dBase IV). Добавляю индексы в базу (DBF.AddIndex), выясняется, что добавлять в индексы можно только string или float (кстати, из-за чего такое ограничение?), а у меня есть еще логические (ftBool) и формат даты (ftDate).
Дальше пытаюсь использовать фильтр с помощью свойства filter.
Код: Выделить всё
filter := 'field1="value1" and field2="value2"' и т.п.

Все работает, пока я использую в фильтре только поля строкового типа (ftString). Когда пытаюсь добавить другие поля выдает странное сообщение, что "индекс основан на неизвестном поле". Выходит, что фильтр можно применять только по индексированным полям..?
Отсюда следует вывод, исходя из двух ограничений, что фильтр в dBase применим только к строковым или вещественным полям?! Понимаю что это не так, но объясните, что именно я не понимаю :oops:
0.9.26 beta
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 686
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Вопрос по работе DBF

Сообщение Vadim » 22.01.2009 06:53:46

Начнём с того, что Вы работаете не с DBF-файлами, а с компонентом TDBF. А уж компонент TDBF работает с DBF файлами. :)
Если Вы используете Boolean-поля, то учтите, что они уже сами по себе логическое выражение. Вот, к примеру, взял я таблицу из стандартной поставки VFP под названием foxcode.dbf. Теперь, чтобы отфильтровать её по логическому полю SAVE, пишу такую фигню:
Код: Выделить всё
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
  Dbf1.Filtered:=False;
  If RadioGroup1.ItemIndex=0 Then
    dbf1.Filter:='save'
  Else
    dbf1.Filter:='not save';
  Dbf1.Filtered:=True;
end;

И всё фильтруется самым восхитительным образом. :)
Согласен, сообщение "индекс основан на неизвестном поле" маловнятное, но позволяет предположить, что TDBF посчитал Ваше "value" за название какого-то неведосого поля, которого, естественно в таблице нет.

Добавлено спустя 10 минут 54 секунды:
Кстати, TableLevel лучше ставить равным 7, т.к. у dBase IV было маловато типов данных, а вот у dBase 7 уже появились целочисленные, блоб и прочие поля. Думаю и с индексами тогда Ваша проблема решится.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Вопрос по работе DBF

Сообщение Ichthyander » 22.01.2009 10:27:09

:)
If RadioGroup1.ItemIndex=0 Then
dbf1.Filter:='save'
Else
dbf1.Filter:='not save';

Ух ты, как все элементарно оказывается! Что только я не пробовал: BoolField="True", BoolField="0"; BoolField="t"... а ведь сколько не искал в и-нете, не нашел, вернее нашел, но как раз то что и использовал (BoolField="True") :)

Кстати, TableLevel лучше ставить равным 7, т.к. у dBase IV было маловато типов данных, а вот у dBase 7 уже появились целочисленные, блоб и прочие поля. Думаю и с индексами тогда Ваша проблема решится.

Большинство бесплатных DBF просмотрщиков открывает dBase IV и не открывают DBF level 7 (Visual dBase), поэтому подумал использовать dBase IV, но это не принципиально, думаю, действительно, лучше поставить level 7, тем более что очень неудобно, когда отсутствует тип поля данных AutoInc в dBase IV...
Спасибо, Вадим
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 686
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Вопрос по работе DBF

Сообщение Vadim » 22.01.2009 11:14:11

Ichthyander
Да не за что. ;)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Вопрос по работе DBF

Сообщение Ichthyander » 22.01.2009 11:52:52

Кстати, нашел интересный документ http://www.grifsolu.com/funcmain.php
Эти функции работают в свойстве filter. Проверял.
Так чтобы использовать фильтр по дате, добавил такое выражение: filter := 'DTOS(DateField)="DateString"', где DateString - строка, представляющая дату в формате 'ccyymmdd', а DateField - имя поля даты
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 686
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Вопрос по работе DBF

Сообщение Ichthyander » 23.01.2009 23:27:57

Еще один вопрос. Не получается сортировка.
Код
Код: Выделить всё
DBFResponses.IndexFieldNames := Column.FieldName

почему-то не прокатывает :(
Что может быть не так?
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 686
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Вопрос по работе DBF

Сообщение Vadim » 24.01.2009 06:33:59

Ichthyander
Вот что нам рассказывает справка Delphi по поводу применения IndexFieldNames:
For Paradox and dBASE any column names specified in IndexFieldNames must already be indexed.

Ну, слово "Paradox", в данном случе, можно проигнорировать. :) А вот остальное стоит прочитать крайне внимательно. По-русски это выглядит примерно так:
Любые имена колонок указанные в IndexFieldNames должны быть проиндексированы.

Или, по другому говоря, для этой колонки должен существовать индексный файл. В Вашем случае это так?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Вопрос по работе DBF

Сообщение Ichthyander » 24.01.2009 11:07:59

Да, я проиндексировал некоторые поля (AutoInc и строковые). Покажу код:
Функция инициализации базы данных
Код: Выделить всё
function DBInitialization(const DBFDir: String): TDbf;
begin
  Result := TDBF.Create(nil);
  with Result do
  begin
    TableLevel := 7;
    TableName := DBFileName;
    FilePathFull := DBFDir;
    Exclusive := False;
    DBDefineFields(Result)
  end
end;

Объявление полей
Код: Выделить всё
procedure DBDefineFields(DBF: TDBF);
begin
  with DBF.FieldDefs do
  begin
    Clear;
    Add(FieldNames[fiID], ftAutoInc, 0, True);
    Add(FieldNames[fiRepeated], ftBoolean, 0, True);
......    ..........    ............   ..........   ......
    Add(FieldNames[fiC], ftInteger, 0, True);
    Add(FieldNames[fiAC], ftInteger, 0, True)
  end
end;

Функция создания базы данных
Код: Выделить всё
function CreateResponsesTable(DBF: TDBF): Boolean;
begin
  with DBF do
  begin
    Close;
    DBDefineFields(DBF);
    if not DirectoryExists(FilePathFull) then
      Result := CreateDir(FilePathFull)
    else
      Result := True;
    if Result then
    begin
      CreateTable;
      Exclusive := true;
      Open;
      AddIndex(FieldNames[fiID], FieldNames[fiID], [ixPrimary, ixUnique]);
.... ....  ....  ....  ....  ....  ....  ....  ....  ....  ....  ....  ....
      AddIndex(FieldNames[fiNegCharName],
        FieldNames[fiNegCharName], [ixCaseInsensitive]);
      Close;
      Exclusive := False
    end
  end
end;

Как видите в функции создания базы данных у меня идет добавление индексов (кстати, база данных так и ругается, когда я пытаюсь добавить какой-нибудь индекс типа TDataTime или TDate).
Но я уже стал сомневаться... Может быть функцию AddIndex нужно вызывать не только при создании, но и каждый раз при открытии базы данных?..
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 686
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Вопрос по работе DBF

Сообщение Vadim » 24.01.2009 11:56:01

Вот я воспроизвёл у себя Ваш пример, правда в несколько урезанном виде:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
  dbf1.TableLevel := 7;
  dbf1.TableName := 'mytable.dbf';
  dbf1.FilePath := 'Каталог\где\лежит\таблица';
  dbf1.Exclusive := True;  //Надо True, чтобы создавались индексы
  with DBF1.FieldDefs do
  begin
    Clear;
    Add('fiID', ftAutoInc);
    Add('fiRepeated', ftBoolean);
    Add('fiC', ftInteger);
    Add('fiAC', ftInteger);
    Add('fiNegCharName', ftString, 30);
  end;
  dbf1.CreateTable;
  dbf1.Open;
  dbf1.AddIndex('fiID', 'fiID', [ixPrimary, ixUnique]);
  dbf1.AddIndex('fiNegCharName','fiNegCharName', [ixCaseInsensitive]);
  dbf1.IndexFieldNames:='fiNegCharName';
end;

В самом конце я назначаю текущим индексом 'fiNegCharName' и сразу же начинаю вводить данные в DBGrid связанный с этой таблицей.
Сортировка происходит самым восхитительным образом, т.е. сразу же после того, как я ввёл значение в поле 'fiNegCharName' и перешёл на следующую строку, это значение встаёт именно на то место, которое и положено ему по индексу.
Сравните, в чём отличие Вашего кода...
В dbf версии 7 создаётся один индексный файл для всех индексов относящихся к таблице - файл с расширением .mdx. Он должен лежать рядом с файлом таблицы. Этот файл при открытии таблицы открывается автоматически. Всё что нужно после этого - либо выбрать поле индексирования, если индексы построены только по одному полю, а не по нескольким, либо выбрать название индекса (IndexName), если индекс сложносоставной.
И всё...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Вопрос по работе DBF

Сообщение Andrew » 26.01.2009 08:17:34

Здравствуйте, у меня такой вопрос
можно ли при помощи tdbf скинуть кодовую таблицу базы в нулевую, а то для этого приходиться пользоваться сторонним софтом
Andrew
новенький
 
Сообщения: 14
Зарегистрирован: 15.01.2008 23:21:26


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 45

Рейтинг@Mail.ru