Урок  3          "Базы Данных"                                   

  by Frank Fortino (ffortino@svn.net)     Copyright 1999

Перевод на русский язык   Руденко Е.В.  janerev@hotmale.ru



  Содержание:


L3examp.zip - примеры программ


  •  -Button Mouse Clicks             BtbClick1P
  •  -Buttons                                     FirstBtnP,                Btn2P
  •  -DBDatePicker                        DBDatePickerP
  •  -DBGridMultiSel1                  GridMultiSel1P
  •  -DBReadField                           DBReadFieldP
  •  -DisplayWindows                    Windows1P
  •  -FilterLocate                             DBFilter1P
  •  -FirstDB                                    FirstDBP
  •  -ListBoxes                                 LB1P,                         LB2P
  •  -MultiFormTimer                    MultiFormTimerP
  •  -SQLFind                                  SQLFindP
  •  -Timer                                       Timer1P


Я включил  14 Примеров программ из уроков в файл "L3Examples.zip".  Пытайтесь запускать и изменять ВСЕ из них.

В данном Уроке я не могу рассмотреть все о Базах Данных, так что далее будет еще один урок.


Ну, если вы действительно начинающий программист на  Delphi , вы можете не понять всего, но вы должны читать и выполнять эти Уроки, даже если вы чего-то не понимаете.

Помните, что эти Уроки для Начинающих, так что я раскрываю только основы Баз Данных.

Я собираюсь рассказать только о  Локальных Базах Данных  Paradox  и  Локальном  SQL.  Вместе с Уроком 2 у вас должен быть файл  LocalSQL.htm .
    Некоторые моменты программирования Баз данных  трудно объяснить словами, так что я написал несколько простых программ примеров. Поиграйтесь с ними и изучите, как они работают .


Примечание:

Мои Уроки не имеют четкой организации. Базы Данных - действительно сложная штука . 
Я не могу объяснить все об их устройстве; во-первых, потому что всего я не знаю, и во-вторых, это будет слишком детально, как в книгах.

Так что, я собираюсь сосредоточиться на некоторых вещах.  Я хочу немедленно начать использовать Базы Данных, а не только читать о них.
 Также я хочу , чтобы вы использовали язык  SQL сразу со старта.

Итак, ВСЕ НА БОРТУ, давайте двигаться дальше!


Что такое База Данных (БД)?         

Давайте вернемся на шаг назад и взглянем на БД немного с другой стороны.

Сначала давайте определим все новые термины:

-База Данных (Database)
-Таблица (Table)
-Запись (Record)
-Поле (Field)
-Запрос (Query)
-Набор Базы Данных (Dataset)
-SQL
-Источник Данных (Datasource)
-Реальные (поля) (Persistance)
-Ключ (Key)
-Индекс (Index)
-Вторичный Индекс (Secondary Index)
-Курсор (Cursor)
-Вычисляемое поле (Calculated Field)
-Поле Просмотра (Lookup Field)
-Тип базы Данных (Database Types)
-Программы и Инструменты для работы с БД (Programs and Tools that manage Databases)
-Локальная База Данных (Local Database)
-Алиас (Alias)
-Компоненты для работы с БД (Data Aware Components)
-DBI


- БАЗА ДАННЫХ  = Набор  Таблиц.

- ТАБЛИЦА = Набор  Записей, состоящих из одного или более  Полей.
                      Файлы на вашем винчестере  (.db .px)

- ПОЛЕ =  Колонка в таблице. Сохраняет один и только один вид данных.

- ЗАПИСЬ = Логический набор полей в таблице, часто называемый "строкой"

-ЗАПРОС = Как Таблица, но использует запрос на языке  SQL  (набор строк) для чтения и записи данных в  БД

-НАБОР БАЗЫ ДАННЫХ = Ссылка на  Таблицу  или  Запрос

-SQL = Структурированный Язык Запросов; большое число функций для работы с БД

-ИСТОЧНИК ДАННЫХ = Связующее звено между БД и Компонентами для работы с БД , такими как   DBGrid, DBEdit, DBLookUpComboBox, ...

-РЕАЛЬНЫЕ = Относится к реально существующим в базе данных полям
        (Вычисляемые поля и Поля просмотраК НИМ НЕ ОТНОСЯТСЯ)

-КЛЮЧПервичный Индекс (поле (или несколько полей) используемое для сортировки данных в БД)

-ИНДЕКС = Поле (или несколько полей) используемое для сортировки записей в БД (может быть Первичным или 

Вторичным )

-ВТОРИЧНЫЙ ИНДЕКС =Другое поле (поля), использующиеся для сортировки записей в БД.

-КУРСОР = Указатель на запись (на  первую Запись в БД, которую вы можете прочитать и записать в нее)

-ВЫЧИСЛЯЕМОЕ ПОЛЕ = Поле, которое рассчитывается по постоянным полям БД
        Вычисляемые поля существуют только в памяти и  Существуют НЕ ПОСТОЯННО

-ПОЛЕ ПРОСМОТРА = Поле, которое просматривается (содержится) в другой БД, используя Ключевое Поле (в обеих базах данных эти поля должны быть идентичны).
        Поле Просмотра -  НЕ ПОСТОЯННОЕ ПОЛЕ

-ТИПЫ БАЗ ДАННЫХ:
        -Paradox =Формат Баз данных (то есть , как данные хранятся на диске) (Который я использую)
        -DBase =Старый формат Баз Данных  (Который я не использую)
        -Access,  другая БД

-Программы и утилиты для работы с БД:
        -BDE - основная программа, которая осуществляет всю работу с БД
                (представляет собой  DLL (Dynamic Link Library) , которая должна инсталлироваться вместе с вашим .exe файлом )

        -DataBase Desktop - программа для создания БД, а также, для их просмотра и редактирования.

        -BDEcfg32 =программа для создания Алиасов

        -Database Explorer  (эту программу я практически не использую)

        -Local DatabaseБД, которая находится на жестком диске вашего компьютера, а не на сервере

-Alias =Путь (Директория) к БД (на вашем диске)

-Компоненты для работы с БД
        -DBGrid
        -DBEdit
        -DBLookUpComboBox
        - некоторые другие (Я назову их позже).  Их имена начинаются с  DB...

-DBI = Вызовы  BDE, подобно вызовам  Windows API 
        (Я попытаюсь их не использовать, потому что они используют "тонны" параметров)


Вопрос: Какой минимальный набор Компонентов нужен для работы с БД?
        Ответ.   2    Таблица (Table) и Источник Данных (DataSource)    (или Запрос (Query) и  DataSource)


КОММЕНТАРИЙ:     Почему необходимы  2 Компонента, а не 1?   (Ответ я не знаю!)
        Я знаю , что :

            -Когда вы хотите Записать или Прочитать данные (Запись) в БД, вы используете  Таблицу:

                    например,  Table1.FieldByName('CustName').AsString:='Bill Thomas';

            -Все Компоненты для работы с БД  (DBGrid, и т.д. ...) используют  DataSource для связи с  БД


Минимальная последовательность действий для работы с БД?          

(смотрите для примера  FirstDB.dpr   программу)
        -Разместите Таблицу ( Table) на форме (Table1)
        -Установите Свойства  Table1 в Инспекторе Объектов:
                1) Table1.DataBaseName => 'DBDemos' (это и называется  АЛИАС (путь к БД))
                        -Delphi присвоила странное имя для этого Свойства
                        -DataBaseName должно назваться DataBasePath или  DataBaseAlias НО ЭТО НЕ ТАК
                2) Table1.TableName => 'Customer.db';
        -Разместите  Datasource на форме (DataSource1)
                -Установите свойство  DataSource1.DataSet => Table1


ЗАМЕТЬТЕ: Чтобы показать вам выбор в  Инспекторе Объектов я буду использовать символ  '=>'
                            В  программном коде  используется символ ':='

        Данный формат я буду использовать на протяжении всех моих Уроков.


Некоторая "путаница" в Базах Данных:

    -DatabaseName (Свойство таблицы), Алиас и  (Путь к директории с файлами БД) -  всё означает одно и то же.
    -Таблица имеет Свойство, называемое  'DatabaseName'
            -которое показываетместо на диске, где размещаются файлы БД.
            -Это , по существу, путь к Директории с файлами БД:
                    например, c:\D3Data\DBases
            (Свойство "DatabaseName" должно было бы называться " DatabasePath", однако , это не так)


Вы можете запустить программу  BDEcfg32.exe и присвоить Алиас для пути к базе: 
        например,  MyDataBases = c:\D3Data\DBases
                        "MyDataBases" - это Алиас

Если вы определили Алиас (используя  BDEcfg32.exe), то он появляется в списке выбора в свойстве таблицы  DatabaseName  (в Инспекторе Объектов)

Если вы оставили свойство таблицы  DatabaseName пустым ( в Инспекторе Объектов), то по умолчанию считается, что ваша БД расположена в текущем каталоге.

При этом возникают некоторые вопросы, что яснее проявляется при работе с примером (FirstDBP.dpr)

Итак, теперь давайте считать, что Свойство таблицы  DatabaseName - это только путь  (указатель на директорию).


3 способа организовать вашу Базу Данных
        1) Разместить БД (.db .px файлы) в вашей текущей Директории
                При этом вы не должны заполнять свойство  Table1.DatabaseName (в Инспекторе Объектов)
             // Этот путь я использую при первоначальной разработке программы, так что БД сохраняется для каждой версии программы. Это помогает при добавлении новых полей или при изменении определений полей.

       2) Разместить все файлы вашей БД в Общей Директории (например, c:\DB\Data)
                Затем установите  Table1.DatabaseName(как путь) => 'c:\DB\Data' (в Инспекторе Объектов)     // Так я делаю чаще

        3) Разместите все файлы вашей БД в Общей Директории (например, c:\DB\Data)
                Затем создайте Алиас с помощью программы  BDEcfg32


Мои предпочтения:
    Я не люблю использовать Алиасы. Для их создания необходимо запускать программу  BDEcfg32.exe.
    И при инсталляции программы на другие компьютеры, на них приходится устанавливать Алиасы.
    Так что , я размещаю все мои базы данных в  1 подкаталоге.
    И затем я прописываю путь в Свойстве таблицы  Table1.DatabaseName .
        например, Table1.DatabaseName => 'c:\DB\Data'


Итак, что сказать еще о Базах Данных?

Ну, Базы Данных имеют целый набор прекрасных Методов и функций для  Сортировки, Фильтрации и Поиска данных.
        например, устанавливаем Свойство  Table1.Filter:='CustNun>1000';
        Метод Table1.Locate(..)     может найти подходящие под условие фильтра поля.

Вдобавок, существует  SQL , что дает некоторые "фантастические" возможности. 

Я буду много рассказывать о SQL позже (в последующих уроках).
Это такая важная и мощная принадлежность Баз Данных.


КОММЕНТАРИЙ:

Вы не можете копировать запись 1 командой.
Почему? Я думал , что БД - это могуче.

Таблица дает вам доступ только к 1 записи одновременно и вы не можете сделать копию легко (в действительности вы конечно можете это сделать, но сложным путем, так что здесь мы не будем это обсуждать)

У вас есть легкий доступ к Полям записи, так что вы можете копировать запись копируя все ее Поля.

Это одна из немногих слабостей, которые я нашел в структуре БД  Delphi.


Способы обращения (чтение/запись) к Полю:

    Table1.Fields[3].Value:='Frank'; // .Fields - массив

    Table1['CustName']:='Frank';

    Table1.FieldValues['CustName']:='Frank';

    Table1CustName.AsString:='Frank';
                    (если вы перед этим запустили Редактор Полей ( Fields Editor) и выбрали имя поля (CustName Field)

    Table1.FieldByName('CustName').AsString:='Frank';
                    (так я обычно и делаю)

Запустите пример программы :     DBReadField.dpr


Вычисляемые поля:

Вычисляемые поля  служат только для  отображения,
Это НЕ реально существующие поля в  .db файле, они существуют только в памяти.

Вы НЕ МОЖЕТЕ  делать поиск или сортировку в Вычисляемых полях.
Итак, что Вычисляемые поля не реальны.

Для использования вычисляемых полей вы должны сделать две вещи:
        -Создайте новое Поле ( New field) в Таблице, используя Редактор Полей ( Fields Editor)
                (щелкните правой кнопкой на Таблице и выберите  Fields Editor - затем прочитайте в вашей книге, как добавить Вычисляемое Поле к Таблице)
        -Используйте Событие Таблицы  OnCalcFields Event, чтобы сделать вычисления и занести данные в Вычисляемое Поле
                например,
        n1:=T1.FieldByName('N1').AsInteger;         // N1 и  N2 реально существующие поля
        n2:=T1.FieldByName('N2').AsInteger;
        T1.FieldByName('CalcN3').AsInteger:=n1+n2; // CalcN3 - вычисляемое поле


Наблюдение за БД

-НЕ УСТАНАВЛИВАЙТЕ  свойство таблиц  Active  => True в Инспекторе Объектов (при создании программы)
        Вы должны открыть ( Open) Таблицу в Событии формы  OnShow 
        begin
          Table1.Open;
        end;
-НЕ ПЫТАЙТЕСЬ  изменить любое из Реально существующих Полей Таблицы в Событие  OnCalc Event (для Таблицы)
        В Событии OnCalc Event вы можете изменить ТОЛЬКО Вычисляемые Поля.
        


Поиск в Базе Данных

В Delphi есть много методов для поиска в Базе Данных:
    -Find
    -FindNearest
    -GotoKey
    -GotoNearest
    -Lookup
    -Locate
    -SQL

    Я очень редко использую методы  Find, FindNearest, GotoKey, GotoNearest или Lookup.
    ВСЕ ОНИ  требуют, чтобы в Базе Данных имелся  Индекс для Поля , по которому вы осуществляете поиск.
    Если у вас есть много различных полей , по которым вы хотите осуществлять поиск, то все они должны быть        проиндексированы (так называемые Вторичные Индексы ( secondary Indexes)), причем каждый Вторичный индекс
            требует образования двух дополнительных файлов.

    то есть :

        Indexes         File Cnt         Files
        -------             ----------          ---------------------------------
            0                     1                     .dpr
            1                     2                     .dpr     .px
            2                     4                     .dpr     .px     .xg0     .yg0
            3                     6                     .dpr     .px     .xg0     .yg0     .xg1     .yg1

        Так для 3 Индексов (1 Первичный и  2 Вторичных) у вас образуется 6 файлов .
                Таким образом для каждой Базы Данных образуется множество файлов.

    Я использую Метод Table1. Locate() , когда хочу передвинуть Курсор (указатель в Таблице) к найденной записи. Это удобно делать с параметром  loPartialKey , который дает возможность поиска по частичному совпадению (вот пример:)
        

     Table1.Locate('CustName', 'Frank Fortino', [loPartialKey]);

Запустите пример программы:     FilterLocate.dpr


НУ Посмотрим наконец, что такое База Данных

Для создания Базы Данных используем Компоненты Доступа к БД :
        -DBGrid, DBEdit, DBLookupComboBox, ...

Компонент  DBGrid - самый мощный из данных Компонентов.

-Выберите в меню New Application

-Разместите  Table1 на  Form1     DatabaseName => DBDemos     TableName => Employee.db
-Разместите  DataSource на  Form1     Dataset =>Table1
-Разместите  DBGrid на  Form1    DataSource => DataSource1

-Установите для  Table1   Свойство   Active => True
        теперь DBGrid должна показывать Базу Данных  Employee.db 

-Установите для  Table1   Свойство   Active => False

В Событии  FormShow Event установите  Table1.Open :
    procedure TForm1.FormShow(Sender: TObject);
    begin
      Table1.Open;
    end;


Техника Франка:
    -Используйте компонент  DBGrids только для отображения данных, но не для редактирования
    -Почему? Потому что это слишком могучий компонент, который имеет множество свойств, могущих создать противные проблемы. Я опишу эти проблемы несколько позже.
    -Используйте группы компонентов DBEdit для редактирования и изменения данных; 


SQL

select
from
where
order by

    Основная структура языка  SQL 
        'select A,B from C where D>10 order by E'
                            -A and B are the Fields you want in your Record
                                    e.g. select CustName, CustNum from ...

                               Заметим: что символ  * выбирает Все Поля в БД
                                            например,  select * from ...

                            -C - это имя БД
                                    например,  select * from Customers.db

                            -D - это Поле, по которому вы хотите отбирать данные
                                    например, select * from Customers.db where CustNum>100 ...

                            -E - это Поле, по которому вы хотите сортировать данные
                                    например, select * from Customers.db where CustNum>100 order by CustName

    Используя  SQL вы можете делать ЗАМЕЧАТЕЛЬНЫЕ вещи.


ВНИМАНИЕ:
    Вы должны быть очень и очень внимательны при написании вашего  SQL запроса.  Это неограниченное поле для ошибок.
    Кавычки (" и ') должны использоваться корректно.
    Имена , которые совпадают с зарезервированными словами  SQL, должны быть заключены в кавычки.
        например,  select "Index" from Parts.db    

 Ваше поле, названное  Index совпадает с зарезервированным словом  SQL (Index)


Давайте напишем событие  ButtonClick Event , в котором выполняется некоторый запрос SQL

     Q1 : TQuery;

procedure TForm1.SQLBtnClick(Sender: TObject);
begin
  Q1.Close;
  Q1.SQL.Clear;
  XStr:='select * from Customer.db where CustNo>1000';
  Q1.SQL.Add(XStr);
  Q1.Open;
end;


Frank's стиль:

    Я  НЕ ИСПОЛЬЗУЮ  параметры в  SQL, они немного загадочны по своей структуре и я не вижу в них необходимости .
    Таким образом, я строю все мои запросы  SQL как строки, показанные выше.


Пока это все.

Frank




Возврат в список переводов

 Lesson 1
 Lesson 2
 Lesson 4