Работа с таблицами в коде

Previous  Top  Next

    
 

 

Пока мы рассмотрели самые простейшие и самые не эффективные операции над базами данных, которые нужны лишь в очень ограниченных случаях - их недостаток очевиден - операции роводятся только с одной записью и эти операции только визуальные. Чем это плохо? - это самый медленный способ работы с базами. Он годиться только для работы с данными в ручную, все остальные операции, которые не требуют визуализации не должны работать таким образом.

 

Итак, начинаем разбирать способы работы с базами данных в коде.

Прежде всего заметим, что работать мы будем только с компонентом

Table1. Сразу предупреждаю - КАТЕГОРИЧЕСКИ НЕ СЛЕДУЕТ ПЫТАТЬСЯ ИЗ

КОДА МЕНЯТЬ ЗНАЧЕНИЯ В ВИЗУАЛЬНЫХ КОМПОНЕНТАХ, не следует пытаться

менять или читать значения из DBGrid, DBEdit и т.д. Эти компоненты

существуют только для работы оператора "вручную". Для доступа к

данным из кода надо использовать только невизуальные компоненты

типа TTable (в дальнейшем мы разберём и другие компоненты для работы

с данными - но в любом случае это будут не визуальные компоненты).

 

Представив себе обычную таблицу, понятно что для доступа к данным

надо определить столбец(поле) и строку(запись) в которой эти данные

находятся. Давайте разбирать по очереди.

 

1) Определить поле задача очень простая. Способов здесь 2:

или по имени:

 

Table1.FieldByName('Category')

 

или по номеру столбца

 

Table1.Fields[1]

 

Оба выражения являются объектом наследованным от типа TField

 

Я не буду разбирать этот объект подробно, только приведу пример

как можно пользоваться этим объектом для доступа к содержимому

ячейки таблицы. Содержимое может быть разных типов, поэтому можно

использовать следующие методы в зависимости от типа данных:

Code:

Table1.FieldByName('Category').AsString

Table1.FieldByName('Category').AsInteger

Table1.FieldByName('Category').AsBoolean

Table1.FieldByName('Category').AsDateTime

Table1.FieldByName('Category').AsFloat

 

 

 

Например, поставте на форму кнопку, и на onClick напишите

следующий код:

 

Showmessage(Table1.FieldByName('Category').AsString);

 

При нажатии на кнопку вы увидите содержимое столбца 'Category'

для текущей записи. Аналогично для обращения по номеру:

 

Showmessage(Table1.Fields[1].AsString);

 

Обратите внимание, что на этапе компилляции компиллятор абсолютно

не знает о реальном типе данных в поле таблицы. Это выяснится

только при попытке выполнить строку. Что будет если типы не

совпадают? Если тип можно конвертировать - то ничего страшного,

например если у вас поле с целым числом 123, то обращение к полю

через AsString выдаст результат - строку '123'. Но если типы

не совместимы, то будет сгенерирована ошибка, например такая строка

почти наверняка в нашем приложении приведёт к ошибке:

Code:

var i:integer;

...

i:=Table1.FieldByName('Category').AsInteger;

showmessage(inttostr(i));

 

 

 

Потому что реальные данные не могут быть приведены к целому типу.

 

Теперь давайте разбираться как нам добраться до нужной строки,

другими словами, до нужной записи. Как я уже говорил мы можем

работать только с одной "активной" записью, поэтому задача сводится

к установке нужной записи "активной" (К знатокам баз данных - я упорно

и намеренно обхожу стороной понятие "курсор" и попытаюсь провести повествование

без его упоминания, с целью упрощения понимания материала и не хочу углублятся

в материал, без которого можно на первых порах обойтись). Итак, прежде всего

Table компонент имеет 4 метода которые помогут нам пройти через все строки

таблицы:

 

Table1.First - переход на первую запись

Table1.Last - переход на последнюю запись

Table1.Prior - переход на предыдущую запись

Table1.Next - переход на следующую запись

 

А так же 2 полезных свойства:

 

Table1.RecordCount - возвращает количество записей (строк) в таблице

Table1.Eof - возвращает TRUE если достигнута последняя запись, в остальных случаях FALSE

 

 

Давайте на нашу форму положим компонент Memo (на сей раз обычное, а не dbMemo).

 

Вот этот простейший код позволит пройти таблицу от начала до конца и считать

значения одного поля для всех записей в Memo:

Code:

Table1.First;//переход на первую запись

While not Table1.eof do //делать цикл пока таблица не закончится

begin

Memo1.lines.add(Table1.fieldbyname('Category').AsString); //заносим в Мемо значение поля для текущей записи

Table1.Next;//переходим на следующую запись

end;

 

 

 

Или это же самое можно сделать например так:

Code:

Table1.First;

For i=0 to Table1.recordcount-1 do

begin

Memo1.lines.add(Table1.fieldbyname('Category').AsString); //заносим в Мемо значение поля для текущей записи

Table1.Next;//переходим на следующую запись

end;

 

 

 

Второй способ гораздо хуже. Он имеет следующие недостатки:

 

1) Не для всех баз данных метод Table1.recordcount возвращает правильное

значение. Иногда Table1.recordcount устанавливается только после перехода на

последнюю запись(это не глюк, это вполне объяснимое поведение, например если у

вас есть хорошая табличка размером в несколько гигабайт на другом компьютере,

то Table вовсе не скачивает всю эту таблицу локально, а достаёт данные только

по мере необходимости). К счастью этот недостаток легко устраним, надо код

преобразовать до следующего вида:

Code:

Table1.Last;

Table1.First;

For i=0 to Table1.recordcount-1 do

begin

Memo1.lines.add(Table1.fieldbyname('Category').AsString); //заносим в Мемо значение поля для текущей записи

Table1.Next;//переходим на следующую запись

end;

 

 

 

Несмотря на кажущуюся бессмысленность это работает.

 

2) А вот другой аспект - всегда надо помнить о многопользовательском

доступе к таблицам - что случится, если во время прохода по записям другой пользователь

добавит или удалит запись?