Планирование базы данных
Компонент TBatchMove
Этот компонент обеспечивает копирование данных из одной таблицы в другую. Основные свойства: Source - таблица (или запрос), откуда копируются данные, Destination - таблица, куда копируются данные, Mapping - определяет соответствие между колонками исходной и результирующей таблиц (для идентичных таблиц это свойство определять не обязательно), Mode - тип перемещения (batAppend - добавляет новые строки в результирующую таблицу, batUpdate - заменяет строки в результирующей таблице на соответствующие строки оригинала, batCopy - копирует строки в результирующую таблицу, переписывая ее, batDelete - удаляет записи в результирующей таблице, соответствующие записям оригинала), KeyViolTableName и ProblemTableName - имена дополнительных таблиц для помещения записей, чье копирование запрещено правилами ссылочной целостности или по каким-либо причинам невозможно (например, из-за несоответствия типов данных), ChangedTableName - имя таблицы для помещения измененных записей.
Копирование происходит при выполнении метода Execute. Отметим, что этот метод может быть вызван непосредственно из среды разработки с помощью контекстного меню компонента TBatchMove.
Чаще всего подобное копирование используется при смене сервера баз данных или при переносе desktop-приложения в архитектуру клиент/сервер. В этом случае возможно выявить нарушения ссылочной целостности в исходных таблицах и при необходимости отредактировать данные, связав с компонентами TTable управляющие элементы через соответствующие компоненты TDataSource. Пример подобного применеия этого компонента был приведен в предыдущей статье данного цикла.
| |
Компонент TDatabase
Обычно при разработке приложений, использующих базы данных, с помощью утилит конфигурации BDE создаются псевдонимы (алиасы), указывающие на тип и местоположение данных. Компоненты типа TTable, TQuery, TStoredProc обладают свойством DatabaseName, при установке которого на этапе проектирования можно выбрать необходимый псевдоним из выпадающего списка или явно указать каталог, в котором располагаются плоские таблицы. Однако нередко бывает необходимо создать псевдоним динамически, или переопределить какие-либо параметры настройки драйвера базы данных (например, языковый драйвер, размер буферов, параметры кэширования структур таблиц на рабочей станции) для конкретного приложения без модификации файла конфигурации BDE. В этом случае обычно используется компонент TDatabase, помещаемый явно на форму или в модуль данных. Если определить свойство DatabaseName этого компонента, оно появится в списке псевдонимов при установке свойства DatabaseName компонентов TTable, TQuery, TS toredProc.
Отметим, что, если не поместить компонент TDatabase на форму (или в модуль данных), он в любом случае будет создан на этапе выполнения в процессе создания формы или модуля данных. Дело в том, что именно этот компонент отвечает за взаимодействие с Borland Database Engine, и поэтому его создание инициируется компонентами TTable, TQuery, TStoredProc, если таковые присутствуют в создаваемых на этапе выполнения формах или модулях данных.
Для динамического создания псевдонима следует поместить компонент TDatabase на форму или в модуль данных и выбрать опцию Database Editor из контекстного меню этого компонента (рис.4).

Рис.4. Компонент TDatabase в модуле данных
В редакторе свойств Database Editor (рис.5) можно выбрать либо имя существующего (т.е. описанного в файле конфигурации BDE или созданного с помощью другого, созданного ранее, компонента TDatabase) псевдонима базы данных, либо явно указать драйвер БД и переопределить параметры доступа к базе данных. Нажатие на кнопку Defaults приводит к внесению всех параметров и их значений, характерных для данного псевдонима (или данного драйвера, если указан драйвер БД), в список Parameter Overrides, и затем можно внести в него изменения. Если снять отметку с флажка Login prompt, можно подавить появление диалога ввода пароля пользователя (что иногда бывает полезно при отладке приложений, а также в случае, когда требования к безопасности данных невысоки по сравнению с требованиями к производительности работы пользователя). Опция Keep inactive connection указывает, сохранять ли соединение с базой данных, если пользователь закрыл все таблицы. Если эта опция выбрана, при закрытии и последующем повторном открытии таблиц пользователь должен заново регистрироваться на сервере.
Отметим, что переопределить параметры псевдонима базы данных можно также и с помощью инспектора объектов - они содержатся в опубликованных свойствах компонента TDatabase(рис.6).

Рис. 5. Редактор свойств компонента TDatabase
Помимо переопределения параметров псевдонимов или создания новых псевдонимов компонент TDatabase нередко используется для минимизации числа обращений к серверу. Как было сказано выше, компоненты TTable, TQuery и TStoredProc инициируют динамическое создание компонента TDatabase, если он в явном виде не присутствует в форме или модуле данных. Соответственно каждый раз, когда в процессе выполнения приложения создается новая форма, пользователь получает диалог ввода имени и пароля, и, что не менее существенно, происходит обращение клиентского приложения к серверу баз данных с целью выяснения существования такого пользователя, правильности его пароля, а также его прав на таблицы и иные объекты базы данных посредством вызовов функций BDE, обращающихся, в свою очередь, к функциям прикладного программного интерфейса клиентской части соответствующего сервера. Чтобы избежать этой ситуации, на форму или в модуль данных, создаваемый при запуске приложения, помещается компонент TDatabase (или несколько компонентов TDatabase, если приложение использует несколько различных баз данных), и свойство DatabaseName всех компонентов TTable, TQuer y , TStoredProc устанавливается равным не имени соответствующего псевдонима, а имени соответствующего компонента TDatabase.

Рис.7. Связь компонента TTable с компонентом TDatabase
Из других параметров серверных баз данных, которые можно переопределить с помощью компонента TDatabase, весьма важным является параметр SQLPassThruMode, определяющий, каким образом завершаются транзакции (т.е. согласованные изменения в нескольких таблицах базы данных), инициированные компонентами TTable и TQuery, и могут ли они использовать общие соединения с базой данных. Возможные значения этого параметра - NOT SHARED, SHARED AUTOCOMMIT и SHARED NOAUTOCOMMIT.
При использовании значения NOT SHARED для компонентов TQuery и компонентов TTable создаются отдельные соединения с базой данных, что позволяет избежать возможных конфликтов и непредсказуемых результатов обновлений данных в ряде случаев (например, при попытке обновления одной и той же записи с помощью методов TTable и с помощью SQL-запроса на обновление данных, инициированное компонентом TQuery).
Наиболее эффективным с точки зрения минимизации соединений с базой данных значением этого параметра в большинстве случаев является значение SHARED AUTOCOMMIT. При использовании этого значения изменения каждой записи в таблицах немедленно фиксируются сервером независимо от того, к какому классу (TTable или TQuery) принадлежит компонент, их инициировавший, при этом компоненты обоих классов могут использовать общие соединения с базой данных.
Третье возможное значение этого параметра - SHARED NOAUTOCOMMIT. В этом случае компоненты TTable и TQuery могут также использовать одно и то же соединение с базой данных, но без завершения транзакций после редактирования каждой записи, но контроль за завершением транзакций следует осуществлять в клиентском приложении.
Свойство Transisolation компонента TDatabase определяет уровень изоляции транзакций разных пользователей друг от друга. Предположим, в процессе транзакции требуется использовать значение, хранящееся в поле какой-либо таблицы, например, для проведения расчетов. С момента начала транзакции это значение может быть изменено другим пользователем, поэтому в общем случае неочевидно, какое именно значение будет использовано - реально существующее в базе данных на момент, когда оно было затребовано, или то, которое существовало на момент начала транзакции.
Значение свойства Transisolation, равное tiDirtyRead, применяется, если в этой ситуации используются самые последние данные, независимо от того, завершил ли изменившую их транзакцию другой пользователь. В этом случае существует потенциальная опасность использовать данные, реально не сохраненные в базе данных, если другой пользователь выполнил откат транзакции. Отметим, что не все серверные СУБД поддерживают такой режим.
Значение tiReadCommitted применяется, если нужно использовать последнее значение на тот момент, когда оно затребовано, но только после того, как изменивший его пользователь завершил транзакцию. Этот режим поддерживается большинством серверных СУБД.
Значение tiRepeatableRead полностью изолирует транзакцию от вмешательства других пользователей. При его применении в течение всей транзакции используются одни и те же данные, существовавшие на момент начала транзакции, независимо от того, изменялись ли они другими пользователями. Такой режим может создать проблемы при высокой интенсивности транзакций. Представим себе, например, систему продажи авиабилетов, когда оба оператора одновременно получают данные о том, что данное место свободно , и продают два билета на одно место. В приложениях подобного рода не рекомендуется использовать значение tiRepeatableRead.
Повлиять на выполнение серверных транзакций можно также путем кэширования внесенных пользователем изменений вместо попытки немедленного сохранения их в базе данных, установив равным true значение свойства Cached Updates компонента TTable или TQuery. В этом случае накопленные в локальном кэше изменения пересылаются на сервер с помощью метода ApplyUpdates() компонента TTable или TQuery.
Кэширование изменений полезно по многим причинам. Во-первых, такой метод ввода данных снижает нагрузку на сеть, так как взаимодействие клиента с сервером происходит не постоянно, как в случае непосредственного редактирования таблиц на сервере, а эпизодически. Во-вторых, если сохранение кэшированных данных на сервере не удалось, например, из-за блокировок обновляемых записей другими пользователями, этот метод возвращает значение false, но при этом изменения сохраняются в кэше, что позволяет повторить попытку сохранения данных позже либо внести в изменяемые данные необходимые коррективы. Изменения также можно отменить с помощью метода CancelUpdates().
Отметим, что выполнение метода ApplyUpdates инициирует транзакцию на сервере, которая завершается после внесения всех изменений из кэша в базу данных, и лишь после успешного ее завершения внесенные данные удаляются из кэша. Поэтому до выполнения метода ApplyUpdates серверные данные остаются неизмененными, что позволяет, если этого требует логика клиентского приложения, проанализировать потенциальные изменения, внести в них коррективы и лишь затем сохранить их в базе данных.
Рассмотрим простейший пример применения компонента Database и кэширования данных. Для этой цели скопируем на сервер ORACLE 7 таблицу CLIENTS.DBF из входящей в комплект поставки C++Builder базы данных DBDEMOS (например, с помощью утилиты Data Migration Wizard) и создадим приложение для ввода данных в нее (рис. 8):

Рис. 8 Приложение для ввода данных в таблицу ORACLE
Значения свойств компонентов созданного приложения приведены в таблице 1. Особо отметим, что свойство CachedUpdates компонента Table1должно иметь значение true.
Таблица 1.
| Компонент | Свойство | Значение |
| Database1 | DatabaseName | my_database |
| Params | SERVER NAME=ORA USER NAME=USER1 NET PROTOCOL=TNS OPEN MODE=READ/WRITE SCHEMA CACHE SIZE=8 LANGDRIVER=ancyrr SQLPASSTHRU MODE=SHARED AUTOCOMMIT SCHEMA CACHE TIME=-1 MAX ROWS=-1 BATCH COUNT=200 ENABLE SCHEMA CACHE=FALSE SCHEMA CACHE DIR= ENABLE BCD=FALSE ENABLE INTEGERS=FALSE LIST SYNONYMS=NONE ROWSET SIZE=20 BLOBS TO CACHE=64 BLOB SIZE=32 PASSWORD=u | |
| Table1 | Active | true |
| CachedUpdates | true | |
| DatabaseName | my_database | |
| TableName | CLIENTS | |
| DataSource1 | DataSet | Table1 |
| DBGrid1 | DataSource | DataSource1 |
| DBNavigator1 | DataSource | DataSource1 |
| DBImage1 | DataSource | DataSource1 |
| DataField | IMAGE | |
| LoginPrompt | false | |
| Button1 | Caption | Сохранить |
| Button2 | Caption | Отменить |
| Button3 | Caption | Выход |
//--------------------------------------------------------------------------- #include
При выполнении метода Post компонента Table1 новые записи накапливаются в кэше, а изменений в таблице, хранящейся на сервере, не происходит, что можно проконтролировать, например, с помощью утилиты Database Explorer. При нажатии на кнопку "Сохранить" внесенные записи переносятся на сервер, что также можно проконтролировать, перечитав редактируемую таблицу (рис.9):

Рис.9. Перенос содержимого кэша на сервер
| |
Компонент TSession
Компонент TSession автоматически создается при запуске приложения. Необходимость его явного использования может возникнуть только при создании многопоточных приложений с базами данных (например, когда в одном потоке выполняется длительный запрос, а в другом в это время производится ввод данных в кэш) . В этом случае число компонентов TSession равно числу потоков. Помимо этого, компонент TSession может быть использован для определения на этапе выполнения списка и параметров драйверов и псевдонимов или списка хранимых процедур.
Основные свойства этого компонента: Databases - массив активных компонентов TDataBase, SessionName - имя сеанса. Основные методы: GetDatabaseNames, GetAliasNames - возвращают списки драйверов и псевдонимов, GetAliasParams - возвращает параметры для данного псевдонима, GetDriverNames - возвращает имена доступных драйверов BDE, GetTableNames и GetStoredProcNames - возвращает список таблиц базы данных.
| |
Компонент TStoredProc
Компонент TStoredProc используется для выполнения из приложений C++ Builder хранимых процедур, содержащихся на серверах баз данных. Хранимая процедура представляет собой скомпилированную программу на процедурном расширении языка SQL, характерном для выбранного сервера. Хранимые процедуры могут возвращать наборы данных, основанные на выполнении запроса, если такие процедуры поддерживаются выбранным сервером (в этом случае TStoredProc может использоваться так же, как TQuery, и, так как при этом не требуется компиляция запроса сервером, использование TStoredProc может повысить производительность выполнения выбора данных), могут возвращать числовые параметры (в этом случае эти параметры можно использовать в приложении) и могут ничего не возвращать, а выполнять какие-либо действия на сервере баз данных. Хранимые процедуры также могут иметь входные параметры, передаваемые им из клиентского приложения.
Основные свойства компонента TStoredProc: DatabaseName - имя (alias) базы данных, в которой содержится данная процедура, StoredProcName - имя хранимой процедуры, Params (массив компонентов TParams) - параметры хранимой процедуры, а также ряд свойств, унаследованных от TDataS e t: Active, Fields, Eof, Bof, State и др. Основные методы: ExecProc - выполняет хранимую процедуру, ParamByName - возвращает параметр, используя его имя. TStoredProc обладает также рядом методов, унаследованных от TDataSet: Append, AppendRecord, Close, Ope n , Delete, Edit, Post и т.д.
Рассмотрим простейший пример использования хранимой процедуры. Для этой цели воспользуемся локальным сервером InterBase, входящим в комплект поставки C++ Builder. Создадим новый проект, на главную форму которого поместим компонент TStoredProc, четыре компонента TEdit и компонент TButton. Установим значение свойства DatabaseName компонента StoredProc1 равным IBLOCAL (этот псевдоним демонстрационной базы данных Employee.gdb создается автоматически при установке сервера InterBase). Далее щелкнем на колонке значений напротив свойства StoredProcName, после чего на экране должен появиться стандартный диалог для ввода имени пользователя и пароля (рис.1):

Рис.1. Диалог регистрации пользователя
По умолчанию при установке InterBase системный администратор базы данных имеет имя SYSDBA и пароль MASTERKEY (в дальнейшем его можно изменить).
После соединения с сервером (он должен перед этим быть запущен) напротив имени свойства StoredProcName появится выпадающий список имеющихся в базе данных хранимых процедур. Выберем для примера процедуру ORG_CHART, присваивающую своим выходным параметрам значения одной из записей хранящейся на сервере таблицы. Выбрав свойство Params, можно просмотреть параметры хранимой процедуры с помощью соответствующего редактора свойств (рис. 2).

Рис.2. Редактор свойства Params компонента TStoredProc.
Создадим обработчик события OnClick для кнопки Button1:
void __fastcall TForm1::Button1Click(TObject *Sender) { StoredProc1->ExecProc(); Edit1->Text=StoredProc1->Params->Items[0]->AsString; Edit2->Text=StoredProc1->Params->Items[1]->AsString; Edit3->Text=StoredProc1->Params->Items[2]->AsString; Edit4->Text=StoredProc1->Params->Items[3]->AsString; Edit5->Text=StoredProc1->Params->Items[4]->AsString; }
После компиляции и запуска приложения нажатие на кнопку инициирует запуск хранимой процедуры и вывод ее параметров в соответствующие компоненты Edit1...Edit5 (рис.3).

Рис.3. Результаты выполнения хранимой процедуры ORG_CHART.
|
Компонент TUpdateSQL
TUpdateSQL предназначен для модификации данных на сервере с помощью заранее подготовленных SQL-предложений. Он позволяет определить различные операторы SQL для удаления, вставки и модификации записи, в том числе отличные от простых операторов DELETE, INSERT, APPEND. Эти операторы SQL содержатся в свойствах DeleteSQL, InsertSQL, ModifySQL соответственно.
Имя компонента TUpdateSQL может быть значением свойства UpdateObject какого-либо компонента TDataSet (например, TTable или TQuery). Если в этом случае используется кэширование данных, то в процессе выполнения транзакции, инициированной применением метода ApplyUpdates компонента TDataSet при попытке вставки, удаления или изменения записи генерируется SQL-запрос, содержащийся в свойстве InsertSQL, DeleteSQL или ModifySQL соответственно. Эти свойства можно редактировать, выбрав пункт UpdateSQL editor из контекстного меню компонента TUpdateSQL. Если же кэширование не используется, соответствующие SQL-запросы генерируются при выполнении метода Post компонента TDataSet.
Отметим, что эти три свойства поддерживают специальное расширение SQL, обеспечивающее возможность использования в запросах значений полей, существовавших до начала выполнения транзакции, переносящей на сервер данные из кэша (обычно это требуется при создании предложения WHERE в SQL-запросах). Такие значения полей обозначаются следующим образом: префикс "OLD_" + <имя поля>.
На этапе выполнения в процессе сохранения какой-либо записи на сервере компонент TUpdateSQL выбирает один из трех описанных в его свойствах запросов в соответствии со значением свойства UpdateKind компонента TDataSet, пересылает параметры запроса на сервер и выполняет запрос с целью фиксации на сервере данного обновления.
Для управления каждым отдельным обновлением внутри транзакции, переносящей данные из кэша на сервер, можно использовать событие OnApplyUpdate соответствующего компонента TDataSet, а также параметры UpdateKind (тип обновления) и UpdateAction, которому должно быть присвоено значение uaApplied, если обновление было успешным. Если установить значение этого параметра равным uaSkip, данная запись в кэше будет проигнорирована и не перенесена на сервер.
Для изучения поведения TUpdateSQL внесем изменения в уже созданное приложение, заменив компонент Table1 на компонент TQuery и добавив на форму один компонент TUpdateSQL и компонент TCheckBox. Свойства этих компонентов изменим следующим образом (табл.2):
Таблица 2
| Query1 | Active | true |
| CachedUpdates | true | |
| UpdateObject | UpdateSQL1 | |
| SQL | Select * from clients | |
| DataSource1 | DataSet | Query1 |
| CheckBox1 | Caption | Использовать кэширование |
| UpdateSQL1 | ModifySQL | update CLIENTS set LAST_NAME = :LAST_NAME, FIRST_NAME = :FIRST_NAME, ACCT_NBR = :ACCT_NBR where LAST_NAME = :OLD_LAST_NAME and FIRST_NAME = :OLD_FIRST_NAME and ACCT_NBR = :OLD_ACCT_NBR |
| DeleteSQL | delete from CLIENTS where LAST_NAME = :OLD_LAST_NAME and FIRST_NAME = :OLD_FIRST_NAME and ACCT_NBR = :OLD_ACCT_NBR | |
| InsertSQL | insert into CLIENTS (LAST_NAME, FIRST_NAME, ACCT_NBR) values (:LAST_NAME, :FIRST_NAME, :ACCT_NBR) |
Cтандартные SQL-запросы для добавления, удаления и изменения записи наиболее удобно создавать с помощью UpdateSQL editor, выбранного из контекстного меню компонента UpdateSQL1 (рис. 10)

Рис.10. UpdateSQL editor
Добавим в запрос вычисляемое поле STATUS для отображения состояния записи в кэше, уберем часть полей из списка отображаемых колонок DBGrid1, внесем изменения в существующие обработчики событий и добавим несколько новых (для события OnCalcField компонента Query1 и для события OnClick компонента CheckBox1):
//--------------------------------------------------------------------------- #include
} //--------------------------------------------------------------------------- void __fastcall TForm1::Query1CalcFields(TDataSet *DataSet) { AnsiString UpdStr[] = {"Не изменялась", "Изменена", "Добавлена", "Удалена"}; if (Query1->CachedUpdates) Query1STATUS->Value=UpdStr[Query1->UpdateStatus()]; } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox1Click(TObject *Sender) { Query1->CachedUpdates=CheckBox1->Checked; } //---------------------------------------------------------------------------
Если перед запуском приложения запустить утилиту SQL Monitor, то можно пронаблюдать, как генерируются запросы, содержащиеся в свойствах компонента UpdateSQL1, при использовании кэширования и без него, а также как отображается состояние конкретной записи при использовании кэширования (рис.11):

Рис.11. Приложение с использованием UpdateSQL
Отметим, что свойства DeleteSQL, InsertSQL, ModifySQL компонента TUpdateSQL могут содержать более сложные запросы, нежели сгенерированные автоматически в его редакторе свойств, в соответствии с логикой содержащего его приложения.
|
Определение цели использования
Определение цели использования
Разработка структуры базы данных может стать серьезным испытанием, которого пытаются избежать многие пользователи, о чем непременно сожалеют впоследствии. Лишь некоторые, наиболее талантливые и одаренные специалисты пропускают этот этап, умудряясь создавать эффективные приложения базы данных. Даже если представленные в этой главе сведения вам не покажутся интересными, не забывайте, что разработка структуры базы данных — очень важная задача.
Итак, если вместо того, чтобы сваливать все объекты в одну кучу, вы примете решение о планировании базы данных, следует составить и записать небольшой план. Не стоит уделять ему чрезмерного внимания и тратить много сил, достаточно и одного предложения, например такого: «Хранение и анализ данных о состоянии шелковичных червей в предверии похолодания». По окончании планирования первичную задачу, возможно, понадобится слегка изменить, но сама цель останется неизменной — наметить основу базы данных.
Мы же с вами будем работать над созданием базы данных для хранения информации о садоводстве. В частности, речь пойдет о цветах, растениях и овощах. Эта база данных будет применяться при изложении всего оставшегося материала книги, однако в каждой главе она будет приобретать новые черты и функции, поэтому структура базы данных будет меняться в соответствии с определенными требованиями.
Планирование таблиц
h1>Таблица — это набор взаимосвязанных данных, размещенных в столбцах и строках. Термин реляционная база данных означает, что данные хранятся в нескольких связанных между собой таблицах.
В каждой из таких таблиц содержатся данные определенной категории — тематический набор данных одного типа. Другими словами, для данных каждой категории понадобится отдельная таблица (вообще-то все несколько сложнее, но на настоящем этапе такое определение вполне подходит).
Как вы уже знаете, таблица состоит из столбцов и строк (рядов). Столбец содержит поле — наименьшую единицу данных. Все поля вместе взятые составляют запись, а одна запись, в свою очередь, содержит данные для одной категории.
Звучит не очень-то понятно, не правда ли? Но не беспокойтесь, со временем ситуация прояснится, а пока что применим оговоренные концепции к создаваемой базе данных, определив категории в представленном ранее списке.
Изначально у нас имеется две категории — информация по каждому растению и данные каталога. Таким образом, получаем следующую таблицу.
Планирование возможных вариантов форм
Планирование возможных вариантов форм
Приступая к созданию собственно приложения базы данных, необходимо закончить разработку таблиц. Следующий шаг заключается в добавлении ряда объектов, которые понадобятся при обработке данных. В первую очередь стоит подумать о возможности использования форм для просмотра данных и манипуляции ими. Пока что будет достаточно одной-двух таких форм.
Далее нам необходимо пересмотреть все бумажные носители информации и проанализировать их эффективность. Быть может, стоит продолжать использовать базовую структуру форм, основанную на бумажных записях, или же придумать более эффективную и рациональную структуру отображения информации. Тот факт, что данные уже записываются тем или иным способом, вовсе не означает, что этот способ нельзя усовершенствовать.
Для ввода, удаления и изменения данных рекомендуется применять формы. Хотя эти операции можно выполнять непосредственно в таблицах, не стоит рисковать. Более тoro, нужно запретить пользователям доступ к таблицам, на основе которых создаются формы.
Мы все еще продолжаем делать наброски с помощью ручки и бумаги, поэтому пока что не следует создавать формы в Access. Когда таблицы готовы, можно переходить к разработке прототипа форм с помощью специального мастера, о котором речь пойдет в главе 8, «Создание и использование форм данных».
Сейчас же вернемся к структуре базы данных и ч подумаем, какие еще формы могут нам понадобиться. Необходимо определить наиболее эффективный метод добавления новых каталогов о растениях, а также метод изменения списка типов.
Возможно, имеет смысл создать форму, отобража10-щую поля из более чем одной формы. По сути, речь идет о создании подформы — одной формы, вложенной в другую. Например, разве не удобно было бы просматривать информацию о каталоге и данные о приобретенных семенах из каждого каталога? Или же просматривать информацию из каталога и вводить данные о семенах растений, еще не указанных в базе данных?
Запрет на использование таблиц и доступ к ним позволит обеспечить целостность данных, ведь с помощью таблицы пользователь может обойти запреты, которые были принятые с целью сохранения корректности и актуальности данных.
Формы, показанные на рис. 4.6, предоставляют нам массу возможностей. Правда, они созданы самой Access, поэтому, пока мы еще не научились это делать, можно обойтись ручкой и бумагой.
Планирование возможных вариантов отчетов
Планирование возможных вариантов отчетов
Разработка структуры отчетов выполняется примерно по той же схеме, что и аналогичная процедура для форм. Различие между этими процессами обуславливается тем, что отчеты можно распечатать на бумаге, в то время как с формами работают на экране компьютера. Если у вас уже есть готовые отчеты, положите их рядом — возможно, они понадобятся в дальнейшем. Как правило, все приложения баз данных, за небольшим исключением, генерируют один или два отчета.
В отчетах подытоживается информация о содержимом приложения базы данных, и очень часто на их основе производят модификацию базы. Например, база данных растений позволит сгенерировать отчеты, которые можно сохранить и использовать в дальнейшем для просмотра состояния сада в определенное время года.
Какие сведения из базы данных растений нам потребуется распечатать? Быть может, это будет список растений или адреса компаний, поставляющих семена.
Приятное впечатление всегда производит отчет с картинками - он очень пригодится на этапе планирования.
При желании сведения, аналогичные указанным на рис. 4.8, можно распечатать для всех растений, отсортированных по их латинским именами. Этот отчет будет помещен в папку с аналогичными документами. Отчет, представленный на рис 4 9 понадобится для планирования процесса разбивки сада на участки. Много полезной информации о работе с отчетами содержится в главе 9, «Печать информации с помощью отчетов» и в главе 14, «Настройка отчетов».
Правило 1
Это правило гласит, что каждый элемент данных (поле) должен иметь наименьший размер. Оно использовалось ранее, при создании таблицы растений, однако едва ли может быть применено к таблице каталога. Хранение адреса в одном поле — неподходящее решение, оно нарушает первое правило.
Как известно, адрес состоит из нескольких составляющих: названия улицы, города и области, почтового индекса, а иногда еще и названия страны. Следовательно, поле адреса обычно содержит не менее пяти блоков данных.
Зачем же нужно разделять даже адрес? Дело в том, что работать с различными блоками данных в одном поле крайне неудобно. Предположим, вам понадобилась информация из определенного каталога, однако вспомнить его название никак не удается. Вы лишь припомнили, что издательство, выпустившее каталог, находится в Ленинградской области. Если запись о Ленинградской области содержится где-то посередине поля, между записями о Москве и России, найти ее будет непросто. С другой стороны, если создать отдельное поле для Ленинградской области, нужную запись останется поискать лишь в нем. Итак, изменяем таблицу каталога следующим образом.
| Каталоги |
|
Имя |
|
Улица |
|
Город |
|
Область |
|
Почтовый индекс |
|
Страна |
|
Специализация |
Правило 2
Второе правило гласит: в одном поле нельзя хранить более одного блока данных. С помощью полей определены три типа растений: декоративные, пищевые (т.е. употребляемые в пищу) и лечебные. Но что если эти типы будут повторяться, ведь некоторые растения одновременно относятся и к декоративным, и к лечебным, однако более одного типа данных в одном поле размещать нельзя. Эта задача решается путем создания новой таблицы для каждого типа данных, после чего получим две таблицы (без таблицы каталогов).
| Растения |
Типы |
| Имя |
Тип |
| Латинское имя |
  |
| Заметки |
  |
| Фотография |
  |
В дальнейшем мы соединим таблицы между собой и укажем, какой тип относится к какому растению, а пока что ограничимся разделением данных.
Правило 3
В базе данных будут храниться сведения о семенах свеклы или, предположим, петунии и о многом другом. Как при этом отличать одно растение от другого? Каждое растение обладает определенной характеристикой. Уникальная информация в терминах баз данных называется первичным ключом. А третье правило гласит, что каждая таблица должна содержать первичный ключ.
Поле первичного ключа содержит значение, уникально идентифицирующее каждую запись, причем это значение не может равняться нулю (а также быть пустым и иметь неопределенное значение). Выбирая первичный ключ таблицы, необходимо руководствоваться такими правилами.
- Для уникального определения каждой записи следует использовать хранящуюся в ней информацию. Одно или больше полей данных могут изначально быть уникальными для каждой записи. Такой тип первичного ключа называется натуральным.
- Можно добавить поле типа данных с автоматической нумерацией. Использование этого типа данных позволяет Access автоматически вводить последовательное значение для каждой записи. Например, значение первой записи первичного ключа будет равно 1, второй — 2, третьей — 3 и т.д. Такой тип ключа считается искусственным.
На рис. 4.4 схематически показано различие между указанными типами ключей.
Предназначение Access
Предназначение Access
По сути, Access — это всего лишь инструмент, как молоток или, скажем, отвертка. Его использование, конечно же, делает наш труд, а следовательно, и нашу жизнь немного легче. Но стоит забыть, для чего он нужен и как им пользоваться, и тут же можно запросто получить по рукам. Поэтому помните, что и база данных должна служить для выполнения четко оговоренных задач — лишь при этом условии она поможет повысить эффективность вашей работы вне зависимости от того, о каком виде деятельности идет речь.
Однако возможности базы данных не ограничиваются хранением информации. Профессионально разработанная база позволяет сохранить достоверность данных и обеспечить эффективный, быстрый и удобный доступ к ним. В такой базе не будет места для беспорядка и путаницы.
Предварительное планирование на бумаге
Предварительное планирование на бумаге
Нам необходимо определить задачи, для выполнения которых создается база данных. Нужно в точности знать, какие именно данные будут содержаться в базе и какие действия будут с ними производиться.
Невозможно создать базу данных, не имея понятия о том, что в ней будет храниться. Людям, привыкшим к беспорядочным записям в блокноте, записывающим все подряд в таблицу Excel, возможно, понадобится научиться разделять различные типы информации. В случае с базой данных, посвященной садоводству, необходимо выбрать наиболее важные аспекты, относящиеся к этой теме.
Прежде чем приступить к созданию базы данных, стоит собрать под рукой все книги, журналы и каталоги семян, в которых могут содержаться интересные сведения. Возможно, список каталогов уже готов (рис. 4.1). В таком случае пора приступать непосредственно к планированию базы данных.
Это еще не база данных, но начало уже положено!
Рис. 4.1. Это еще не база данных, но начало уже положено!

Уже существующий дневник может стать подспорьем при планировании базы данных
Рис. 4.2. Уже существующий дневник может стать подспорьем при планировании базы данных

В базе данных Access могут храниться фотографии
Рис. 4.3. В базе данных Access могут храниться фотографии

| Растения |
Каталоги |
| Имя |
Название |
| Латинское имя |
Адрес |
| Тип |
Специализация |
| Заметки |
  |
| Фотография |
  |
На данном этапе Access не применяется, а мы пока что решаем, какие еще таблицы и поля следует создать. Более подробно о формировании таблиц рассказывается в главе 5, «Создание первых таблиц».
Скорее всего, порядок представления данных в таблицах 2 будет отличаться от того, который на бумаге. Информация, приведенная на рис. 4.2, будет со временем разнесена по нескольким таблицам.
Поздравляем! Вы сделали первые шаги на пути организации данных. Немалая часть книги посвящена разделению данных на отдельные таблицы — этот процесс называется нормализацией или упорядочением. Пока что не стоит забивать голову лишними деталями. По мере изучения Access станет понятным, что планирование базы данных зависит в первую очередь от целесообразности выполняемых действий.
Вместо того, чтобы зазубривать технические параметры структуры базы данных, обратите внимание на следующие правила, которыми следует руководствоваться в процессе разработки собственных баз данных:
- правило 1 — разделяйте данные на наименьшие однотипные элементы;
- правило 2 — не храните два элемента в одном месте;
- правило 3 — указывайте уникальные характеристики каждого элемента базы данных.
Не зацикливайтесь на изначальной структуре базы данных. Для достижения наилучших результатов нам придется еще не раз ее менять.
Натуральные и искусственные ключи
h1>Таблица типов растений имеет только одно поле. Таблицы такого рода, как правило, считаются справочными, поскольку с их помощью ищутся значения для данных, связанных с другой таблицей. В нашем случае таблица типов стала справочной по отношению к таблице растений. Справочную таблицу можно оставить без изменений (сделав основное поле первичным ключом или добавив поле автонумерации). Выберем второй вариант и сделаем поле автонумерации первичным ключом. Теперь список таблиц выглядит так, как показано далее, причем каждая таблица содержит несколько полей (первичный ключ обозначается как ПК):
- растения — имя, латинское имя (ПК), заметки, фотография;
- каталоги — имя (ПК), улица, город, область, почтовый индекс, страна, специализация;
- типы — тип (ПК), описание.
Интересно, каким образом таблица растений «узнает» о том, какой тип к какому растению относится или в каком каталоге содержатся сведения о семенах моркови? Это возможно лишь при наличии связей. Взаимосвязь — это, как понятно из названия, связь между таблицами. Принцип взаимосвязи можно сформулировать с помощью такой фразы: «Каждый каталог содержит информацию о многих растениях» или такой: «Каждое растение обладает типом». Более подробно о связях рассказывается в главе 6, «Использование взаимосвязей».
Связанным между собой таблицам требуется два ключа: первичный и так называемый внешний ключ. Второй, внешний, ключ — это первичный ключ другой таблицы, добавленный в основную таблицу. Сказанное можно пояснить схемой, приведенной на рис. 4.5.
Первичные и внешние ключи
Рис. 4.5. Первичные и внешние ключи

Для иллюстрации метода работы взаимосвязанных таблиц следует добавить необходимые внешние ключи к созданным таблицам.
Ранее поле типов было перенесено из таблицы растений в новую таблицу. Теперь эти две таблицы нужно связать между собой. Для этого поле первичного ключа из таблицы типов необходимо разместить в таблице растений в качестве внешнего ключа (ВК):
- растения — имя, латинское имя (ПК), заметки, фотография, номер типа (ВК);
- типы — тип (ПК), описание.
Выполним аналогичные действия для таблиц растений и каталогов, и у нас появится возможность быстро находить каталог с информацией о нужных семенах. В данном случае добавим первичный ключ с таблицы каталогов — поле Имя — в таблицу растений в качестве внешнего ключа:
- растения — имя, латинское имя (ПК), заметки, фотография, номер типа (ВК), имя каталога (ВК);
- каталоги — имя (ПК), улица, город, область, почтовый индекс, страна, специализация.
Обратите внимание на тот факт, что полю внешних ключей не назначаются имена полей соответствующих первичных ключей. Объясняется это тем, что имена полей не должны совпадать. В таблице каталогов содержится поле Имя, а в таблице растений — поле ИмяКаталога; взаимодействие этих ключей автоматически обеспечивает Access.
Итак, на данный момент содержимое таблиц выглядит следующим образом:
- растения — имя, латинское имя (ПК), заметки, фотография, номер типа (ВК), имя каталога (ВК);
- типы —тип (ПК), описание;
- каталоги — имя (ПК), улица, город, область, почтовый индекс, страна, специализация.
Если с упорядочением данных вам не удалось разобраться, не расстраивайтесь, ведь даже профессионалы зачастую путаются в подобных вопросах. Именно по этой причине Access включает в себя анализатор таблиц — специальную утилиту, позволяющую корректно отсортировать данные. Подробная информация об этой утилите изложена в главе 6.
Формы могут быть основаны на нескольких таблицах
Рис. 4.6. Формы могут быть основаны на нескольких таблицах

Кроме таких форм нам для обновления таблицы типов может понадобиться простая форма ввода данных (рис. 4.7).
Форма, используемая для обновления таблицы типов
Рис. 4.7. Форма, используемая для обновления таблицы типов

Информация о формах и подформах содержится в главе 8, «Создание и использование форм данных», и в главе 13, «Настройка форм».
Отчет с наклейками можно использовать для данных любого типа, не ограничиваясь адресами
Рис. 4.8. Отчет с наклейками можно использовать для данных любого типа, не ограничиваясь адресами

Этот отчет понадобится при разбивке сада на участки
Рис.4.9. Этот отчет понадобится при разбивке сада на участки

Список первоочередных данных
Список первоочередных данных
Пришло время на основе печатных документов, личных заметок и книг по садоводству составить список данных, которые будут храниться и обрабатываться в базе. Пока что можно не следить за порядком их перечисления и размещением — просто создайте этот список. Посмотрим, какая информация о растениях будет представлена в нашей базе данных:
- имя;
- латинское имя;
- вид растения — декоративное, употребляемое в пищу или лечебное;
- общие заметки — проблемы, планы на будущее и т.д.;
- фотография растения;
- названия популярных каталогов семян и адреса издательств.
Не ограничивайте воображение и заносите в список все, что приходит в голову. Возможно, у вас уже есть дневник с записями (рис. 4.2) или список растений. Это существенно упрощает процесс планирования базы данных, так как большая часть работы по отбору нужной информации проделана заранее. Однако не стоит попросту переписывать старые заметки, поскольку так можно упустить важные данные. Внимательно просмотрите имеющиеся сведения и решите, какие из них представляют наибольший интерес. Например, в вашей базе данных могут пригодиться фотографии, сделанные цифровым фотоаппаратом (рис. 4.3).
В поисках данных
В поисках данных
На этом этапе не обязательно досконально знать о возможностях и функциях Access, поэтому сконцентрируем внимание на данных, которые будут храниться в базе. Без их систематизации невозможно продвигаться дальше. К счастью, не так уж сложно разобраться, какие данные представляют наибольший интерес.
Базы данных: Разработка - Управление - Excel
- Базы данных
- Разработка баз данных
- СУБД и базы данных
- Управление базами данных
- Классика баз данных
- Софт для создания базы данных
- SQL
- Access
- FoxProо
- Расширенная оптимизация подзапросов в Oracle
- Informix
- Линтер
- Postgres
- СУБД DB2
- InterBase
- Excel
- Таблицы Excel
- Справка Excel
- Программирование в Excel
- Деньги в Excel
- Задачи Excel