Что такое базы данных?
Итак базы данных существуют следующих видов:
1) Древовидные - простейший пример - Windows Registry, файловая система FAT и XML - здесь информация хранится в древовидной структуре и доступ осуществляется через "путь", т.е. указание всех узлов от корневого до нужного. Например:
"c:\My Docs\MyPictures\Me.jpg". Недостатки этого способа хранения данных является очень медленный поиск, если не известен путь и очень плохая устойчивость к повреждениям структуры. Преимущество - возможность хранить в классифицированном виде очень разнородную информацию и очень быстрый поиск при знании ключа. Эти базы данных мы разбирать здесь не будем.
2) Сетевые базы данных - простейший пример - интернет. Т.е. существуют узлы, обособленные друг от друга, содержащие определённую информацию. Каждый узел представляет какое-то количество ссылок на другие узлы, по которым и ведётся поиск. Недостатки - очень сложный и долгий поиск, возможна неполное предоставление информации или невозможность найти нужную информацию. Преимущества - очень легко добавить любую, разнородную информацию, самая высокая стабильность из всех систем. Эти базы данных мы разбирать здесь не будем.
3) Объектные базы данных - новое веяние. Их мы разбирать здесь не будем, но интересующиеся найдут интересной
дискуссию о них в нашем разделе по базам данных.
4) Реляционные базы данных - именно с ними мы и будем работать. В дальнейшем если говорится "база данных", то подразумевается "Реляционная база данных". "Реляционный" - Relation - обозначает взаимосвязанный. С этими связями мы будем разбираться потом, а пока можно для простоты считать, что реляционная база данных - это набор двумерных простых таблиц. Недостатки реляционных баз данных - хранение только однородной информации, сложности в добавлении новых структур и взаимоотношений, информация хранящаяся в такой БД должна быть в нужной степени абстрагированна.
Преимущества - прежде всего очень высокая скорость поиска - по этому параметру у реляционных баз данных конкурентов нет, высокая стабильность, обилие софта для их поддержки и разработки, удобность для очень широкого круга задач.

Реляционные базы данных?
Итак, Реляционная база данных упрощённо является набором таблиц. Таблица же есть основной строительный кирпичик базы данных. Расмотрим структуру таблицы. Для начала представте себе таблицу, например в Word...
Что в ней есть?
Во-первых есть строки и колонки (raw and columns). В базах данных, в отличие от Word есть строгие ограничения на их содержимое, да и терминология немного другая:
1) Колонка называется тоже columns, но чаще употребляется понятие "поле" (field). Колонка всегда имеет имя (по которому ее можно найти) и обязана хранить данные только одного какого-либо типа - например целые числа, строки, дату/время и
т.п. Создавая таблицу вы обязаны указать какой тип имеет каждое поле, другими словами, вы заранее должны определится, какого сорта данные будут хранится в колонке. Например, вот примерно так может выглядеть структура таблицы для хранения данных об участнике этого форума:
· Ник - строка (25 символов)
· ФИО - строка (250 символов)
· Дата регистрации - Дата/время
· Количество постингов - Целое
· Показывать email - True/False
Обратите внимание что для строк я указал конкретную длину, а для остальных ничего не указывал. Зачем? Ответ прост -
каждая строка должна занимать строго одинаковое место (об исключениях потом), и это сделано для быстроты поиска.
Действительно , если бы каждая строка имела разную длину, то чтобы найти например 1000 строку, надо было бы перечитать все 999 предыдущих строк, но если известно, что каждая строка занимает например 1Кб, то чтобы прочитать 1000 строку достаточно прочитать 1 Кб с 999Кб... Другая сторона этого - например мне надо сравнить даты в приведенной выше таблице - сделать это просто - я точно знаю что первую дату можно прочитать с 276 байта, и так же точно я знаю точные координаты каждой даты. Именно в этом и лежит одна из сторон высокой скорости работы баз данных (другие способы ускорения работы рассмотрим позже).
2) Строка - в базах данных имеет специфическое название - запись (Record) - к Дельфийскому типу Record этот термин не имеет никакого отношения. Хотя большинство БД дают возможность перейти и прочитать например 10 запись, надо с самого начала попытаться никогда этим не пользоваться. Почему? Да просто потому что БД практически всегда подразумевают совместный доступ нескольких пользователей к одним и тем же данным, и если Вы хотите перейти на 10 запись, а другой пользователь в это время удалит запись номер 5, то вы перейдёте вовсе не на ту запись что ожидалось. А как же быть? У вас есть 2 способа - либо вы находите нужную запись по значению поля - например для нашей таблицы это будет выглядеть примерно так:
"Найти пользователя [Вася] в первой колонке"
В результате вы получите доступ ко всем полям записи для "Васи". Либо вы берёте все записи и перебираете их в цикле пока не найдёте нужный - это гораздо худший способ, так как работает на 2-3 порядка медленнее и имеет другие неприятные последствия (об этом позже), но он возможен и иногда применяется.

Первая программа с базами данных?
После небольшого теоретизирования спустимся с небес на землю откроем Дельфи и напишем простейшую программу для баз данных. Напишем, это громко сказано, потому что писать ничего не прийдётся, только компоненты потыкаем.
Открываем новый проект. Открываем форму. Кладём на форму компонент TTable (с закладки "Data Access" или "BDE" - у кого какая версия Дельфей). Оп! Не ожидали - вроде бы и таблица, а компонт не визуальный! Итак компонент TTable - это пока основной компонент для нашей базы - всё обращение к таблице идёт только через него. Теперь давай-те его подсоединим к базе данных.
К Дельфи прилогается учебная база данных, её мы и будем пользовать. Найдите свойство DatabaseName и из выпадающего списка выберите "DBDEMOS" - это и есть учебная база данных. Теперь берём свойство TableName и в выпадающем списке обнаруживаем список имён всех таблиц в базе данных "DBDEMOS", выбираем например "biolife.db" -
это таблица так называется (а в данном случае и название файла)
Всё - таблица подсоединена, и с ней даже можно работать, но только в коде. А мы, как особо ленивые, попробуем на сегодня без кода обойтись, а подключить к таблице грид и другие визуальные компоненты.
Но все визуальные компоненты могут подсоединится к TTable только через вспомогательный компонент TDataSource - находящийся на той же закладке. Ставим и его на форму. Находим свойство DataSet у этого компонента и в выпадающем списке указываем на Table1. Теперь визуальные компоенты будут "видеть" инфу в таблице через TDataSource.
Переходим на другую закладку компонентов - "Data Controls" и ставим компоент TDBGrid. В его свойстве DataSource указываем на DataSource1. Что видим? Пока ничего! Таблица то не открыта - кликаем на Table1 и устанавливаем свойство Active в True. Работает!
Можно программу откомпиллировать и поиграться со своим первым приложением для баз данных. Неправда ли очень просто!

Визуальные компоненты для DB
Итак, мы не написав ни строчки кода получили простейшее приложение, работающее с базой данных. С помощью него мы можем просматривать и редактировать содержимое таблицы. Давайте теперь сделаем эту процедуру немного удобнее, на
закладке "Data Control" есть компонент TDBNavigator. Положим его на форму и в инспекторе объектов поставим его
свойство DataSource указывающим на тот же DataSource1, что и для DBGrid - собственно, теперь оба визуальных контрола(DBGrid и DBNavigator) привязаны к одному и тому же DataSource и через него к одной и той же таблицы.
DBNavigator имеет несколько кнопок (вы можете настроить какие именно вы хотите видеть) дающие лёгкий контроль над следующими операциями:
(перечисление в порядке расположения кнопок)
1) Переход на первую запись
2) Переход на предыдущую запись
3) Переход на следующую запись
4) Переход на последнюю запись
5) Добавить запись
6) Удалить запись
7) Редактировать запись
8) Сохранить изменения
9) Отменить изменения
10) Перечитать таблицу
Обратите внимание, что запись (строка) таблицы есть как бы неделимый квант информации - т.е. отменяются действия произведенные для всей записи целиком, добавляется или удаляется тоже строка целиком.
Разберём ещё несколько визуальных компонентов, чтобы покончить с визуализацией данных и перейти собственно к программированию.
На закладке Data Controls есть ещё несколько важных компонентов, давайте поставим их на нашу форму: DBLabel, DBEdit, DBMemo и DBImage. Все их так же как и DBGrid соединим с DataSource1. Однако здесь мы обнаружим что этого недостаточно, эти компоненты работают с отдельной ячейкой в таблице, поэтому мы должны указать ещё поле (столбец) который они будут показывать.
Давайте сделаем следуюшие - для каждого из этих компонентов укажем свойство DataField, например следующим образом:
DBLabel - ассоциируем с полем Category
DBEdit - ассоциируем с полем Common_name
DBMemo - ассоциируем с полем Notes
DBImage - ассоциируем с полем Graphic
Можно откомпилировать программу и немного поиграться с ней. Итак что мы можем здесь увидеть? Что в каждый данный момент времени из всей таблицы у нас есть запись которая активная (текущая) - в DBGrid она показывается треугольничком слева. Именно с этой единственной записью мы и можем оперировать - удалять, добавлять, редактировать, именно её содержимое отображается в DBLabel, DBEdit, DBMemo, DBImage и именно она может быть изменена при помощи этих компонентов. Описанная только что структура позволяет работать только с одной записью в определённый момент времени, если вы переходите на другую запись то все изменения должны быть либо запомнены либо отменены! По умолчанию они запоминаются без всяких запросов, в чём вы можете убедиться меняя значения и переходя на другую запись.
Поиск нужных данных
Теперь разберём более эффективные способы нахождения нужной записи
в таблице.
А если нам надо перейти к вполне конкретной строке (записи)? Можно конечно
организовать такой цикл и найти нужную запись, но это громоздко, неудобно,
и главное очень медлено! Для этого можно использовать метод таблицы Locate.
Например в нашей задаче нам надо найти запись где в поле Category значение
"Cod". Этого можно добится примерно следующим кодом:

Код:
Table1.Locate('Category','Cod',[loCaseInsensitive]);

Можно "повесить" этот код на кнопку и убедится, что после выполнения этого
кода активная запись стала именно та которая нам и нужна. Итак что же за параметры
мы передаём этому методу? Первый параметер - это имя поля, второй параметер -
это значение поля, третий опции поиска (см. справку Дельфи). А что будет если
такого значения нет? Например:

Код:
Table1.Locate('Category','Cod123',[loCaseInsensitive]);

Ничего не будет, правда метод Locate - это функция и она возвращает значение Boolean
в зависимости от того, найдена запись или нет.
Преобразовав код как

Код:
if Table1.Locate('Category','Cod123',[loCaseInsensitive]) then
showmessage('Record is located seccessful!')
else
showmessage('Record is not found!');

можно убедится, что теперь мы знаем найдена запись или нет. Можно искать и по части
значения, например

Код:
Table1.Locate('Category','Co',[])

не сможет найти запись, а

Код:
Table1.Locate('Category','Co',[loPartialKey])

вполне правильно найдёт запись с значением 'Cod'.
А если нам надо найти значение по двум полям? В этой таблице искать так бесполезно,
так как все поля разные. Переключим таблицу на другую. Для этого удалим с формы
все визуальные компоненты кроме DBGrid и DBNavigator (так как у новой таблицы
будет совсем другой список полей). В коде напишем что-то
типа:

Код:
Table1.active:=false; //закрыли таблицу
Table1.tablename:='items.db';//ассоциируем с новой таблицей на диске
Table1.active:=true; //открыли таблицу

Откомпилируем код, убедимся, что теперь мы видим совсем другую таблицу.
Теперь давайте найдём такую запись, где ItemNo=1 и Discount=50, для этого нам надо
применить Locate следующим образом:

Код:
Table1.Locate('ItemNo;Discount',VarArrayOf([1,50]),[]);

Теперь несколько примечаний:
1) Для Дельфи 6/7 - добавьте "Uses Variants;"
2) Первый параметер - это список имён полей через ; без пробелов
3) Второй параметер - это массив вариант - значений полей. Почему вариант? Потому что
поля могут быть разных типов и в этом массиве вполне можно задать значения
разных типов: VarArrayOf([1,'Вася', True, 3.14])

Изменение данных в таблице
Теперь последний штрих о работе с таблицами. Мы разобрали способы обратиться к нужному столбцу и нужной записи, их поиск и чтение значений. А как записать новое значение? Для этого есть методы Edit, Append, Insert, Post и Cancel.
1) Надо изменить текущую запись.

Код:
Table1.edit; //переводим таблицу в режим редактирования 
Table1.fieldbyname('Category').asString:='New value';//изменяем поле 
Table1.post;//сохраняем изменения

2) Надо добавить новую запись.

Код:
Table1.append; //переводим таблицу в режим добавления новой записи
Table1.fieldbyname('Category').asString:='New value';//присваиваем значение полей 
Table1.post;//сохраняем изменения

Итого, как видим изменения данных производятся точно так же как и чтение, но перед изменением КАЖДОЙ записи таблица должна быть переведена в режим редактирования, а после изменения КАЖДОЙ записи изменения должны быть сохранены.
В режим редактирования таблицу переводят следующие методы:
Edit - редактирование текущей записи
Append - добавление записи в конец таблицы
Insert - вставка записи перед текущей
Для выхода из режима редактирования служат методы:
Post - запомнить изменения и выйти из режима редактирования
Cancel - отменить сделанные изменения и выйти из режима редактирования