Библиотека: А. Горев, С. Макашарипов, Р. Ахаян. Эффективная работа с СУБД
Глава 6 Создание базы данных
- 6.1. Visual FoxPro
- Создание и модернизация структуры базы данных
- Использование словаря данных
- Создание и модернизация структуры таблиц
- 6.2. Access
- 6.3. Visual Basic
- 6.4. MS SQL Server
- Планирование процесса наращивания
Описывая практическую технологию создания БД, мы коснемся основополагаюших принципов работы с данными, используемых в средствах разработки корпорации Microsoft. Поэтому в данной главе мы разделим излагаемый материал,
во избежание путаницы в головах наших читателей, по описываемым в
книге средствам разработки.
6.1. Visual FoxPro
В Visual FoxPro базы данных имеют собственную структуру организации данных и предоставляют дополнительные возможности разработчикам. В
базе данных вы можете использовать расширенное представление данных
на уровне таблиц, например, правила на уровне полей и записей, значения
полей по умолчанию, триггеры. Здесь же вы можете хранить процедуры
и устанавливать постоянные отношения между таблицами. Базы данных
можно использовать для обеспечения доступа к внешним источникам данных
и для создания представлений локальных и внешних таблиц.
В этом параграфе мы рассмотрим:
- визуальные методы создания БД и ее компонентов;
- использование основных команд FoxPro для программного
создания компонентов БД;
- организацию связей между таблицами и использование индексов.
Создание и модернизация структуры базы данных
После того, как вы спроектировали базу данных, ее можно создать
в интерактивном режиме, используя диалоговые средства Visual FoxPro
или команду CREATE DATABASE. Если вы разрабатываете пользовательское
приложение, обязательно создавайте базу данных, используя Project
Manager.
В Project Manager выберите вкладку Data, затем в списке пункт
Databases. Нажмите кнопку New. Откроется Конструктор БД, который показан
на рис. 6.1. На этом же рисунке вы найдете необходимые пояснения
для работы с ним.
Рис. 6.1. Окно и панель инструментов Конструктора БД в Visual FoxPro
Вновь созданная база данных пуста и не содержит никаких таблиц и других объектов.
В табл. 6.1 приведены команды и функции, которые вы можете использовать для программного управления базами данных и их объектами.
Таблица 6.1. Команды и функции, управляющие базами данных и их объектами
ADATABASE() | CREATE VIEW | MODIFY CONNECTION |
ADBOBJECTS() | DBC() | MODIFY DATABASE |
ADD TABLE | DBGETPROP() | MODIFY PROCEDURE |
ALTER TABLE | DBSETPROP() | MODIFY STRUCTURE |
APPEND PROCEDURES | DELETE CONNECTION | MODIFY VIEW |
CLOSE DATABASE | DELETE DATABASE | OPEN DATABASE |
COPY PROCEDURES | DELETE VIEW | PACK DATABASE |
CREATE CONNECTION | DISPLAY DATABASE | REMOVE TABLE |
CREATE DATABASE | INDBC() | SET DATABASE |
CREATE SQL VIEW | LIST DATABASE | VALIDATE DATABASE |
CREATE TABLE |
При создании БД не забудьте, что важной особенностью Visual FoxPro является то обстоятельство, что каждая таблица может существовать
в одном из двух состояний: либо в виде свободной таблицы, представляющей
собой файл DBF, не ассоциированный ни с одной из баз данных, либо
в виде таблицы базы данных - файла DBF, включенного в какую-либо
БД. При этом если таблица включена в БД, то она не может быть включена
ни в какую другую БД. Для таблиц, ассоциированных с базой данных,
можно установить ряд свойств, которыми не могут обладать свободные
таблицы. Это такие свойства, как триггеры, правила на уровне полей
и записей и постоянные отношения между таблицами.
Вы можете включить таблицы в базу данных, создав их внутри открытой базы данных или добавив туда уже существующие таблицы.
Как добавить существующую таблицу в базу данных? В Project Manager
выберите пункт Tables из вкладки Аll или Data, затем выполните команду
Add. Программным путем то же самое можно сделать, выполнив следующие
команды:
- OPEN DATABASE auto_store && Открывается база данных && AUTO_STORE
- ADD TABLE salesman && В нее добавляется таблица SALESMAN
Чтобы сделать таблицу частью базы данных, необходимо явно включить
ее в базу данных. Изменение структуры свободной таблицы не вносит
ее автоматически в базу данных, даже если сделать это при открытой
базе данных с помощью команды MODIFY STRUCTURE.
Не забудьте, что вы можете ассоциировать таблицу только с одной базой данных. Если данные из какой-то таблицы необходимо использовать в
нескольких БД, для исключения дублирования информации наиболее простой
путь - не включать эту таблицу ни в какую БД, а оставить ее
свободной. Данные из существующего файла DBF можно использовать, не
включая его в базу данных. В то же время не представляет труда использовать
информацию и из таблицы, расположенной в другой БД.
Как получить доступ к таблице из другой базы данных? Создайте в базе данных представление, включающее нужную таблицу. Или получите доступ
к таблице с помощью команды USE и разделительного символа
"!". Символ "!" надо использовать для ссылки на таблицу
из другой, не текущей, базы данных. Например, если вы хотите просмотреть
таблицу Salesman из базы данных Auto_Store, выполните следующие команды:
- USE Auto_Store!Salesman
- BROWSE
В предыдущем примере база данных Auto_Store открывается автоматически при выполнении команды USE, однако Visual FoxPro не устанавливает
Auto_Store в качестве текущей базы данных. Открытая таким способом
база данных автоматически закрывается, когда вы закрываете таблицу,
если база данных не была явно открыта до этого.
Когда вы добавляете таблицу в базу данных, Visual FoxPro изменяет заголовок файла таблицы, включая туда информацию о пути и имени файла
базы данных. Этот путь и имя файла базы данных называются обратной
связью, поскольку эта информация связывает таблицу с владеющей ею
базой данных. Процесс удаления таблицы из базы данных не только удаляет
ссылку на таблицу и ассоциированную с ней информацию из словаря БД
Visual FoxPro, но и изменяет обратную связь, чтобы отметить таблицу
как свободную.
Вы можете удалить таблицу из базы данных интерактивно или с помощью команды REMOVE TABLE. При удалении таблицы из базы данных
вы можете и физически удалить файл таблицы с диска. В Project Manager
выберите имя таблицы и нажмите кнопку Remove. Если вы работаете
в Конструкторе баз данных, выделите имя таблицы и выберите команду Remove из меню Database.
Последовательность действий по удалению таблицы Salesman из БД Auto_Store
программным путем показа в следующем примере:
- OPEN DATABASE Auto_Store
- REMOVE TABLE Salesman
Удаление таблицы из базы данных автоматически не удаляет файл таблицы. Если вы хотите одновременно удалить таблицу из базы данных и DBF-файл
с диска, включите опцию DELETE в команду REMOVE TABLE.
Удалить базу данных с диска можно с помощью Project Manager или командой DELETE DATABASE.
Для удаления базы данных с диска всегда используйте один из вышеуказанных методов. Удаление базы данных с помощью диспетчера проектов или по
команде DELETE DATABASE автоматически обновляет обратные
связи в файлах таблиц базы данных. Если вы удалите БД с помощью какой-нибудь
утилиты работы с файлами, то в таблицах, принадлежащих БД, останутся
ссылки на уже несуществующую БД, и вы не сможете их использовать.
Команда DELETE DATABASE не удаляет файлы таблиц с диска, а только помечает их как свободные. Если вы хотите одновременно
с базой данных удалить и файлы таблиц, включите опцию DELETE
TABLES в команду DELETE DATABASE.
В приложении Visual FoxPro можно использовать несколько баз данных одновременно. Для этого либо одновременно откройте все требуемые
вам БД, либо сошлитесь на таблицы в закрытых базах данных, как это
было показано ранее. Если одновременно открыто несколько БД, вы можете
установить текущую базу данных и выбирать таблицы из нее без указания
конкретной ссылки.
Как открыть несколько баз данных? В Project Manager выделите имя базы данных и нажмите кнопку Modify или Open, в зависимости от вашей цели.
Или последовательно используйте команду OPEN DATABASE.
Когда вы открываете новую базу данных, старые не закрываются. Все уже открытые базы данных так и остаются открытыми, а последняя открытая
БД становится текущей.
Все таблицы или другие объекты, которые вы создаете, автоматически становятся частью текущей базы данных. Команды и функции, такие как
ADD TABLE и DBC(), манипулирующие с открытыми
БД, оперируют с текущей базой данных.
Вы можете объявить текущей любую из открытых БД с помощью раскрывающегося списка на стандартной панели инструментов Visual FoxPro или командой
SET DATABASE.
В следующем примере открываются три базы данных, первая объявляется текущей, и ее имя отображается на экране с помощью функции DBC():
- OPEN DATABASE Auto_Store
- OPEN DATABASE Connect_Data
- OPEN DATABASE Count_Data
- SET DATABASE TO Auto_Store
- ? DBC()
В Visual FoxPro одна или несколько баз данных открываются автоматически при выполнении запроса или формы, в которых используются несколько
баз данных. Для того чтобы не потерять управление в программе, явно
объявите текущую базу данных.
Как выбрать таблицу из текущей базы данных? Выполните команду USE со знаком вопроса "?" В диалоговом окне Use выберите нужную
таблицу. Если вам нужна таблица, не входящая в открытую базу данных,
в диалоговом окне Use выберите опцию Other.
Закрыть базу данных можно в Project Manager или командой CLOSE DATABASE. В Project Manager выделите имя базы данных и выберите
команду Close. В следующем примере закрывается база
данных Auto_Store:
- SET DATABASE ТО Auto_Store
- CLOSE DATABASE
Оба указанных способа закрывают базу данных автоматически. Еще один способ закрыть базу данных и другие открытые объекты - включить
предложение ALL в команду CLOSE.
Выполнение команды CLOSE DATABASE в окне Command не приведет к закрытию базы данных, если она была открыта одним из
следующих способов:
- В Project Manager в расширенном режиме просмотра содержимого
базы данных.
- Формой, запущенной в собственной Data Session.
В этих случаях БД остается открытой до тех пор, пока она не будет
закрыта в Project Manager или пока не будет закрыта соответствующая
форма.
В Visual FoxPro текущая база данных используется в качестве первичной области видимости для именованных объектов типа таблиц. Когда база
данных открыта, любые запрашиваемые объекты типа таблиц, представлений,
связей ищутся сначала в текущей базе данных. Если объект не найден,
поиск продолжается в пути по умолчанию.
Например, если таблица Model ассоциирована с базой данных Auto_Store, приведенные ниже команды всегда найдут таблицу Model в базе данных.
- OPEN DATABASE Auto_Store
- ADD TABLE C:\MYPROJECT\MODEL.DBF
- USE Model
В следующем примере поиск таблицы Body производится в текущей базе данных:
- USE Body
Если таблица Body не принадлежит текущей базе данных, ее поиск вне базы будет происходить в пути по умолчанию.
Всегда можно указать полный путь к файлу таблицы, чтобы открывать ее вне зависимости от ее принадлежности к какой-либо базе данных,
например, если вас не устраивают изменения в местонахождении таблиц.
Однако ссылки на таблицу только по ее имени могут значительно повысить
производительность приложения, поскольку в Visual FoxPro доступ к
именам таблиц из базы данных осуществляется гораздо эффективней, чем
по полному пути файла.
Когда вы создаете базу данных, Visual FoxPro создает и открывает для монопольного использования файл с именем БД и расширением DВС (DataBase
Container). В этом файле хранится вся информация о базе данных, включая
имена файлов и объектов, ассоциированных с ней. Сами объекты верхнего
уровня типа таблиц или полей в файле DBC не хранятся. Хранятся только
пути к файлам таблиц.
Для того чтобы увидеть структуру базы данных, вы можете пролистать файл базы данных, посмотреть схему, проверить базу данных и даже
расширить файл DВС.
Схема базы данных - это визуальное представление структур таблиц и установленных отношений между ними. Схема открытой базы данных отображается
в окне Конструктора баз данных.
В Конструкторе баз данных панель инструментов Database можно использовать для создания новой таблицы, добавления существующей таблицы в базу
данных, удаления таблиц из базы данных, изменения структуры таблицы.
Здесь же вы можете редактировать хранимые в базе процедуры.
Файл базы данных содержит записи для каждой таблицы, представления, индекса, индексного тега, установленных отношений и связей, ассоциированных
с базой данных; а также записи для каждого поля таблицы или представления,
имеющего расширенные атрибуты. В файле хранится и запись, содержащая
все хранимые процедуры базы данных.
Конструктор баз данных является концептуальным представлением схемы базы данных, однако вам может потребоваться просмотреть содержимое
файла базы данных непосредственно. Можно сделать это, выполнив команду
USE для файла DBC неоткрытой базы данных. В следующем примере
открывается окно просмотра, куда выводится содержимое файла базы данных
Auto_Store в табличном виде.
- CLOSE DATABASE Auto_Store
- USE AUTO_STORE.DBC EXCLUSIVE
- BROWSE
Не используйте команду BROWSE для модификации файла базы данных, если вы не знакомы со структурой файла DBC. Любая ошибка при
изменении файла DBC может разрушить базу данных и привести к потере
информации.
В каждом файле DВС имеется поле примечаний с именем User, в котором вы можете хранить собственную информацию о каждой записи базы данных.
Вы можете также расширить файл DВС, добавив туда поля, чтобы удовлетворить
свои собственные потребности разработчика. Для изменения структуры
файла DBC вы должны открыть его для монопольного использования.
Как добавить поле к файлу DВС?
- Откройте файл DВС для монопольного доступа командой USE.
- Выполните команду MODIFY STRUCTURE.
В следующем примере открывается Конструктор таблиц, где вы можете добавить поле в файл AUTO_STORE.DBC:
- USE AUTO_STORE.DBC EXCLUSIVE
- MODIFY STRUCTURE
При добавлении нового поля в файл базы данных начинайте имя этого поля с символов "U_" для обозначения поля пользователя. Это
поможет вам избежать конфликтов с любыми возможными изменениями структуры
файла DBC.
Не изменяйте системные поля в файле DBC. Любые такие изменения могут нарушить целостность базы данных.
Вы можете проверить целостность базы данных с помощью команды VALIDATE DATABASE.
В следующем примере файл базы данных Auto_Store проверяется на целостность:
- OPEN DATABASE Auto_Store EXCLUSIVE
- VALIDATE DATABASE
Проверка базы данных гарантирует, что строки файла базы данных хранят правильные метаданные о базе.
Использование словаря данных
Базы данных Visual FoxPro используют словарь данных, который повышает эффективность разработки и использования базы данных и освобождает
вас от необходимости писать собственные программы обеспечения правил
на уровне полей и записей или проверки уникальности значений первичных
ключей. Словарь данных Visual FoxPro позволяет создавать следующие
элементы:
- Длинные имена таблиц.
- Комментарии для каждого поля, таблицы и базы данных.
- Длинные имена полей.
- Заголовки полей, отображаемых в окнах просмотра и в виде заголовков столбцов сетки.
- Значения полей по умолчанию.
- Первичные ключи и ключи-кандидаты.
- Правила на уровне полей и правила на уровне записей.
- Триггеры.
- Постоянные отношения между таблицами базы данных.
- Хранимые процедуры.
- Связи с удаленными источниками данных.
- Локальные и удаленные представления.
Некоторые элементы словаря, такие как длинные имена полей, первичные и ключи-кандидаты, значения по умолчанию, правила на уровне полей
и записей, триггеры, хранятся в файле DBC, но становятся доступны
в процессе создания таблицы или представления.
Вы можете создавать хранимые процедуры для обработки информации в базе данных. Хранимая процедура представляет собой код Visual FoxPro,
записанный в файле DBC. Эти процедуры оперируют только с данными конкретной
базы данных. Хранимые процедуры загружаются в память во время открытия
базы данных и выполняются намного быстрее, чем процедуры из программных
файлов.
Для создания, редактирования или удаления хранимой процедуры в Project Manager выделите имя базы данных, выберите в списке пункт Stored Procedures,
затем нажмите одну из кнопок: New, Modify или Remove.
Для этой же цели в Конструкторе баз данных выберите из меню Database команду Edit Stored Procedures.
В любом случае откроется текстовый редактор Visual FoxPro, в котором вы сможете создать или отредактировать хранимую процедуру текущей
базы данных.
Хранимые процедуры используются, в основном, в качестве функций пользователя, на которые можно ссылаться в правилах уровня полей или записей. Когда
вы сохраняете функцию в базе данных, код этой функции записывается
в файл DBC и автоматически перемещается с ней, если вы меняете местоположение
базы. Использование хранимых процедур повышает переносимость приложений,
поскольку вам не нужно больше управлять файлами процедур пользователя
отдельно от файла базы данных.
Поддержание ссылочной целостности предусматривает построение набора правил для сохранения установленных отношений между таблицами при
вводе или удалении записей. Аппарат поддержания ссылочной целостности
позволяет избежать следующих неприятных ситуаций:
- Добавления записей в подчиненную таблицу, если в главной
таблице нет записи с соответствующим первичным ключом.
- Изменения значений в главной таблице, если это изменение
приведет к появлению не связанных ("одиночных") записей подчиненной
таблицы.
- Удаления записей из главной таблицы, если для нее существуют
соответствующие записи в подчиненных таблицах.
Вы можете использовать свои собственные триггеры и хранимые процедуры для поддержания целостности ссылок. Однако Построитель ссылочной целостности
Visual FoxPro позволяет определить правила поддержания ссылок, таблицы,
для которых необходимо поддерживать целостность, и системные события,
после совершения которых будет производиться проверка целостности.
Построитель ссылочной целостности управляет многоуровневыми цепочками
удалений или обновлений, и настоятельно рекомендуется в качестве инструмента
для поддержания ссылочной целостности.
Для работы с Построителем ссылочной целостности откройте Конструктор баз данных. В меню Database выберите Referential Integrity.
Если вы используете Построитель ссылочной целостности, Visual FoxPro сохраняет генерируемый код в качестве триггеров, которые ссылаются
на хранимые процедуры. Вы можете просмотреть код этих процедур, открыв
с помощью текстового редактора хранимые процедуры для базы данных,
как это было описано выше, но будьте очень осторожны при попытке его
модернизации. Может, вы лучше не будете его редактировать?
Если вы изменили проект базы данных, например структуры таблиц, или переназначили индексы, используемые для построения отношений между
таблицами, перезапустите Построитель ссылочной целостности, прежде
чем начнете пользоваться базой данных. Построитель ссылочной целостности
настроит хранимые процедуры и табличные триггеры согласно внесенным
изменениям. Если не сделать этого, вы скорее всего получите непредсказуемые
результаты, поскольку внесенные в проект базы данных изменения никак
не отразятся в ее внутренней структуре.
Вы можете установить постоянные отношения между таблицами базы данных. Постоянные отношения - это отношения, информация о которых хранится
в файле базы данных. Постоянные отношения дают возможность выполнять
следующие действия:
- Автоматически использовать установленные условия объединения в Конструкторах запросов и представлений.
- В Конструкторе баз данных визуально отображать связанные
индексы таблиц.
- В Конструкторе среды окружения данных (Data Environment
Designer) отображать установленные по умолчанию связи для форм и отчетов.
- Использовать аппарат поддержки ссылочной целостности.
В отличие от временных отношений, устанавливаемых по команде
SET RELATION, постоянные отношения не нуждаются
в переопределении при каждом открытии таблиц.
В Visual FoxPro для установки постоянных отношений используются индексы. То есть вы создаете постоянные отношения на основе индексов таблиц,
а не на основе связи полей, что позволяет связывать таблицы на основе
простых и сложных индексных выражений.
Как создать постоянные отношения между таблицами?
В Конструкторе баз данных выберите индекс, который вы хотите связать, и перетащите его на индекс связываемой таблицы, или включите предложение
FOREIGN KEY в команду CREATE TABLE или команду ALTER TABLE.
Если после этого вы посмотрите на схему базы данных в Конструкторе БД, то увидите линию, соединяющую две таблицы и обозначающую новую
постоянную связь.
Тип индексного тега или ключа определяет тип устанавливаемого постоянного отношения. Вы должны использовать первичный или индексный тег-кандидат
или ключ со стороны "один" в отношении "один ко многим";
со стороны "много" вы должны использовать обычный индексный
тег или ключ.
Для удаления постоянного отношения между таблицами в Конструкторе баз данных выделите щелчком линию, соединяющую таблицы. Толщина линии
увеличится, отмечая выбор отношения между таблицами. После этого нажмите
клавишу Del.
Каждая база данных Visual FoxPro содержит свойства Comment и Version. Вы всегда можете узнать содержание этих свойств с помощью функции
DBGETPROP().
В следующем примере на экран выводится номер версии базы данных Auto_Store:
- ? DBGETPROP('Auto_Store', 'DATABASE', 'VERSION')
Возвращаемое значение является номером версии файла DBC и доступно только для чтения.
Программно ввести комментарий в базу данных можно с помощью функции DBSETPROP().
Для этого используйте опцию COMMENT в функции DBSETPROP().
В следующем примере вводится новый комментарий для базы данных Auto_Store:
- ? DBSETPROP('Auto_Store', 'DATABASE', 'COMMENT',
- 'Это моя первая БД')
Функции DBGETPROP() и DBSETPROP() можно использовать для просмотра и изменения свойств других объектов базы данных, о чем
мы расскажем позднее.
Создание и модернизация структуры таблиц
Созданная база данных сможет хранить полезную для пользователя
информацию только после того, как в нее будут включены соответствующие
таблицы. При создании таблиц уточняются типы данных, заголовки полей,
возможные значения по умолчанию, триггеры, а также индексы, которые
строятся для организации отношений между таблицами.
Таблицу можно конструировать и создавать в интерактивном
режиме с помощью Конструктора таблиц, который доступен из Project
Manager или из меню File; ее также можно создать программно.
Чтобы создавать и модифицировать таблицы из программ, используются команды, приведенные в табл. 6.2.
Таблица 6.2. Команды создания и модификации таблиц
ALTER TABLE |
CLOSE TABLES |
CREATE TABLE |
DELETE FILE |
REMOVE TABLE |
Для создания таблицы базы данных в Project Manager выберите базу данных, затем заголовок Tables и нажмите кнопку New, чтобы вызвать Конструктор
таблиц. Окно Конструктора таблиц с необходимыми пояснениями показано
на рис. 6.2. При открытой базе данных вы можете выполнить команду
CREATE TABLE.
Рис. 6.2.
Следующий фрагмент программы создает таблицу Salesman с четырьмя столбцами под именами key_salman, last_name, first_name, patronymic:
- OPEN DATABASE Auto_Store
- CREATE TABLE Salesman (key_salmen I, ;
- last_name C(17), ;
- first_name C(17), ;
- patronymic C(17))
Напомним, что в Visual FoxPro символ "I" обозначает поле с
типом данных Integer, которое имеет стандартную длину, и она не указывается.
Символ "C(17)" обозначает символьное поле с типом данных Character
и длиной 17 символов.
Новая таблица автоматически ассоциируется с той базой данных, которая открыта в момент создания таблицы.
Имена таблиц могут состоять из букв, цифр и символов подчеркивания и должны начинаться с буквы или символа подчеркивания.
Если таблица связана с базой данных, можно задать длинное имя таблицы. Длинное имя таблицы может содержать до 128 символов и употребляется
вместо стандартного имени для идентификации таблицы в базе данных.
Visual FoxPro использует длинные имена таблиц (если они заданы) во
всех случаях, когда имя встречается в интерфейсе, например в Конструкторе
баз данных, в Конструкторе запросов, Конструкторе представлений, а
также в заголовке окна Browse.
Для присвоения таблице базы данных длинного имени в Конструкторе таблиц введите имя в поле Table Name (см. рис 6.2). В программе используйте
предложение NAME в команде CREATE TABLE. Следующий фрагмент
создает таблицу Automobil и присваивает ей более осмысленное имя Automobile_Passenger_Car:
- CREATE TABLE Automobil NAME Automobile_Passenger_Car ; (key_auto I, ; key_model I, date_issue D, cost N(10,2))
Для переименования таблиц или для добавления длинных имен таблицам, которые создавались без них, также используется Конструктор таблиц.
Например, если бывшая свободная таблица связывается с базой данных,
то с помощью Конструктора таблиц можно присвоить ей длинное имя. Длинные
имена могут состоять из букв, цифр, символов подчеркивания и должны
начинаться с буквы или символа подчеркивания. В длинных именах не
разрешается употреблять пробелы.
В команде CREATE TABLE задается имя того DBF-файла, который Visual FoxPro создает для хранения новой таблицы. Это имя файла является
стандартным именем таблицы как для таблиц, связанных с базой данных,
так и для свободных таблиц.
При создании полей таблицы задается имя поля, тип данных и длина поля. Можно также установить, разрешаются или нет значения NULL для поля
и значение поля по умолчанию.
Для свободных таблиц имена полей могут быть длиной до 10
символов; для таблиц, связанных с базой данных, имена полей могут
содержать до 128 символов. Если таблица исключается из базы данных,
то длинные имена полей сокращаются до 10 символов.
Когда создается таблица базы данных, Visual FoxPro запоминает длинные имена полей в записи файла DBC. Первые 10 символов длинного имени
запоминаются и в файле DBF в качестве имени поля.
Если окажется, что усечения длинных имен до 10 символов не являются уникальными в таблице, Visual FoxPro генерирует имена, состоящие из
первых n символов длинных имен с добавленными к ним последовательными
номерами так, чтобы общая длина сгенерированных имен составляла 10
символов. Например, следующие длинные имена будут преобразованы в
такие 10-символьные:
Длинное имя | Короткое имя |
automobile_passenger_car_key_auto | automobile |
automobile_passenger_car_key_model | automobil1 |
automobile_passenger_car_date_issue | automobil2 |
... | ... |
automobile_passenger_car_cost | automobi11 |
Если таблица связана с базой данных, то ее поля можно обозначать только длинными именами. Использование 10-символьных имен полей для таблицы
в составе базы данных невозможно. Если таблица удаляется из базы данных,
то длинные имена ее полей теряются и для ссылок на поля таблицы придется
использовать 10-символьные имена, хранящиеся в файле DBF.
Можно использовать длинные имена полей в индексных файлах. Однако если индекс был создан с использованием длинных имен полей, а затем
таблица, для которой он создавался, исключается из базы данных, индекс
перестанет работать. В этом случае можно удалить индекс и создать
его заново, употребляя короткие имена полей.
Правила составления длинных имен полей такие же, как и для любых идентификаторов Visual FoxPro, за исключением ограничения длины до 128 символов.
После создания в открытой базе данных таблицы можно добавить к каждому ее полю описание, чтобы облегчить понимание и упростить дальнейшую
ее модификацию. Visual FoxPro показывает текст комментария при выборе
поля в списке полей таблицы в Project Manager.
Для добавления комментария к полю таблицы базы данных в Конструкторе таблиц введите текст комментария в поле ввода Field Comment или используйте
функцию DBSETPROP().
Например, можно пояснить, что содержится в поле key_model таблицы Model, введя в качестве комментария к полю текст "Уникальный ключ
модели автомобиля":
- ?DBSETPROP('Model.key_model', 'FIELD', 'COMMENT', ;
- 'Уникальный ключ модели автомобиля')
Для каждого поля таблицы в базе данных может быть задан заголовок. Visual FoxPro выводит текст этого заголовка в качестве названия столбца
для данного поля в окне Browse и в качестве заголовка по умолчанию
для колонок объекта Grid формы.
Для добавления заголовка поля таблицы базы данных в Конструкторе таблиц введите текст в поле Caption в разделе Field Properties или используйте
функцию DBSETPROP().
Например, можно ввести текст "Наименование модели" как заголовок поля name_model в таблице Model :
- ?DBSETPROP('Model.name_model', 'FIELD', 'CAPTION',; 'Наименование модели')
В процессе создания полей таблицы производится выбор типов данных, для хранения которых предназначаются поля. При определении типа данных
для поля следует помнить:
- Какого рода значения допускаются для данного поля (например,
в числовое поле нельзя будет заносить текст).
- Объем памяти, резервируемый Visual FoxPro для хранения
значений поля (например, для каждого значения типа Currency используется
8 байтов).
- Какого рода операции могут производиться над значениями
данного поля. Например, Visual FoxPro может находить суммы значений
выражений типов Numeric или Currency, но не сможет провести эту операцию
с выражениями типов Character или General.
- Сможет ли FoxPro выполнять индексирование или сортировку
по значениям данного поля (невозможно выполнять сортировку или индексирование
по полям примечаний или General).
Для телефонных номеров, кодов изделий и других чисел, с которыми не предполагается выполнять математические вычисления, следует задавать
тип данных Character, а не тип Numeric. Если вы используете поле для
размещения уникального цифрового ключа, используйте тип данных Integer.
При построении новой таблицы может быть задано, что одно или несколько ее полей допускают значения NULL. Занесение в поле значения NULL констатирует
тот факт, что информация, которая обычно должна храниться в данном
поле или записи, в настоящее время недоступна.
Как управлять использованием значений NULL для отдельных полей? В Конструкторе таблиц установите или снимите отметку со столбца Null
для данного поля. Если столбец Null отмечен, то в поле могут вводиться
значения NULL (см. рис. 6.2). В программе используйте предложения
NULL или NOT NULL в команде CREATE TABLE.
Например, следующая команда создает и открывает таблицу, в которой не допускаются значения NULL в поле key_body, а разрешаются значения
NULL в поле name_body:
- CREATE TABLE body (key_body i NOT NULL, name_body c(20); NULL)
Можно также определять режим использования значений NULL с помощью команды SET NULL.
Для того чтобы разрешить использование значений NULL во всех полях таблицы в Конструкторе таблиц, отметьте столбец Null для каждого поля
таблицы или перед использованием команды CREATE TABLE выполните
команду SET NULL ON.
После команды SET NULL ON Visual FoxPro автоматически отмечает столбец NULL для всех полей, создаваемых в Конструкторе таблиц. Если
команда SET NULL задана до использования команды CREATE TABLE, то нет необходимости указывать предложения NULL или NOT NULL. Например, следующий программный код создает таблицу, в которой допускаются значения NULL для всех полей:
- SЕТ NULL ON
- CREATE TABLE Fuel_oil (key_fuel_oil I, name_fuel_oil C(20))
Наличие значений NULL оказывает влияние на свойства таблиц и индексов. Например, если команда APPEND FROM используется для копирования
записей из таблицы, где есть значения NULL, в таблицу, где они не
допускаются, то значения NULL будут при копировании рассматриваться
или как пустые строки, или как нули, или как пустые поля.
Если требуется, чтобы при добавлении новой записи автоматически заполнялось некоторое поле, то для такого поля можно задать значение по умолчанию.
Значение поля по умолчанию - это число или строка,
которые служат стандартным заполнением поля при добавлении новых записей
в таблицу, связанную с базой данных.
Значения по умолчанию применяются как при вводе данных с
помощью формы, так и при вводе в окно просмотра с помощью представлений
или программно и сохраняются в поле, пока не будут введены другие
значения.
Значения по умолчанию могут быть заданы в Конструкторе таблиц
или программно. Значения по умолчанию могут быть заданы для полей
любого типа, кроме General.
Для того чтобы задать значение по умолчанию для поля таблицы,
включенной в базу данных, в Конструкторе таблиц введите значение в
поле Default Value, находящееся в группе Field Properties (рис. 6.3),
или используйте выражение DEFAULT в команде CREATE TABLE.
Рис. 6.3. Задание значения по умолчанию в Конструкторе таблиц
Предположим, в силу географического положения магазина чаще всего адрес клиентов данного магазина начинается с фразы "Санкт-Петербург".
В следующем примере создается поле address со значением по умолчанию
"Санкт-Петербург":
- CREATE TABLE Customer (key_customer I, name_customer C(30), ;
- address C(30) DEFAULT "Санкт-Петербург", ;
- tel C(12), fax C(12), last_name C(17), first_name C(17),;
- patronymic C(17), juridical L, comment M)
Если таблица Customer уже имеет поле address, то добавить для него значение по умолчанию можно следующей командой:
- ALTER TABLE Customer ALTER COLUMN address SET DEFAULT ;
- "Санкт-Петербург"
Значения по умолчанию могут использоваться для ускорения ввода данных, позволяя пропускать при вводе поля, для которых не требуется значение,
отличное от стандартного.
Если по бизнес-правилам в приложении требуется обязательное наличие значения некоторого поля, то задание значения по умолчанию помогает
избежать нарушения соответствующих правил проверки полей и записей.
При удалении таблицы из базы данных удаляются и все связанные с таблицей значения по умолчанию. Хранимые процедуры, на которые ссылались удаляемые
значения по умолчанию, сохраняются и после удаления значений по умолчанию.
В качестве значений по умолчанию можно задавать как явные значения в виде чисел, строк символов, дат и т. д., так и выражения, дающие
явные значения в результате вычислений. В качестве такого выражения
можно использовать и пользовательскую функцию. В этом случае такую
функцию целесообразно записать в хранимых процедурах.
Visual FoxPro производит вычисления для определения типов данных при закрытии определения таблицы. Если тип вычисленного значения несовместим
с типом соответствующего поля, то генерируется сообщение об ошибке.
Если выражение представляет собой определенную пользователем функцию
или содержит вызовы таких функций, то такое выражение не вычисляется.
Для того чтобы обеспечить соблюдение бизнес-правил при вводе данных, можно задать правила проверки полей и записей, которые контролируют
допустимость вводимых данных в таблицу базы данных.
Правила проверки полей и записей контролируют вводимые значения
на выполнение заданного критерия. Если вводимое значение не удовлетворяет
критерию, оно отвергается.
Правила проверки могут задаваться только для таблиц, связанных с базой данных.
Правила проверки полей и записей позволяют контролировать ввод информации как в окне просмотра, так и в экранной форме или при вводе данных
из программы. При прочих равных условиях правила проверки позволяют
задать контролирующее выражение лаконичнее, чем при использовании
выражения VALID при проектировании экранной формы или соответствующего
кода в программе. Вдобавок, будучи установленными для таблицы базы
данных, правила проверки распространяются на все приложения, использующие
данную таблицу.
Для контроля вводимых данных можно также определить первичные индексы и индексы-кандидаты, которые предотвращают ввод дублирующих значений
полей, а также можно определить триггеры, обеспечивающие целостность
ссылок или выполняющие какие-либо действия при изменении данных в
базе данных.
Ограничения на уровне поля применяются в тех случаях, когда требуется проверять вводимую в поле информацию независимо от остальной части
записи. Например, можно использовать правило проверки поля, чтобы
исключить возможность ввода отрицательного числа в поле, которое должно
иметь положительное значение. Можно использовать правила проверки
поля и для сравнения вводимого в поле значения со значением из другой
таблицы.
Не следует задавать такие правила проверки полей и записей,
если эти поля и записи являются специфическими для данного приложения.
Правила проверки записей и полей должны обеспечивать целостность данных
и бизнес-правила, которые всегда применимы к базе данных независимо
от приложения. Например, можно задать правило, которое будет сравнивать
значение, вводимое в поле key_body, со значениями из справочной таблицы
кузовов, и отвергать те значения, которые не обнаружатся среди допустимых
кодов кузовов.
Как задать правило проверки поля? В Конструкторе таблиц введите
выражение критерия в поле ввода Validation Rule в группе Field Properties
(рис.6.4) или используйте выражение CHECK в команде CREATE TABLE
или ALTER TABLE.
Рис. 6.4. Задание правил проверки и сообщения об ошибке
в Конструкторе таблиц
Следующий программный код вводит для таблицы Model правило проверки, требующее, чтобы значения, вводимые в поле quantity_drum, были не
меньше единицы:
- ALTER TABLE Model ;
- ALTER COLUMN quantity_drum SET CHECK quantity_drum >>= 1
Если пользователь попытается ввести меньшее значение, Visual FoxPro выведет диалоговое окно, содержащее сообщение об ошибке, и значение
будет отвергнуто.
Сообщение, которое выводится при нарушении правил, может быть задано при определении поля. Заданное сообщение будет выводиться вместо стандартного
сообщения об ошибке в соответствующем диалоговом окне.
Для задания сообщения о нарушении правил проверки полей в Конструкторе таблиц введите сообщение в поле ввода Validation Text в группе Field
Properties (рис.6.4) или используйте необязательный параметр ERROR
в выражении CHECK в команде CREATE TABLE или ALTER TABLE.
Следующий фрагмент программы вводит для таблицы Model правило проверки, требующее, чтобы значения, вводимые в поле quantity_drum, были не
меньше единицы, а также определяет сообщение об ошибке:
- ALTER TABLE Model ;
- ALTER COLUMN quantity_drum SET CHECK quantity_drum >>= 1 ;
- ERROR "Количество цилиндров должно быть больше или равно 1"
Если пользователь попытается ввести значение меньше 1, Visual
FoxPro выведет диалоговое окно с заданным сообщением об ошибке и неверное
значение будет отвергнуто (рис. 6.5). Чтобы задать собственное сообщение
об ошибке, можно использовать и выражение SET CHECK в команде ALTER TABLE с необязательным параметром ERROR.
Рис. 6.5.
Не следует включать в правила проверки никаких команд или функций, которые пытаются переместить указатель записи в текущей рабочей области,
то есть в той рабочей области, для которой эти правила проверяются.
Включение в правила проверки таких команд и функций, как SEEK,
LOCATE, SKIP, APPEND, APPEND BLANK, INSERT, AVERAGE, COUNT, BROWSE
или REPLACE FOR, может привести к повторному срабатыванию
правил, создавая ошибочную ситуацию. Такая ситуация называется рекурсией.
В Visual FoxPro триггеры определяются и хранятся как свойства для
заданной таблицы. Если таблица удаляется из базы данных, то связанные
с ней триггеры тоже удаляются. Триггеры срабатывают после проверки
всех прочих ограничений, таких как правила проверки, уникальность
первичного ключа, допустимость пустых значений. В отличие от правил
уровней полей и записей, триггеры не срабатывают для буферизованных
данных.
Триггеры можно создавать в Конструкторе таблиц или с помощью
команды CREATE TRIGGER. Для таблицы может быть задано по
одному триггеру на каждое из событий: INSERT, UPDATE или DELETE. В
каждый момент времени таблица может иметь максимум три триггера. Значением
триггера может быть истина (.Т.) или ложь (.F.).
Для установки триггера в диалоговом окне Table Properties
Конструктора таблиц введите в одно из полей ввода - INSERT,
UPDATE или DELETE Trigger - выражение триггера или имя хранимой
процедуры, содержащей выражение триггера. Программно можно использовать
предложение CHECK в команде CREATE TRIGGER.
Предположим, при продаже очередного автомобиля 27 числа каждого месяца требуется формировать запрос о результатах продажи за текущий
месяц. Чтобы этого добиться, можно задать триггер на операцию Insert
для таблицы Sale. Триггер устанавливается на операцию INSERT (а не
на операцию DELETE или UPDATE), поскольку требуется, чтобы триггер
срабатывал при добавлении новой записи. При создании триггера
можно указать функцию __ri_insert_sale() как триггер вставки
таблицы Sale (рис. 6.6). Эту функцию необходимо описать в хранимой
процедуре:
Рис. 6.6.
- PROCEDURE __ri_insert_sale
- IF DAY(DATE())=27
- WAIT WINDOW 'Формирование отчета' NOWAIT
- SELECT * ;
- FROM Sale ;
- WHERE MONTH(Sale.date_sale) = MONTH(DATE());
- INTO CURSOR Sale_Month_Current
- ENDIF
- ENDPROC
Триггеры для событий UPDATE и DELETE задаются аналогично.
После создания таблицы ее структура и свойства могут быть в любое время модифицированы. Для полей можно добавить, изменить или удалить
имена, размеры, типы данных, значения по умолчанию, правила проверки,
комментарии и заголовки.
Структура таблицы может быть изменена как в среде Конструктора таблиц, так и программно с помощью команды ALTER TABLE.
Например, можно изменить структуру связанной с базой данных таблицы Sale с помощью следующих команд:
- OPEN DATABASE Auto_Store
- USE Sale EXCLUSIVE
- MODIFY STRUCTURE
После этого открывается Конструктор таблиц.
Для создания свободной таблицы в Project Manager выберите пункт Free Tables, а затем нажмите кнопку New, чтобы вызвать Конструктор таблиц.
Для программного создания свободной таблицы используйте команду CREATE TABLE без открытых баз данных.
Следующий программный код создает свободную таблицу Order_, состоящую из четырех полей с именами key_order, key_customer, key_model, key_salman:
- CLOSE DATABASES
- CREATE TABLE Order_ (key_order I, ;
- key_customer I, ;
- key_model I, ;
- key_salman I)
Новая таблица является свободной, поскольку в момент ее создания не было открытых баз данных.
Если требуется перемещаться по записям таблицы, просматривать их или манипулировать ими в некотором заданном порядке, то следует использовать
индекс.
Индекс Visual FoxPro представляет собой файл указателей,
логически упорядоченных в соответствии со значениями индексного ключа.
Индексный файл отделен от файла таблицы (DBF-файла) и не изменяет
физический порядок расположения записей в таблице. При создании индекса
создается файл, поддерживающий указатели на записи в DBF-файле. Если
требуется работать с записями в некотором порядке, то следует выбрать
соответствующий индекс, чтобы установить тот порядок, в котором будут
видимы и доступны записи таблицы.
Первоначально при создании таблицы Visual FoxPro создает
файл DBF и если имеются поля примечаний и General, то связанный с
ним FPT-файл. В это время не создается никаких индексных файлов. Записи
запоминаются в новой таблице в порядке ввода. При просмотре новой
таблицы записи видны в том порядке, в котором они вводились. Обычно
требуется просматривать записи и иметь к ним доступ в некотором заданном
порядке. Например, может потребоваться, чтобы записи в таблице клиентов
были отсортированы в алфавитном порядке названий компаний. Если нужно
задать порядок доступа к записям и порядок их просмотра, следует создать
для таблицы индексный файл путем создания для таблиц первого способа
упорядочения или индексного ключа. Тогда можно будет устанавливать
порядок записей в таблице в соответствии с индексным ключом и получать
доступ к записям таблицы в новом порядке.
Как задать для таблицы индексный ключ? В Конструкторе таблиц
на вкладке Index введите информацию об индексном ключе. Установите
Regular в качестве типа индекса или используйте команду INDEX.
Например, следующий программный код открывает таблицу Model
и создает индексный ключ для поля key_body. Ключевое слово TAG и следующее
за ним "key_body" задают имя или тег для нового индексного
ключа.
- USE Model
- INDEX ON key_body TAG key_body
В этом примере тег индексного ключа имел то же имя, что и
индексируемое поле. Эти имена не обязательно должны совпадать, для
индексного ключа можно задать и другое имя.
После создания с помощью команды INDEX индекса
Visual FoxPro автоматически использует этот индекс, чтобы установить
порядок записей в таблице. Например, если ввести данные в таблицу
из предыдущего примера и просмотреть ее в окне просмотра, то записи
будут отсортированы по полю key_body.
При создании первого индексного ключа таблицы в предыдущем
примере Visual FoxPro автоматически создал новый файл - MODEL.CDX,
в котором запоминаются индексные ключи.
Индексный CDX-файл, называемый структурным составным индексом,
представляет собой наиболее общий и важный тип индексных файлов Visual
FoxPro.
Обратите внимание на следующие свойства структурного CDX-файла:
- Автоматически открывается при открытии таблицы.
- В одном индексном файле может содержаться несколько вариантов упорядочения записей или индексных ключей.
- Автоматически поддерживает операции добавления, изменения или удаления записей таблицы.
Visual FoxPro предлагает дополнительно еще два вида индексных файлов: неструктурные СDХ-файлы и файлы с одним ключом - IDX-файлы.
Однако СDХ-файлы, или структурные составные компактные индексы, представляют
наиболее важный вид индексов. Остальные два вида индексов употребляются
реже.
Visual FoxPro поддерживает четыре типа индексов: первичные, кандидаты, уникальные и обычные. Тип индекса определяет, допустимы или нет повторяющиеся
значения полей и записей.
Первичный индекс (Primary) - это единственный индекс
в таблице, который определяет уникальное ключевое значение для ее
записей.
Следовательно, он запрещает повторяющиеся значения в заданных полях или в выражении. Для таблицы может быть создан только один первичный
индекс. При попытке задать первичный индекс для поля, в котором уже
имеются повторяющиеся значения, Visual FoxPro выдает сообщение об
ошибке.
Индекс-кандидат (Candidate) - это индекс, который удовлетворяет
требованиям к первичному индексу, но может быть не единственным в
таблице.
Он также запрещает повторяющиеся значения в заданных полях или выражении. Название "кандидат" относится к основному свойству индекса:
поскольку он запрещает дублирующие значения, то этот индекс можно
использовать в качестве первичного индекса для таблицы.
При попытке задать индекс-кандидат для поля, в котором уже имеются повторяющиеся значения, Visual FoxPro выдает сообщение об ошибке.
Первичные индексы и индексы-кандидаты создаются с помощью команд CREATE TABLE или ALTER TABLE. При определении постоянного
отношения типа "один ко многим" или "один к одному" можно использовать со стороны "один" как первичный индекс, так и индекс-кандидат.
Для создания первичного индекса или индекса-кандидата на вкладке Index Конструктора таблиц выберите тип индекса Primary или Candidate и создайте
индекс (рис. 6.7) или используйте команду ALTER TABLE.
Рис. 6.7.
Например, каждая из следующих команд делает key_model первичным ключом для таблицы Model:
- ALTER TABLE Model ADD PRIMARY KEY key_model TAG key_mode
- ALTER TABLE Model ALTER COLUMN key_model I PRIMARY KEY
Первичные индексы и индексы-кандидаты хранятся в структурном
СDХ-файле данной таблицы, а также в базе данных, когда установлены
свойства "Primary" или "Candidate". Эти типы индексов
невозможно хранить ни в неструктурных СDХ-файлах, ни в IDХ-файлах.
Основной причиной этого является то, что файл, содержащий индексы
таких типов, должен быть всегда открытым, если открыта соответствующая
таблица.
Если в индексном выражении, связанном с базой данных, используется определенная пользователем функция, то выражение обрабатывается таким
же образом, как и выражения правил проверки и триггеров, содержащие
определенные пользователем функции.
В Visual FoxPro уникальный индекс (Unique) не запрещает
повторяющиеся значения, однако уникальный индекс запоминает в индексном
файле только первое появление каждого значения.
Слово "уникальный" относится к значениям индексного файла,
содержащего только уникальные значения ключей; поскольку каждое значение
не запоминается более одного раза, все последующие появления какого-либо
значения игнорируются. Если таблица проиндексирована уникальным индексом,
то она может иметь повторяющиеся значения. Уникальный тип индексов
поддерживается для обеспечения совместимости с предыдущими версиями.
Обычный индекс (Regular) - это индекс, который не является уникальным, первичным или индексом-кандидатом.
Обычные индексы используются для упорядочения и поиска записей, но не для обеспечения уникальности данных в этих записях. Обычный индекс
используется также при организации постоянных отношений типа "один
ко многим" со стороны многих.
После создания индексных ключей для таблицы Model по полям
key_model, key_firm, key_fuil_oil, key_tyre и key_body можно выводить записи в различном порядке, просто выбирая нужный индексный ключ. Команда SET ORDER используется для указания того индексного ключа, по которому будет упорядочиваться таблица.
Например, следующие команды открывают окно Browse для просмотра данных и выводят записи таблицы Model, упорядоченные по полю key_model:
- SET ORDER ТО key_model
- BROWSE
В табл. 6.3 систематизируются свойства трех видов индексов.
Таблица 6.3. Виды индексов Visual FoxPro
Виды индекса | Описание | Количество ключей | Ограничения |
Структурный CDX | Имя файла, совпадает с именем таблицы; автоматически
открывается при открытии таблицы | Выражения со многими ключами, называемыми
тегами | Максимум 240 символов на вычисляемое выражение |
Неструктурный CDX | Должен открываться явно; имеет имя файла, отличное
от имени файла таблицы | Выражения со многими ключами, называемыми тегами | Максимум 240 символов на вычисляемое выражение |
Простые IDX | Должен открываться явно; имя файла с расширением .IDX
определяется пользователем | Одноключевые выражения | Максимум 100 символов
на вычисляемое выражение |
Неструктурные СDХ-индексы применяются в тех случаях, когда требуется создать несколько индексных тегов для какой-либо специальной цели,
однако нежелательна постоянная поддержка этих индексов. Например,
если приложение содержит некоторый набор отчетов на основе анализа
данных в полях, которые в остальное время не индексируются, то прикладная
программа может создать неструктурный СDХ-индекс с необходимыми индексными
тегами, запустить на выполнение эти отчеты, а затем удалить неструктурные
СDХ-индексы.
Для создания неструктурного индексного тега используйте команду INDEX с параметрами TAG и OF.
Предложение OF в команде INDEX используется для указания того, что индекс-ный тег должен быть сохранен в файле, отличном от
структурного СDХ-файла данной таблицы. Например, следующая команда
создает тег с именем name_firm для таблицы Firm и сохраняет его в
неструктурном СDХ-файле с именем NSTRFIRM.CDX:
- USE Firm
- INDEX ON name_firm TO TAG name_firm OF NSTRFIRM
Простой, или отдельный индексный файл, образуется на основе выражений с одним ключом и хранится в файле с расширением IDХ. В отличие от
СDХ-индексов, которые строятся на основе выражений со многими ключами,
простые IDХ-индексы сохраняют информацию только об одном ключевом
выражении.
Обычно простые индексы используются в качестве временных индексов, создаваемых или реорганизуемых непосредственно перед использованием.
Для каждой таблицы может быть создано сколько угодно IDХ-файлов. Некоторые
программисты предпочитают использовать этот тип индекса при создании
многопользовательских приложений, так как он легче поддается восстановлению
в случае аварийных сбоев.
Вы можете упростить организацию поиска данных в приложении, если воспользуетесь индексами на основе выражений. Выражения могут
быть простыми или сложными - это зависит от задачи.
Простые индексные выражения - это индексы, построенные на основе одного поля или сложения нескольких символьных полей для формирования
составного ключа. Например, можно создать индекс для таблицы Customer
из базы данных Auto_Store на основе выражения:
- last_name + first_name + patronymic
Если просматривать таблицу Customer, когда она упорядочена по такому ключу, то можно убедиться, что она оказывается отсортированной по
полю last_name, затем по полю first_name и только после этого по полю
patronymic.
Вы можете создать индекс с помощью следующей команды:
- INDEX ON last_name + first_name + patronymic TAG ; LasFirPat
Можно создавать индексы на основе более сложных индексных выражений. Индексные выражения Visual FoxPro могут содержать функции Visual FoxPro,
константы или определенные пользователем функции.
Результат вычисления индексного выражения не должен превышать 100 символов для простых (IDХ) индексов и 240 символов для тегов СDХ-индексов.
В одном индексном теге можно комбинировать данные различных типов,
преобразовав компоненты выражения к символьному типу.
Для индексных тегов могут употребляться встроенные функции Visual FoxPro. Например, чтобы преобразовать поле типа дата в символьное
выражение, можно использовать функцию DTOS(), а для преобразования
числового значения в строку символов - функцию STR().
Пусть требуется создать индексный тег для таблицы Account, в котором
бы комбинировались поля date_write (дата выписки счета) и sum_ (сумма
оплаты), тогда можно использовать следующее индексное выражение:
- INDEX ON DTOS(date_write) + STR(sum_) TAG DatSum
Вы можете расширить возможности индекса, если будете использовать в индексном выражении хранимые процедуры и определенные пользователем
функции.
Если индексный тег строится для таблицы, связанной с базой данных, то предпочтительнее использовать хранимые процедуры, а не определенные
пользователем функции. Поскольку определенная пользователем функция
хранится в файле, отдельном от базы данных, есть вероятность, что
этот файл будет перемещен или удален, а это приведет к неработоспособности
индексный тег, ссылающийся на такую функцию. Хранимые же процедуры
запоминаются в DBС-файле и всегда могут быть найдены Visual FoxPro.
Другим преимуществом использования хранимых процедур в индексных выражениях является то, что в индексе будет гарантировано использование в точности
того кода, который указан. Если же в индексном выражении используется
определенная пользователем функция, то при выполнении индексирования
будет вызываться любая функция с указанным именем, оказавшаяся в области
видимости Visual FoxPro.
Использование хранимых процедур или определенных пользователем функций следует тщательно продумывать, поскольку это увеличивает время создания индекса.
Вы можете просматривать записи по убыванию ключа, создав индекс с убывающими ключами или рассматривая обычный индекс в обратном порядке.
Как создать убывающий индекс? На вкладке Index Конструктора таблиц нажмите кнопку со стрелкой слева от поля Name так, чтобы стрелка на
кнопке указала вниз, или используйте предложение DESCENDING в команде INDEX ON.
При создании структурного составного индексного файла можно использовать оба метода. При создании индексов других видов можно использовать
только второй способ. Например, можно создать новый убывающий индекс,
упорядочивающий таблицу Account от больших к меньшим значениям поля
sum_, и просматривать таблицу в таком порядке при помощи следующего
программного кода:
- USE Account
- INDEX ON sum_ TAG sum_ DESCENDING
- BROWSE
Возможность читать индекс по убыванию ключа позволяет воспользоваться существующим индексом, вместо того чтобы создавать новый. Пусть имеется
индекс, упорядочивающий таблицу Account по полю sum_, созданный с помощью следующего программного кода:
- USE Account
- INDEX ON sum_ TAG sum_
По умолчанию порядок будет возрастающий. Просматривать таблицу в порядке убывания ключа можно с помощью следующего программного кода:
- USE Account
- SET ORDER ТО sum_ DESCENDING
- BROWSE
В предыдущих примерах внимание было сосредоточено на доступе к информации по убыванию ключа. Однако обе команды - SET ORDER
и INDEX - могут использоваться с опцией ASCENDING.
Комбинируя разные варианты употребления этих команд, можно добиться
значительной гибкости приложения. Например, при создании индекса можно
указать опцию ASCENDING или DESCENDING для наиболее часто используемого
порядка, а если необходимо, в команде SET ORDER можно указать противоположный порядок.
Вы можете ограничить множество доступных данных только необходимыми данными, использовав фильтрующий индекс. Если создать фильтрующий
индекс, то видимы и доступны будут только записи, удовлетворяющие
критерию фильтрующего выражения.
Как создать фильтр? На вкладке Index Конструктора таблиц введите фильтрующее выражение в поле ввода Filter нужного индекса (рис. 6.8) или используйте
необязательное предложение FOR в команде INDEX.
Рис. 6.8.
Если в команду INDEX ввести необязательное предложение FOR, то индекс будет действовать на таблицу, как фильтр. Индексные ключи
будут создаваться в индексном файле только для записей, удовлетворяющих
значению фильтра. Следующий программный код создает фильтрующий индекс
и выводит отфильтрованные данные в окне просмотра:
- USE Account
- INDEX ON sum_ FOR sum_>>30000 TAG sum_
- BROWSE
Для того чтобы временно отфильтровать данные без построения специального фильтрующего индекса, используется команда SET FILTER. Особенно
полезна эта команда в тех случаях, когда требуется задать временное
условие, которому должны удовлетворять записи таблицы, чтобы быть
доступными. Например, чтобы отфильтровать таблицу Account так, чтобы
показать только счета с суммой оплаты больше 30000, можно использовать
следующие команды:
- USE Account
- SET FILTER ТО sum_ >> 30000
- BROWSE
Команда SET FILTER воспринимает в качестве фильтра
любое допустимое логическое выражение Visual FoxPro. После того как
выдана команда SET FILTER, в таблице будут доступны только
записи, удовлетворяющие условию фильтра. Все команды доступа к таблицам
действуют с учетом установленного командой SET FILTER критерия.
Для каждой открытой таблицы может быть установлен свой фильтр.
Вы можете повысить производительность при работе с индексированными таблицами, поддерживая индексы в актуальном состоянии (соответствующим
данным в таблицах) и используя в них оптимизируемые выражения.
Индексный файл может оказаться устаревшим, если таблица
открывается без соответствующего индексного файла и в ее ключевые
поля вносятся изменения. Индексные файлы могут также оказаться недействительными
в результате аппаратных сбоев, а также в результате редактирования
таблицы программами, отличными от Visual FoxPro. Если индексный файл
оказался устаревшим, то его можно обновить командой REINDEX.
Как перестроить индексный файл? В меню Table
выберите Rebuild Indexes или используйте команду REINDEX.
Например, следующий программный код обновляет индексный
файл для таблицы Account:
- USE Account REINDEX
Команда REINDEX обновляет все индексные файлы,
открытые в текущей рабочей области. Visual FoxPro распознает все виды
индексных файлов (составные СDХ-файлы, структурные СDХ-файлы и простые
IDХ-файлы) и соответственно их перестраивает. Обновляются все теги
в СDХ-файлах и структурных СDХ-файлах, открывающихся автоматически
вместе с таблицей.
Перестройка индексов требует временных затрат, особенно
для больших таблиц. Перестройку индексов следует производить только
при необходимости.
Итак, пришло время вернуться к нашей задаче, описанной в
первой главе (раздел 1.2) и спроектированной во второй (раздел 2.2).
Следующий программный код описывает создание базы данных Auto_Store.
Полностью программа записана на прилагаемой к книге дискете, здесь
мы приводим ключевые фрагменты, исключая однотипные операции:
- WAIT WINDOW "Один момент..." NOWAIT
- * После выполнения данного кода не забудьте БД
- * "Auto_Store" включить в проект (с помощью клавиши Add,
- * предварительно выделив пункт Databases во вкладке Data)
- CREATE DATABASE auto_store && Создание БД Auto_Store
- ? DBSETPROP('auto_store', 'database', 'comment', ;
- 'Автоматизация управления работы дилера по продаже легковых автомобилей.') && Комментарий к БД
- * Создание таблицы Model
- CREATE TABLE Model (key_model i, name_model c(20), key_firm i DEFAULT 1, ;
- swept_volume n(5) NULL, quantity_drum n(2) NULL, ;
- capacity n(5,1) NULL, torgue n(5,1) NULL, ;
- key_fuel_oil i DEFAULT 1, top_speed n(5,1) NULL, ;
- starting n(4,1) NULL, key_tyre i DEFAULT 1, ;
- key_body i DEFAULT 1, quantity_door n(1) NULL, ;
- quantity_sead n(2) NULL, length n(5)<|>NULL, width n(4) ;
- NULL, ;
- height n(4) NULL, expense_90 n(4,1) NULL, ;
- expense_120 n(4,1) NULL, expense_town n(4,1) NULL)
- * Установка заголовков (для таблицы model)
- ? DBSETPROP ('Model.key_model', 'field', 'caption', ; 'Уникальный ключ модели')
- ? DBSETPROP ('Model.name_model', 'field', 'caption', ; 'Наименование модели')
- ? DBSETPROP ('Model.key_firm', 'field', 'caption', ;
- 'Уникальный ключ фирмы')
- ...
-
- * Создание комментария (для таблицы Model)
- ? DBSETPROP ('Model.key_firm', 'field', 'comment', ;
- 'По данному полю можно определить наименование фирмы ; через таблицы Firm')
-
- * Создание первичного ключа (для таблицы Model)
- ALTER TABLE Model ADD PRIMARY KEY key_model TAG key_model
-
- * Формирование правил и сообщений об ошибке
- * (для таблицы Model)
- ALTER TABLE Model ALTER COLUMN swept_volume SET CHECK ; swept_volume>>0 ;
- ERROR "Значение рабочего объема не должно быть ; отрицательным"
- ALTER TABLE Model ALTER COLUMN quantity_drum SET CHECK ; quantity_drum >>= 1 ;
- ERROR "Количество цилиндров должно быть больше или равно 1"
-
- * Создание таблицы Firm
- CREATE TABLE Firm (key_firm i, name_firm c(20), ; key_country i)
-
- * Установка заголовков (для таблицы Firm)
- ? DBSETPROP ('Firm.key_firm', 'field', 'caption', ;
- 'Уникальный ключ фирмы')
- ? DBSETPROP ('Firm.name_firm', 'field', 'caption', ;
- 'Наименование фирмы')
- ? DBSETPROP ('Firm.key_country', 'field', 'caption', ;
- 'Уникальный ключ страны')
-
- * Создание первичного ключа (для таблицы Firm)
- ALTER TABLE Firm ADD PRIMARY KEY key_firm TAG key_firm
- ...
- * Создание таблицы Automobile_Passenger_Car
- CREATE TABLE Automobile_Passenger_Car (key_auto i, ; key_model i, date_issue d, cost n(10,2))
-
- * Установка заголовков
- * (для таблицы Automobile_Passenger_Car)
- ? DBSETPROP ('Automobile_Passenger_Car.key_auto', ; 'field', 'caption', 'Уникальный ключ автомобиля')
- ...
-
- * Создание первичного ключа
- * (для таблицы Automobile_Passenger_Car)
- ALTER TABLE Automobile_Passenger_Car ADD PRIMARY KEY ; key_auto TAG key_auto
-
- *Создание постоянных отношений
- ALTER TABLE Automobile_Passenger_Car ;
- ADD FOREIGN KEY key_model TAG key_model REFERENCES Model
-
- ALTER TABLE Model ;
- ADD FOREIGN KEY key_firm TAG key_firm REFERENCES Firm
-
- ALTER TABLE Model ;
- ADD FOREIGN KEY key_fuel_oil TAG key_fiuel REFERENCES ; Fuel_Oil
-
- ...
6.2. Access
Согласно сложившемуся мнению, СУБД Microsoft Access предназначена для конечных пользователей, которые легко и непринужденно создают
достаточно сложные приложения. Строят связи между таблицами, создают
изощренные запросы и на их основе проектируют формы и отчеты. Если
нужен какой-нибудь "наворот", то используют макросы. Сразу
оговоримся, что это вполне возможно, хотя мы уверены, что без программирования
даже в Access не обойтись.
В этом параграфе мы рассмотрим визуальные методы создания
баз данных в MS Access.
Основой любой системы обработки систематизированных данных являются таблицы. Казалось бы, вслед за этим может последовать вопрос: а почему
бы не использовать Excel, в котором таблицы и создавать не надо, они
уже давно созданы. Авторам известен случай, когда директор одного
из заводов, страшный поклонник Excel, требовал от специалистов по
информационному обеспечению построить автоматизированную систему управления
документооборотом на основе Microsoft Excel. Критерием приема на работу
на этом заводе программиста, да и любого другого специалиста, было
наличие твердых и уверенных познаний электронных таблиц известного
производителя программных продуктов. К сожалению, до конца проследить
за этой историей не удалось, возможно, что-нибудь получилось. Да и
почему нет - в конце концов, живем в свободной рыночной стране,
если сказали, что это АСУ, значит, это АСУ, и не рассказывайте нам
сказки про связи, сущности и уж тем более про ODBC.
В Access можно сконструировать 90 % приложения из данных
вам "кубиков", которые здесь называются объектами, и дописать
немножко кода для особо требовательных процессов.
Возможны контраргументы - "больно медленный продукт".
Уверяем вас, не медленней, чем Delphi, когда тот работает с данными.
Не делает EXE-файлы. Минус, но насколько важный? Время, когда надо
было "работать с дисковода", уже прошло.
Мы не будем никого разубеждать и что-либо доказывать. Наша
цель - показать, как строить базы данных в Access и как работать
с ними.
Access - достаточно тесно интегрированный в Microsoft
Office продукт. Попро-буйте провести следующую операцию. Откройте
любую таблицу в Excel. Наберите какие-нибудь табличные данные. Например,
как в следующей таблице:
First | Second | Third |
Вольво | 2 | 12.03.96 |
Волга | 56 | 12.04.96 |
Мерседес | 34 | 17.12.96 |
Тойота | 78 | 14.09.23 |
Теперь выделите область с данными и скопируйте ее в буфер. Если у вас еще не открыт Access, то откройте его. Для того, чтобы создать
контейнер базы данных, выберите в меню Файл команду Создать.
Либо воспользуйтесь значком с изображением белого листка бумаги, во
всех приложениях Microsoft означающим "создать новый файл".
В контейнере, который представляет собой графическое средство работы
с базой данных, отображаются все объекты, которые в ней содержатся.
Объекты каждого типа располагаются на своих страницах. Нас интересуют таблицы, поэтому переходим на страницу Таблицы. Выполнив операцию
Вставить, мы получаем новую таблицу. У нее есть один недостаток, на
который в принципе не стоит обращать внимания, - текстовые поля
всегда имеют длину в 255 символов.
Мы не призываем вас сразу же переводить таблицы из Excel в Access, это был просто маленький пример, показывающий интеграцию Access в
Microsoft Office.
Первое, с чего рекомендуется начинать - создание таблицы. Очевидно и, можно сказать, банально. Следует отметить одно "но" -
структура вашего приложения может быть достаточно сложной и не всегда
вписываться в рамки простых стандартов. Приведем несколько примеров.
Вы используете данные с сервера, в таком случае, возможно, вам не придется создавать таблицы, а надо присоединять таблицы с сервера.
Эта операция не намного сложнее, чем их создание.
Подобная же ситуация может сложиться, если на вашем предприятии применяют приложения, использующие другие процессоры данных. Вы можете совместно обрабатывать их, используя присоединенные таблицы. То есть вы работаете
на Access, а все остальные, например, на FoxPro. При этом используете
одни и те же таблицы в формате FoxPro 2.6.
Рассмотрим другой случай. Вы решили хранить таблицы в одной базе данных, а объекты их обработки и вывода - формы и отчеты - в другой.
В таком случае вы либо используете присоединенные таблицы, либо программным
способом создаете запросы к таблицам и используете их в своих формах.
Для начала рассмотрим обычный случай, который может охватить достаточно широкий круг задач. В Контейнере БД перейдите на вкладку Таблицы и
нажмите на кнопку Создать. Перед вами появится диалоговое окно Новая
таблица, показанное на рис. 6.9. В списке справа перечислены пять
пунктов, которые предоставляют различные варианты создания таблицы.
Рис. 6.9.
В первом случае на экран будет выведена готовая таблица для заполнения ее данными, как показано на рис. 6.10.
Рис. 6.10.
Во втором случае на экране появляется Конструктор таблиц, окно которого показано на рис. 6.11. Вооруженные знаниями типов полей, которые мы получили
в главе 3, можем перейти к конструированию. Для этого в первой колонке
нам надо ввести название поля, а во второй, как следует из ее названия,
выбрать тип из предлагаемого списка. В третьей колонке настоятельно
рекомендуем как можно подробнее описать, с какой целью это поле появилось
в таблице. Если таблиц много, то вы можете проявлять сколь угодно
бурную фантазию при выборе названия поля и все равно однажды не сможете
вспомнить, а для чего какое-то поле появилось. Обратим ваше внимание
на полезную информацию, которая выводится в правом нижнем углу. Вы
можете узнать, что бесполезно давать полю имя, число символов в котором
более 64. А если нажмете на клавишу F1, то узнаете, что нельзя
использовать точку, восклицательный знак и квадратные скобки. Пробелы
могут быть внутри названия, но нельзя использовать их в начале имени.
Рис. 6.11.
Для каждого типа поля в левой нижней части экрана высвечивается
свой набор свойств. Для текстового поля обязательно укажите длину.
Размеры по умолчанию вновь создаваемых текстовых полей можно установить
с помощью диалогового окна Параметры, вызов которого происходит посредством
задания одноименной команды в меню Сервис. В этом диалоге
выберите вкладку Таблицы/запросы, а в ней область с заголовком Размеры
полей по умолчанию, как это продемонстрировано на рис. 6.12. Опыт
подсказывает, что довольно часто найти оптимальную длину поля невозможно,
поэтому какое бы значение по умолчанию вы ни установили, свойство
"длина поля" редактировать придется часто. Главный принцип,
которым вы должны руководствоваться, - самое длинное значение,
которое вы введете в это поле, должно "чувствовать себя в нем
комфортно" и не быть усеченным. Можете особо не жалеть места.
Структура файла MDB такова, что лишнее пространство в поле, не занятое
символами, не хранится.
Можете провести эксперимент. Увеличьте размеры текстовых
полей, но не редактируйте записи. Потом проверьте размер. Он изменится.
Но не навсегда - есть способ вернуть его к прежнему размеру.
Необходимо использовать сжатие базы данных. Эта операция доступна
с помощью меню Сервис, в котором есть команда Служебные программы, одна из которых и сможет сделать базу данных более
компактной. Эту операцию надо проводить периодически, так как, даже
если вы удалите таблицу размером в пять мегабайт, ваша база данных
автоматически не уменьшится, пока вы не выполните сжатие. Меню Сервис
динамически меняет свое содержимое и для того, чтобы увидеть в нем
команду Служебные программы, необходимо закрыть базу
данных.
Рис. 6.12. Установка размеров поля в Access по умолчанию
Следующее свойство поля - Формат - служит для вывода значений
поля в более удобном виде. Например, вам хочется выводить телефонные
номера в общепринятом виде, то есть вот так: (812)259-4277, а хранить
в таблице в виде того же набора цифр, но без скобок и дефисов. Тогда
наберите в строке Формат следующее выражение:
- (000)00-00000
Теперь данные будут выводится так, как мы привыкли видеть телефонные номера, хотя храниться будут совсем по-другому. Для данного поля лучше
использовать текстовый тип данных. Поэкспериментируйте - поймете
почему.
Когда мы начнем вводить данные или редактировать их, то снова увидим строку типа 8125250495. Эту проблему можно решить с помощью свойства
Маска ввода. Наберите то же самое, что и для свойства Формат. Access
сам отредактирует введенное вами значение, оно будет выглядеть так:
- \(0\-000\)000\-00\-00
Если вы хотите подробнее ознакомиться с символами, которые используются при создании значений свойств Формат и Маска ввода, то приготовьтесь
потратить время - их достаточно много. На первых порах советуем
вам распечатать темы файла контекстной справки по этим свойствам.
Для некоторых типов полей вы можете воспользоваться встроенными значениями форматов. Особенно много их у поля типа "дата и время".
Следующее свойство - это Подпись поля, в английской версии Caption, то есть то, что мы привыкли называть заголовком. Подпись - это
альтернатива названия поля. При этом ограничение на количество символов
значительно превосходит аналогичное для название поля - здесь
можно написать целое произведение, так как вы можете использовать
2048 символов (к примеру, бесплатное объявление в Санкт-Петербургской
газете "Реклама-Шанс" не должно превышать 80 символов). Если
вы введете значение для этого свойства, то при просмотре таблицы оно
будет выводиться вместо заголовка поля, в противном случае, как вы
уже поняли, будет выводиться название поля.
Свойство Значение по умолчанию удобно использовать в различных случаях. Допустим, вы хотите знать дату и время появления новой записи в вашей
таблице. В таком случае сделайте значение поля по умолчанию равным
функции Now(). Теперь вы четко можете отследить, в какой
момент была добавлена новая запись.
В сочетании со свойством Условие на значение, свойство Значение по умолчанию становится еще более сильным ограничителем для желающих
вводить фальсифицированные данные. Установите свойство Условие на
значение равным следующему выражению:
- <<=Now() And >>Now()-1
Теперь никто не сможет отредактировать данные в этом поле и, к примеру, провести какую-нибудь операцию задним числом.
Все это, конечно, не совсем так просто. Но тем не менее вам удастся навести порядок в обработке ваших данных, а в сочетании со средствами
защиты вы сможете предохранить свои данные от любых дальнейших изменений,
не каждый любитель так называемого "взлома" сможет добраться
до них.
После того как пользователь попытается нарушить Условие на значение, выведется стандартное сообщение Microsoft Access. Это можно легко
преодолеть, установив значение свойства Сообщение об ошибке. Учтите,
что свойство имеет строчный тип данных, поэтому данное значение вводите
в кавычках. Можете сделать его равным значению, возвращаемому какой-либо
функцией, естественно, оно тоже должно быть строчным.
Свойство Обязательное поле требует, чтобы в поле было введено какое-нибудь значение.
Свойство Пустые строки не противоречит свойству Обязательное поле. Если вы установите значение этого свойство равным "Да", то
сможете вводить значения типа NULL, то есть отсутствие какого-либо
значения.
Каждое поле, кроме полей примечаний и объектов OLE, может быть индексировано, что значительно ускоряет поиск, но замедляет ввод и обновление данных.
Для того чтобы создать индекс, используйте свойство Индексированное
поле, при этом вы можете создать индекс, который не может иметь дублирующих
друг друга значений в разных записях или, напротив, допустить повторение
значений в индексированном поле. Но таким образом вы можете создать
только простые индексы, которые состоят из значений одного поля. Для
того чтобы создать сложные индексы, используйте команду Индексы
из меню Вид. Здесь вы можете в левой колонке ввести
название индекса, а во второй колонке последовательно указать поля,
которые добавляете в индекс (рис. 6.13).
Рис. 6.13. Создание сложного индекса в Access
Можно сделать поле первичным ключом, а затем использовать его для связи таблицы с другими таблицами. Причем это будет связь, которая
позволяет использовать контроль целостности данных.
Когда вы будете создавать базу данных, вам придется очень много общаться с заказчиком или постановщиком задачи и чертить различные схемы, обсуждать,
где какие данные будут храниться, как таблицы будут связываться. Если
у вас еще не выработался универсальный способ общения с пользователем
и воплощения выработанных идей, используйте Схему данных. Для того
чтобы вывести ее на экран выберите команду Схема данных в меню
Сервис или значок с изображением связанных таблиц в Стандартной
панели инструментов.
Из схемы данных, которая приведена на рис. 6.14, вы легко можете
попасть в Конструктор таблиц. Для этого выделите таблицу и нажмите
правую клавишу. В появившемся всплывающем меню выберите нужную команду.
Для того чтобы связать две таблицы, выберите поле в графическом изображении
таблицы и с помощью мыши перетащите на соответствующее поле в таблице,
с которой вы связываетесь. Обычно для связи используют ключевые поля,
так как в этом случае становятся доступными средства контроля целостности
данных, например каскадное обновление и каскадное удаление связанных
записей.
Рис. 6.14. Графическая схема созданной базы данных в Access
Все вышеизложенное можно проделать с помощью объектов доступа к данным, то есть создать таблицы и установить их свойства с помощью кода. Для
того чтобы узнать об этом, обратитесь к следующему параграфу данной
главы, в котором описывается построение БД в Microsoft Visual Basic.
Создав, подключив или импортировав таблицы, установив правила для полей, построив индексы и ключи и на их основе постоянно хранимые
связи, кое-где, к тому же, с контролем целостности данных, вы решили
львиную долю задачи. Правда, приходится отметить, что пожелания пользователя
могут меняться до самого последнего момента разработки, так что к
этому тоже надо быть готовым.
Создав таблицы, вы можете воспользоваться средством Анализ таблиц, который позволяет разбить данные из одной таблицы на несколько, если
это необходимо. При этом Access руководствуется принципом избыточности
данных, то есть если он заметит, что какие-то значения часто повторяются,
то предложит вынести их в отдельную таблицу. Соответственно, для того
чтобы таблицы могли разделяться, они должны содержать данные. Этот
способ рекомендуется использовать при импорте данных из других приложений
и переносе таблиц Excel в базу данных Access.
6.3. Visual Basic
Visual Basic, являясь универсальным средством разработки пользовательских программ, предоставляет весьма скудные средства для визуальной работы
с БД. Это не покажется вам неестественным, если вы помните, что он
использует общий с Access процессор БД и, следовательно, не имеет
значения, создана БД в Access или Visual Basic. Для работы с другими
форматами данных можно использовать ODBC.
В этом параграфе мы рассмотрим программные методы создания
БД в Visual Basic, обращая особое внимание на такой важный компонент,
как объекты для доступа к данным - DAO.
Visual Basic позволяет использовать два метода для работы с данными:
- с помощью специальных элементов управления для работы с данными;
- путем применения объектов для доступа к данным (DAO - Data Access Objects).
Если элементы управления данными позволяют практически без
программирования обеспечить элементарные возможности по просмотру
и редактированию информации в существующих БД, то использование объектов
для доступа к данным хотя и требует программирования, но зато предоставляет
самые широкие возможности по управлению базой данных. При этом не
стоит думать, что программист перед проектированием прикладной программы
должен выбрать один из методов. Наоборот, почти наверняка в своей
прикладной программе вы будете использовать как один, так и второй
способ работы с данными. В дальнейшем мы постараемся дать четкие рекомендации
по использованию этих двух методов в различных ситуациях, возникающих
при проектировании прикладной программы. В том случае, если вам интересны
технологии клиент-сервер, обратите внимание на специальные методы,
которые могут использоваться для доступа к данным в этом случае и
которые описаны в главе 8.
Модель управления данными, основанная на объектах DAO, представляет
собой коллекцию классов, которые моделируют структуру реляционной
базы данных.
Эти объекты имеют свойства и методы, которые позволяют выполнять все необходимые операции для управления базой данных, включая ее создание,
описание таблиц, полей и индексов, связей между таблицами, перемещения
по записям таблиц, выполнения запросов и т. д. Внутренний механизм
процессора данных транслирует эти операции с объектами для доступа
к данным в физические действия над файлами БД.
Visual Basic имеет две отдельные версии процессора данных и библиотек объектов для доступа к данным:
- версия 2.5 предназначена для написания программ, работающих в 16-битовой операционной системе (Windows 3.х и Windows for Work-groups);
- версия 3.0 - для 32-битовой ОС (Microsoft Windows 95 или Windows NT).
Написание прикладной программы для обработки данных в Visual
Basic схематично состоит из создания объектов для доступа к данным,
таких, например, как Database, TableDef, Field и Index, которые соответствуют
различным составляющим физической БД, к информации которой вы хотите
получить доступ. Используя соответствующие свойства и методы созданных
объектов, можно выполнять необходимые операции с базой. Увидеть результат
выполнения операций и обеспечить редактирование данных пользователем
можно с помощью экранных форм, в которых будут использоваться соответствующие
элементы управления.
Изложенный подход упрощает вашу прикладную программу и позволяет обойтись значительно меньшим количеством строк кода, написанного вручную,
а так же избавляет от необходимости непосредственного манипулирования
и поиска необходимых данных. Программа становится более гибкой, потому
что вы можете использовать те же самые объекты, свойства и методы
при работе с разнообразными поддерживаемыми форматами баз данных.
И если вам необходимо перейти от одного формата базы данных к другому
(например, при перенесении базы данных Visual FoxPro на SQL Server),
для этого потребуется сделать лишь небольшие изменения в программном
коде. Таким образом вы даже можете создавать прикладные программы,
которые будут соединять таблицы из двух и более различных баз данных
в одном запросе или отчете.
С помощью Visual Basic вы получаете доступ к БД, которые можно разбить на три категории:
- Базы данных Visual Basic, используют формат, аналогичный
Microsoft Access. Управление этими БД осуществляет непосредственно
процессор данных Visual Basic, что обеспечивает программе максимальную
гибкость и скорость работы.
- Доступ к форматам БД внешних СУБД для персональных систем,
таких как Btrieve, dBASE III, dBASE IV, Microsoft FoxPro и Paradox,
осуществляется с помощью метода последовательного доступа (ISAM -
Indexed Sequential Access Method). Это наиболее простой вариант технологии
ODBC, о чем более подробно речь пойдет в главе 8. Таким же образом
может осуществляться использование текстовых файлов или электронных
таблиц формата Microsoft Excel и Lotus 1-2-3.
- Данные, хранящиеся на сервере, для доступа к ним требуется
несколько более сложная технология с использованием отдельных драйверов
ODBC. Чтобы создать приложение для управления данными в архитектуре
клиент-сервер, из программы на сервер необходимо передать команды
SQL, впрочем, об этом вы прочитаете чуть позже, добравшись до главы 8.
Объекты для доступа к данным имеют иерархическую организацию,
в которой большинство классов относится к коллекциям классов, которые,
в свою очередь, принадлежат другому классу выше в иерархии. Полная
структура объектов для доступа к данным приведена на рис. 6.15.
Рис. 6.15. Иерархия объектов для доступа к данным в Visual Basic
Мы поместили этот рисунок не для того, чтобы напугать вас
мудреными словами "иерархия объектов". Этот способ хранения
объектов реализуется с помощью специального вида объекта, который
называется коллекцией. Единственная цель объекта коллекции состоит
в том, чтобы содержать другие объекты. Объекты, содержащиеся в данной
коллекции, всегда относятся к одному и тому же виду. Например, в коллекции
Indexes могут содержаться только объекты Index.
Обратите внимание, что элементы иерархии объектов DAO на
самом деле являются классами. Напомним, что класс - это не реальный
объект, который может выполнять в программе какие-то действия, а только
его прообраз. На основе определенного класса в программе мы создаем
объект, который тут же готов выполнять предусмотренные в классе функции.
Например, после такой строки в программе:
- Dim oWksp As Workspace
создается объект на основе класса Workspace, для ссылки на который используется переменная oWksp.
Так как главной темой обсуждения в этом параграфе является поведение объектов, которые создаются в программе для обеспечения заданной функциональности, термин "объект" используется чаще, чем "класс". Только
не забудьте, что в строгой формулировке, например, термин "объект
Database" означает "объект класса Database".
Как вы можете видеть на рис. 6.15, большинство объектов доступа
к данным представляется и как объект, и как коллекция. На самом верху
иерархии - процессор данных, который представляется объектом
DBEngine. Это единственный объект доступа к данным, который не может
быть включен в какой-то другой объект. Объект DBEngine имеет коллекцию
Workspaces (имя коллекции всегда имеет множественное число от имени
содержащихся объектов), которая в свою очередь, может содержать один
или большее количество объектов Workspace. Каждый объект Workspace
имеет коллекцию Databases, которая содержит один или большее количество
объектов Database и т. д.
Доступ к отдельным объектам коллекции может быть осуществлен по его номеру. Нумерация объектов в коллекции начинается с нуля. Например,
на первый объект TableDef в базе данных с именем MyDatabase можно
сослаться как MyDatabase.TableDefs(0). На второй объект TableDef можно
сослаться как MyDatabase.TableDefs(1) и т. д.
Объекты в иерархии должны указываться с полным перечнем "пути" от самого верхнего объекта, например:
- DBEngine.Workspaces(0).Databases(0).TableDefs(0).Fields_ "Customer")
Как видно из этого примера, некоторые коллекции, помимо цифрового индекса, для ссылки на конкретный объект допускают ссылку по имени.
Например, мы ссылаемся на объект коллекции Fields по значению свойства
Name объекта Field.
В этом случае, при явной ссылке на объект, в отличие от ссылки по
индексу, предпочтительнее использовать разделитель ! (восклицательный
знак). Таким образом, следующие выражения эквивалентны:
- MyTableDef.Fields("Customer")
- MyTableDef.Fields!Customer
Большинство объектов для доступа к данным имеют коллекции по умолчанию. Это позволяет использовать в программе более простой код, так как
в этом случае не требуется явного указания имени коллекции при ссылке
на объект из коллекции по умолчанию. Например, коллекцией по умолчанию
для объекта Recordset будет являться коллекция Fields. Для получения
значения поля Customer вы можете написать:
Cust = MyRecordset!Customer
что короче, чем
- Cust = MyRecordset.Fields!Customer
Использование заданных по умолчанию коллекций упрощает код в прикладной программе, потому что при использовании вложенных ссылок на объекты
заданные по умолчанию коллекции и составляют основную иерархию "пути"
до объектов.
Основная идея объектно-ориентированного программирования заключается в том, что данные и процедуры, относящиеся к отдельному объекту, сохраняются
все вместе внутри объекта. В Visual Basic, как и в других объектно-ориентированных
языках программирования, данные, относящиеся к объекту (установки
и атрибуты), называются свойствами, в то время как процедуры, с помощью которых
выполняются какие-либо действия над объектами, называются методами.
Таким образом, написание программы с использованием объектов для доступа к данным заключается в создании переменной, которая будет выполнять
функции ссылки на объект, а затем в манипулировании объектом путем
выполнения соответствующих методов и установки требуемых значений
свойств. В качестве примера давайте рассмотрим следующий фрагмент
программы:
- * Определяем переменные для ссылки на объекты
- Dim MyDB As Database, MyWS As Workspace, MyRS As_ Recordset
- * Открываем таблицу Clients в БД ACCOUNTS.MDB
- Set MyWS = DBEngine.Workspaces(0)
- Set MyDB = MyWS.OpenDatabase("ACCOUNTS.MDB")
- Set MyRS = MyDB.OpenRecordSet("Clients")
- * Устанавливаем порядок вывода записей
- MyRS.Index = "ClientID"
Для открытия базы данных мы используем метод OpenDatabase
объекта Work-space и привязываем к ней переменную MyDB с целью обеспечения
дальнейших ссылок. Обеспечить доступ к записям таблицы Clients призван
метод OpenRecordset. Требуемый логический порядок вывода записей мы
устанавливаем с помощью свойства Index, которому присваиваем значение,
соответствующее имени нужного индекса - ClientID.
Для большинства объектов доступа к данным программист может
задать новые свойства, не предусмотренные стандартно в языке. Эта
возможность позволяет гибко настраивать объекты в пользовательской
программе и как угодно расширять перечень данных, сохраняемых вместе
с объектом.
Теперь пришло время остановиться на каждом из объектов для
доступа к данным, чтобы вы смогли получить представление о тех возможностях,
которые могут быть реализованы с их помощью в прикладной программе.
В табл. 6.4 приведен список свойств, а в табл. 6.5 - список
методов, которые можно использовать для объектов каждого вида. В дальнейшем,
при описании методов работы с данными, мы дадим более подробное описание
перечисленных свойств и методов, но если вы хотя бы немного помните,
что делали на уроках английского языка в школе, то уже сейчас сможете
сделать некоторые выводы, изучив названия приведенных в таблицах свойств
и методов.
DBEngine
Этот объект верхнего уровня ассоциируется с процессором
данных. Он устанавливает системные параметры процессора данных и обеспечивает
возможность работы с БД за счет автоматического создания объекта Workspace
с номером 0. Коллекцией по умолчанию для этого объекта является Workspaces.
Workspace
Используется для поддержки транзакций, является контейнером
для открытой БД и обеспечивает секретность работы с данными. Объект
по умолчанию коллекции Workspaces - Workspaces(0) создается
автоматически, как только в программе задается первая ссылка на объекты
для доступа к данным. Этот объект может быть инициализирован с помощью
свойств Username и Password перед активизацией объекта DBEngine. Коллекцией
по умолчанию для этого объекта будет являться коллекция Databases.
Database
Этот объект корреспондируется с базой данных Visual Basic,
внешней БД или соединением ODBC. Он используется для определения таблиц,
связей и запросов к БД, а также для открытия объекта Recordset. Коллекцией
по умолчанию является TableDefs.
TableDef
Каждый объект TableDef в коллекции TableDefs описывает соответствующую таблицу в текущей БД или присоединенную таблицу во внешней БД. В последнем случае с помощью этого объекта мы не можем изменить описание внешней
таблицы. Коллекцией по умолчанию является Fields.
QueryDef
Этот объект является описанием сохраняемого запроса, который
представляет собой объектный код с операторами SQL. С помощью этого
объекта мы можем просмотреть и отредактировать при необходимости код,
сохраняемый в запросе, установить его параметры и выполнить запрос.
Коллекцией по умолчанию является Fields.
Recordset
Представляет собой курсор, который используется для отображения данных из таблицы БД или результата запроса. Курсор запоминает необходимые
данные в виде набора записей в буфере и обеспечивает перемещение по
этим записям с помощью методов Move, Seek и Find, выделяя текущую,
что позволяет просматривать, обновлять или удалять необходимые данные.
Этот объект является временным, и как только он закрывается, удаляется
из коллекции, а все ассоциированные с ним данные из памяти. Коллекцией
по умолчанию является Fields.
Field
Этот объект ассоциируется с колонкой данных, имеющих одинаковый тип и свойства. Коллекция объектов Field представляет собой запись
в курсоре объекта Recordset. Данные в курсоре могут быть прочитаны
и изменены с помощью свойства Value объекта Field. Как только указатель
записи в курсоре перемещается на новую запись, все объекты Field в
коллекции автоматически обновляются новыми значениями данных.
Index
В этом объекте хранится индекс, относящийся к объектам TableDef
или Recordset, основанному на таблице. Нужный индекс может быть установлен
с помощью свойства Index.
Parameter
Запоминает параметры для параметрического запроса. Коллекция
Parameters объекта QueryDef позволяет получить или установить параметры
для выполняемого запроса.
User
Используется для описания и поддержки условий доступа пользователей к информации, хранящейся в БД. Объект DBEngine поддерживает коллекцию
пользователей. Добавление или удаление членов коллекции Users соответственно
создает или стирает бюджеты пользователей. Каждый объект User создается
с именем и паролем. Доступ к таким объектам, как TableDef или QueryDef,
с помощью этого объекта может быть назначен индивидуально для конкретного
пользователя.
Group
Представляет собой коллекцию пользователей с одинаковыми
правами доступа к данным. Объект DBEngine поддерживает коллекцию групп
пользователей. Каждый пользователь в группе наследует те права доступа,
которые предоставлены группе. Это облегчает управление доступом к
данным для нескольких пользователей.
Relation
Этот объект используется для хранения данных о связях между
полями двух объектов TableDef. Каждый объект Database имеет единственную
коллекцию объектов Relation. Процессор данных использует информацию
о связях для определения возможности обновления и удаления данных
без потери целостности данных в БД.
Property
Запоминает значения свойств какого-либо объекта. При этом
сохраняются как встроенные в язык свойства, так и добавленные для
данного объекта программистом. Свои свойства можно описать для следующих
объектов:
- Database
- TableDef
- QueryDef
- TableDef.Index
- TableDef.Field
- QueryDef.Field
Container
Этот объект используется для соединения с объектами Document
и перечисления объектов, размещаемых в БД, включая объекты, определяемые
пользователь-ской программой. Каждый объект Database может иметь только
одну коллекцию объектов Container.
Document
Позволяет заносить данные в объект Container. Например,
права пользователя для доступа к данным могут быть установлены в этих
объектах для получения или уничтожения определенных привилегий.
В таблицах 6.4 и 6.5 используются следующие условные
обозначения:
1 | DBEngine | 2 | Workspace |
3 | Database | 4 | TableDef |
5 | QueryDef | 6 | Recordset |
7 | Field | 8 | Index |
9 | Parameter | 10 | User |
11 | Group | 12 | Relation |
13 | Property | 14 | Container |
15 | Document |
Таблица 6.4. Свойства объектов для доступа к данным
Свойства | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
AllowZeroLength | | | | | | | + | | | | | | | | |
AllPermissions | | | | | | | | | | | | | | + | + |
Attributes | | | | + | | | + | | | | | + | | | |
BOF | | | | | | + | | | | | | | | | |
Bookmark | | | | | | + | | | | | | | | | |
Bookmarkable | | | | | | + | | | | | | | | | |
CacheSize | | | | | | + | | | | | | | | | |
CacheStart | | | | | | + | | | | | | | | | |
Clustered | | | | | | | | + | | | | | | | |
CollatingOrder | | | + | | | | + | | | | | | | | |
ConflictTable | | | | + | | | | | | | | | | | |
Connect | | | + | + | + | | | | | | | | | | |
Container | | | | | | | | | | | | | | | + |
CreateGroup | | | | | | | | | | | | | | | |
CreateUser | | | | | | | | | | | | | | | |
CurrentUsers | | | + | | | | | | | | | | | | |
DateCreated | | | | + | + | ++ | | | | | | | | | + |
DataUpdatable | | | | | | | + | | | | | | | | |
Default User | + | | | | | | | | | | | | | | |
Default Password | + | | | | | | | | | | | | | | |
DefaultValue | | | | | | | + | | | | | | | | |
DesignMaster | | | + | | | | | | | | | | | | |
EOF | | | | | | + | | | | | | | | | |
Fields | | | | | | | | + | | | | | | | |
Filter | | | | | | + | | | | | | | | | |
Foreign | | | | | | | | + | | | | | | | |
ForeignName | | | | | | | + | | | | | | | | |
ForeignTable | | | | | | | | | | | | + | | | |
IgnoreNull | | | | | | | | + | | | | | | | |
Index | | | | | | + | | | | | | | | | |
Inherited | | | | | | | | | | | | | + | | |
IniPath | + | | | | | | | | | | | | | | |
LastModified | | | | | | + | | | | | | | | | |
LastUpdated | | | | + | + | ++ | | | | | | | | | |
LockEdits | | | | | | + | | | | | | | | | |
LoginTimeout | + | | | | | | | | | | | | | | |
Name | | + | + | ++ | ++ | ++ | ++ | ++ | ++ | ++ | ++ | ++ | ++ | ++ | + |
NewPassword | | | | | | | | | | | | | | | |
NoMatch | | | | | | + | | | | | | | | | |
OrdinalPosition | | | | | | | + | | | | | | | | |
Owner | | | | | | | | | | | | | | + | + |
Password | | + | + | | | | | | | ++ | | | | | |
PercentPosition | | | | | | + | | | | | | | | | |
Permissions | | | | | | | | | | | | | | | + |
PID | | | | | | | | | | + | + | | | | |
Primary | | | | | | | | + | | | | | | | |
Owner | | | | | | | | | | | | | | | |
QueryTimeout | | | + | | + | | | | | | | | | | |
RecordCount | | | | + | | + | | | | | | | | | |
ReplicaDescription | | | + | | | | | | | | | | | | |
ReplicaID | | | + | | | | | | | | | | | | |
ReplicaSetDescription | | | + | | | | | | | | | | | | |
Required | | | | | | | + | + | | | | | | | |
Restartable | | | | | | + | | | | | | | | | |
ReturnsRecords | | | | | + | | | | | | | | | | |
Signature | | | + | | | | | | | | | | | | |
Size | | | | | | | + | | | | | | | | |
Sort | | | | | | + | | | | | | | | | |
SourceField | | | | | | | + | | | | | | | | |
SourceTable | | | | | | | + | | | | | | | | |
SourceTableName | | | | + | | | | | | | | | | | |
SQL | | | | | + | | | | | | | | | | |
SystemDbPath | + | | | | | | | | | | | | | | |
Table | | | | | | | | | | | | + | | | |
Transactions | | | + | | | + | | | | | | | | | |
Type | | | | | + | + | ++ | | ++ | | | | ++ | | |
Unique | | | | | | | | | | | | | | | |
Updatable | | | + | + | ++ | ++ | | | | | | | | | |
UserName | | + | | | | | | | | | | | | | + |
ValidateOnSet | | | | | | | + | | | | | | | | |
ValidationRule | | | | + | | + | ++ | | | | | | | | |
ValidationText | | | | + | | + | ++ | | | | | | | | |
Value | | | | | | | + | | + | | | | ++ | | |
Version | + | | + | | | | | | | | | | | | |
Таблица 6.5. Методы объектов для доступа к данным
Методы | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
AddNew | | | | | | + | | | | | | | | | |
AppendChunk | | | | | | | + | | | | | | | | |
BeginTrans | | + | | | | | | | | | | | | | |
Clone | | | | | | + | | | | | | | | | |
Close | | + | ++ | | ++ | + | | | | | | | | | |
CommitTrans | | + | | | | | | | | | | | | | |
CompactDatabase | + | | | | | | | | | | | | | | |
CopyFields | | | | | | + | | | | | | | | | |
CreateDatabase | | + | | | | | | | | | | | | | |
CreateField | | | | + | | | | ++ | | | | ++ | | | |
CreateGroup | | + | | | | | | | | + | | | | | |
CreateInde+ | | | | ++ | | | | | | | | | | | |
CreateProperty | | | + | ++ | ++ | | ++ | ++ | | | | | | | |
CreateQueryDef | | | + | | | | | | | | | | | | |
CreateRelation | | | + | | | | | | | | | | | | |
CreateReplica | | | + | | | | | | | | | | | | |
CreateTabledef | | | + | | | | | | | | | | | | |
CreateUser | | + | | | | | | | | | ++ | | | | |
CreateWorkspace | + | | | | | | | | | | | | | | |
Delete | | | | | | + | | | | | | | | | |
Edit | | | | | | + | | | | | | | | | |
Execute | | | + | | ++ | | | | | | | | | | |
FieldSize | | | | | | | + | | | | | | | | |
FillCache | | | | | | + | | | | | | | | | |
FindFirst | | | | | | + | | | | | | | | | |
FindLast | | | | | | + | | | | | | | | | |
FindNext | | | | | | + | | | | | | | | | |
FindPrevious | | | | | | + | | | | | | | | | |
GetChunk | | | | | | | + | | | | | | | | |
GetRows | | | | | | + | | | | | | | | | |
Idle | + | | | | | | | | | | | | | | |
Move | | | | | | + | | | | | | | | | |
MoveFirst | | | | | | + | | | | | | | | | |
MoveLast | | | | | | + | | | | | | | | | |
MoveNext | | | | | | + | | | | | | | | | |
MovePrevious | | | | | | + | | | | | | | | | |
MoveReplica | | + | | | | | | | | | | | | | |
NewPassword | | | | | | | | | | | | | | | |
OpenDatabase | | | | | | | | | | | | | | | |
OpenRecordset | | | + | ++ | ++ | ++ | | | | | | | | | |
RefreshLink | | | | + | | | | | | | | | | | |
RegisterDatabase | + | | | | | | | | | | | | | | |
RepairDatabase | + | | | | | | | | | | | | | | |
Requery | | | | | | + | | | | | | | | | |
Rollback | | + | | | | | | | | | | | | | |
Seek | | | | | | + | | | | | | | | | |
Synchronize | | | + | | | | | | | | | | | | |
Update | | | | | | + | | | | | | | | | |
Теперь, когда вы получили представление о концепции использования объектов доступа к данным и процессора данных для управления БД, мы
можем обсудить, как использовать этот инструментарий для создания
базы данных.
В Visual Basic существует несколько способов создания БД.
На этапе разработки прикладной программы можно использовать самый простой способ - с помощью Data Manager. После запуска Visual
Basic в меню Add-Ins выберите команду Data Manager. В его окне в меню
File выберите команду New Database. Задайте имя для создаваемой БД
и выберите папку, в которой она будет располагаться. В окне Data Manager
появится окно с именем новой БД, как это видно на рис. 6.16. С его
помощью вы также можете внести в структуру БД необходимые изменения,
добавить или отредактировать хранящиеся в ней данные.
Рис. 6.16. Создание базы данных с помощью Data Manager
Второй способ создания БД основывается на использовании в Visual Basic формата хранения данных Microsoft Access. Тем самым любая БД, созданная
в СУБД Access 7.0, может быть "полнокровно" использована в
программе, написанной на Visual Basic.
Естественно, посредством технологии ODBC мы можем создать, а в дальнейшем управлять из программы Visual Basic базой данных, созданной в любой
другой СУБД при наличии соответствующего драйвера.
Перечисленные варианты, как правило, не приемлемы, если в соответствии с заданной функциональностью необходимо создание БД в процессе работы
прикладной программы. Поэтому использование объектов доступа к данным
для создания БД обеспечивает максимальную гибкость и самые широкие
возможности в работе. Перед тем как использовать объекты для доступа
к данным, не забудьте убедиться, что установлена ссылка на соответствующую
библиотеку. В меню Tools при задании команды References
в появляющемся диалоговом окне должна быть помечена библиотека Microsoft
DAO 3.0 Object Library.
Для создания новой БД в меню File Visual Basic выберем команду New Project. Назовем проект Create_DB. Создадим
в проекте программный модуль путем выполнения команды Module
в меню Insert. После в этом же меню выполним команду
Procedure. В появившемся диалоговом окне напишем имя
создаваемой процедуры - Main, для типа процедуры выберем Sub,
а для диапазона действия - Public. После нажатия кнопки OK появится
шаблон, готовый для написания программного кода, как это показано
на рис. 6.17. Далее необходимо выполнить следующие действия.
Рис. 6.17. Шаблон для написания программы
1. Используйте оператор Dim для создания новых переменных, с помощью которых будет выполняться ссылка на соответствующий объект,
включенный в БД. Дополнительно к объектам DBEngine и Workspace, которые
определяют рабочую среду, необходимо иметь:
- Один объект Database.
- Один объект TableDef для каждой таблицы.
- Один объект Field для каждого поля каждой таблицы.
- Один объект Index для каждого индекса таблицы.
Таким образом, для создания фрагмента БД Autostore, состоящего из двух связанных таблиц Customer и Account, мы должны определить следующие
переменные:
- Public Sub Main()
- ' Определяем переменные
- Dim oAutoDB As Database, oAutoWs As Workspace
- Dim oCustomerTd As TableDef, oAccountTd As TableDef
- Dim oCustomerFlds(8) As Field, oAccountFlds(7) As Field
- Dim oCustomerIdx As Index, oAccountIdx(2) As Index
- Dim oAutoRel As Relation
- Dim oIndexFld(3), oRelFld As Field
Для непосредственного создания БД используйте метод
CreateDatabase объекта Workspace:
- Set oDBVar = [oWSVar.]CreateDatabase(cDataBaseName,
- Locale [, Options])
где
- oDBVar - имя переменной для ссылки на БД;
- oWSVar - имя переменной для ссылки на объект Workspace;
- cDataBaseName - имя создаваемой БД, которому может
предшествовать указание пути доступа к файлам;
- Locale - последовательность расположения символов
в таблицах БД при сортировке или индексировании данных. Для России
наиболее подходящим может быть использование последовательности, соответствующей
стандартной таблице расположения символов, которая устанавливается
заданием константы dbLangGeneral, или последовательности, соответствующей
русскому алфавиту. Для этого надо использовать константу dbLangCyrillic.
- Options - задает дополнительные параметры для БД.
Например, можно использовать константу dbEncrypt для шифрования данных
в создаваемой БД.
Для создания БД Autostore используем следующий код:
- Set oAutoWs = DBEngine.Workspaces(0)
- Set oAutoDB = oAutoWs.CreateDatabase("AUTOSTORE.MDB",_ dbLangGeneral)
Чтобы создаваемые файлы при записи на диск оказались в нужном месте, можно использовать операторы ChDrive и ChDir.
3. Используйте метод CreateTableDef объекта Database для создания таблиц в БД:
- Set oTDVar = oDBVar.CreateTableDef([cName
- [, Attributes [, Source [,]]]])
где
- oTDVar - имя переменной для ссылки на объект TableDef.
- oDBVar - имя переменной для ссылки на
объект Database.
- cName - имя создаваемой таблицы. Оно
должно начинаться с буквы и иметь не более 40 символов. В имени таблицы
не должно использоваться знаков пунктуации и пробелов.
- Attributes - устанавливает дополнительные
характеристики для создаваемой таблицы, в основном используемые для
внешних источников данных.
- Source - указывает имя таблицы внешней БД, которая будет являться источником данных.
- Connect - определяет характеристики соединения в случае использования внешнего источника данных.
Создадим две таблицы в БД Auto_Store, используя следующие строки:
- Set oCustomerTd = oAutoDB.CreateTableDef("Customer")
- Set oAccountTd = oAutoDB.CreateTableDef("Account")
4. Для создания полей в таблице используйте метод CreateField объекта TableDef:
- Set oFVar = oTDVar.CreateField([cName [, Type [, Size]]])
где
- oFVar - имя переменной для ссылки на объект
Field.
- oTDVar - имя переменной для ссылки на объект TableDef.
- cName - имя создаваемого поля. Правила задания
имени поля такие же, как для имен таблиц.
- Type - тип создаваемого поля. В Visual Basic
вы можете использовать следующие константы для указания типа поля:
- dbDate - дата и время;
- dbText - символьное;
- dbMemo - поле примечаний;
- dbBoolean - логическое (значения Yes/No);
- dbInteger - целое число (2 байта);
- dbLong - целое число двойной точности (4 байта);
- dbCurrency - денежное выражение;
- dbSingle - числовое;
- dbDouble - числовое с плавающей точкой двойной точности;
- dbByte - целое положительное число;
- dbLongBinary - символьная строка для ссылки на OLE-объект.
- Size - ширина создаваемого поля. Этот параметр
необходимо указывать только для символьных полей (1 - 255).
Проиллюстрируем использование этого метода на примере создания нескольких полей для таблицы Customer:
- Set oCustomerFlds(0) = oCustomerTd.CreateField("KEY_CUSTOMER", dbLong)
- ` Установим для этого поля автоматическое приращение
- ` значения с помощью свойства Attributes объекта Field
- oCustomerFlds(0).Attributes = dbAutoIncrField
- Set oCustomerFlds(1) =_ oCustomerTd.CreateField("NAME_CUSTOMER", dbText, 100)
- ...
5. Для создания индексов используйте метод CreateIndex объекта TableDef:
- Set oIVar = oTDVar.CreateIndex([cName])
где
- olVar - имя переменной для ссылки на объект Index.
- oTDVar - имя переменной для ссылки на объект TableDef.
- cName - имя индекса. Правила его задания такие же, как для имени таблицы.
Необходимые характеристики для создаваемого индекса можно задать с помощью соответствующих свойств объекта Index (см. табл. 6.4). Для
таблицы Customer создание первичного индекса может быть выполнено
следующим образом:
- Set oCustomerIdx = oCustomerTd.CreateIndex("CUSTOMER_ID")
- oCustomerIdx.Primary = True
- oCustomerIdx.Unique = True
Теперь следует с помощью метода CreateField создать поле, для того чтобы указать, какое поле будет использовано в качестве ключевого,
как это показано в следующем примере:
- Set oIndexFld(0) =_ oCustomerIdx.CreateField("KEY_CUSTOMER")
6. Установите отношение между таблицами. Для этого используйте метод CreateRelation объекта Database:
- Set oRelVar = oDBVar.CreateRelation([cName
- [, cParentTable [,cChildTable
- [, Attributes]]]])
где
- oRelVar - имя переменной для ссылки на объект Relation.
- oDBVar - имя переменной для ссылки на объект Database.
- cName - имя создаваемого объекта. Правила его составления такие же, как для таблицы.
- cParentTable - имя родительской таблицы в создаваемом отношении.
- cChildTable - имя дочерней таблицы в создаваемом отношении.
- Attributes - задает тип создаваемого отношения за счет использования следующих констант:
- dbRelationUnique - отношение "один к одному".
- dbRelationDontEnforce - в отношении не поддерживается целостная ссылочность.
- dbRelationInherited - отношение существует не в текущей БД между двумя присоединенными таблицами.
- dbRelationLeft - в родительской таблице могут оставаться записи, не имеющие соответствующих записей в дочерней таблице.
- dbRelationRight - в дочерней таблице могут оставаться записи, не имеющие соответствующих записей в родительской таблице.
- dbRelationUpdateCascade - в отношении будет поддерживаться каскадное обновление.
- dbRelationDeleteCascade - в отношении будет поддерживаться каскадное удаление.
После создания отношения необходимо создать поле для отношения в родительской таблице и указать соответствующее ему поле в дочерней таблице, как
это показано в следующем примере:
- ' Создание связи между таблицами "Один ко многим"
- Set oAutoRel = oAutoDB.CreateRelation("CustToAcc",_ "Customer", "Account")
- Set oRelFld = oAutoRel.CreateField("KEY_CUSTOMER")
- oRelFld.ForeignName = "KEY_CUSTOMER"
7. Добавьте созданные поля и индексы в соответствующие таблицы,
а таблицы и отношение - в БД с помощью метода Append. Обратите
внимание, что после добавления объектов в соответствующие коллекции
большинство их свойств не может быть изменено. Для изменения свойств
в этом случае вам придется сначала удалить соответствующий объект
с помощью метода Delete, а затем создать его заново с требуемыми значениями
свойств и после этого добавить в коллекцию.
- Collection.Append oVar
где
- Collection - имя коллекции, в которую добавляется объект;
- oVar - имя переменной для ссылки на добавляемый объект.
Для нашего примера фрагмент кода, обеспечивающий добавление объектов в коллекции, будет выглядеть следующим образом:
- ` Добавляем поля в таблицы
- oCustomerTd.Fields.Append oCustomerFlds(0)
- oCustomerTd.Fields.Append oCustomerFlds(1)
- . . .
- ` Добавляем поля в индексы
- oCustomerIdx.Fields.Append oIndexFld(0)
- oAccountIdx(0).Fields.Append oIndexFld(1)
- oAccountIdx(1).Fields.Append oIndexFld(2)
- ` Добавляем поля в отношение
- oAutoRel.Fields.Append oRelFld
- ` Добавляем индексы в таблицы
- oCustomerTd.Indexes.Append oCustomerIdx
- oAccountTd.Indexes.Append oAccountIdx(0)
- oAccountTd.Indexes.Append oAccountIdx(1)
- ` Добавляем таблицы в БД
- oAutoDB.TableDefs.Append oCustomerTd
- oAutoDB.TableDefs.Append oAccountTd
- ` Добавляем отношение в БД
- oAutoDB.Relations.Append oAutoRel
Для ясности в примере мы использовали различные переменные для каждого объекта доступа к данным. На практике обычно для сокращения объема
кода используют одну и ту же переменную сначала для создания объекта,
а после его добавления в коллекцию - для ссылки на следующий
объект.
После создания БД вы можете использовать объекты доступа к данным для программного изменения ее структуры. Модификация БД очень похожа
на те действия, которые мы выполняли при ее создании. В большинстве
случаев для добавления объектов достаточно использовать те же самые
методы Create и Append. Вы также можете добавлять в БД новые таблицы,
добавляя новые объекты TableDef или новые поля и индексы, добавляя
новые объекты Field и Index в существующие таблицы. Если вам больше
нравится SQL, используйте для модификации БД операторы этого языка.
Давайте посмотрим на следующий простейший пример добавления таблицы в существующую БД с помощью объектов DAO:
- Dim oDB As Database
- ' Переменная для нового объекта TableDef
- Dim oNewTd As TableDef
- Dim oNewFld As Field' Переменная для нового объекта Field
- ' Открываем БД
- Set oDB =_ DBEngine.Workspaces(0).OpenDatabase("AUTOSTORE.MDB")
- Set oNewTd = oDB.CreateTableDef("Новая таблица")
- Set oNewFld = oNewTd.CreateField("Новое поле", dbInteger)
- ' Добавляем новое поле в таблицу
- oNewTd.Fields.Append oNewFld
- oDB.TableDefs.Append oNewTd' Добавляем таблицу в БД
- oDB.Close ` Закрываем БД
Естественно, существующие в БД объекты могут быть удалены. Мы можем использовать метод Delete для удаления таблицы, добавленной в БД в
предыдущем примере:
- oDB.TableDefs.Delete "Новая таблица"
Следует иметь в виду, что при удалении индексного поля сначала следует удалить сам индекс и связанные с ним объекты Relation. Лишь после
этого вы сможете удалить объекты Field или TableDef, являющиеся составными
частями отношения.
На прилагаемой к книге дискете помещен полный код программы для создания БД Auto_Store в Visual Basic.
6.4. MS SQL Server
Создать базу данных в MS SQL Server можно несколькими путями:
визуально, находясь в Microsoft SQL Enterprise Manager, программно,
посредством редактора Microsoft ISQL/w, программно посредством технологии
SQL pass-through из клиентского приложения и путем наращивания (upsizing)
локальной БД.
В этом параграфе мы опишем создание базы данных как программным путем, так и с помощью процесса наращивания.
Программный путь создания БД посредством одной из составных
частей MS SQL Server - редактора Microsoft ISQL/w - реализуется
простым набором команд, которые мы можем тут же запускать на выполнение.
Редактор ISQL/w имеет несколько страниц, на первой из которых мы можем
набирать необходимые команды, как это показано на рис. 6.18. Набранную
команду можно тут же запустить на выполнение, нажав кнопку с треугольником
в верхней правой части окна. На вкладке Results вы можете просмотреть
результат выполнения команды, если она предусматривает вывод данных
(рис. 6.19). Остальные вкладки обеспечивают возможность очень наглядного
графического представления условий выполнения команды. Вы можете убедиться
в этом, взглянув на рис. 6.20 и 6.21.
Рис. 6.18. Набор команды в редакторе SQL Server
Рис. 6.19. Просмотр результатов выполнения команды в SQL Server
Рис. 6.20. Графическое представление выборки в SQL Server
Рис. 6.21. Графическое представление отношение в выборке между таблицами в SQL Server
Прежде чем создать БД, необходимо решить, на каком из существующих устройств - Device - наша база данных будет храниться,
либо создать подобное устройство.
Device - файл, который MS SQL Server использует для
размещения одной или нескольких баз данных, заранее резервируя место
на диске.
Размер Device указывается уже при его создании. При этом
необходимо учитывать, что база данных может находиться на нескольких
устройствах, то есть Device может хранить часть базы данных. Устройство
создается следующей командой:
- DISK INIT
- NAME = cLogicalName,
- PHYSNAME = cPhysicalName,
- VDEVNO = nValue1,
- SIZE = nValue2
- [, VSTART = Adress]
Описание опций этой команды приведено в следующей таблице:
Предложение | Описание |
NAME | Название устройства, которое будет использоваться внутри SQL для обращения к нему. Не может превышать 30 символов. |
PHYSNAME | Дисковый файл, в котором устройство будет храниться. Его название должно удовлетворять требованиям операционной системы. |
VDEVNO | Уникальный номер устройства между 1 и 255. |
SIZE | Количество 2-килобайтных блоков. Минимальное число - 500
блоков или 1 Mбайт. |
VSTART | Смещение первой базы данных, которая будет храниться в устройстве. По умолчанию 0. |
В качестве примера создадим устройство Rdev_lib, где SAMP_LIB.DAT - имя файла, который является хранилищем устройства:
- DISK INIT
- NAME = 'Rdev_lib',
- PHYSNAME = 'C:\SQL_60\DATA\SAMP_LIB.DAT',
- VDEVNO=1,
- SIZE = 5120
На рис. 6.22 приводится результат создания устройства, который
мы можем увидеть в File Manager Windows NT.
Рис. 6.22.
Далее обязательно необходимо создать устройство Rdev_log
для журнала транзакций БД:
- DISK INIT
- NAME = 'Rdev_log',
- PHYSNAME = 'C:\SQL_60\DATA\SAMP_LOG.DAT',
- VDEVNO=2,
- SIZE = 2048
На рис. 6.23 и 6.24 показаны характеристики вновь созданных
устройств, а на рис. 6.25 - их отображение в Server Manager.
Теперь мы можем создать базу данных Auto_Store, которая
будет размещаться на двух устройствах: Rdev_lib и Rdev_log, где числа
10 и 4 обозначают резервируемое пространство в мегабайтах. Синтаксис
команды, с помощью которой создается база данных:
Рис. 6.23.
Рис. 6.24.
Рис. 6.25.
- CREATE DATABASE DatabaseName
- [ON {DEFAULT | DatabaseDevice} [= Size]
- [, DatabaseDevice [= Size]]...]
- [LOG ON DatabaseDevice [= Size]
- [, DatabaseDevice [= Size]]...]
- [FOR LOAD]
Аргумент DatabaseName указывает имя вновь создаваемой базы данных. Как мы уже упоминали и это видно из приведенного
синтаксиса, вы можете распределить базу данных между несколькими устройствами,
резервируя определенный размер на каждом устройстве. Если вы укажете
ключевое слово DEFAULT, то база данных будет создана на устройстве
по умолчанию, которое определено в таблице Sysdevices, то есть вы
можете написать: ON DEFAULT = 5. Устройство, где будет храниться журнал
транзакций базы данных, вы можете установить с помощью ключевого слова
LOG ON. Можно указать более, чем одно устройство.
Опция FOR LOAD резервирует базу данных для перезагрузки предыдущей копии базы. Если вы указываете опцию FOR LOAD, никто не сможет ни
случайно, ни преднамеренно редактировать базу данных между временем
создания базы данных и ее загрузкой.
- CREATE DATABASE Auto_Store ON Rdev_lib = 10 LOG ON Rdev_log = 4
База данных Auto_Store существует, но пока она совершенно пуста.
Создадим в ней две таблицы: Country и Firm, связанные по полю key_country.
- USE Auto_Store
Создаем таблицу Country:
- CREATE TABLE Country (key_country smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_country varchar(20) NOT NULL, times_ timestamp)
Создаем таблицу Firm:
- CREATE TABLE firm (key_firm smallint IDENTITY(1,1)
- PRIMARY KEY CLUSTERED, name_firm varchar(20) NOT NULL,
- key_country smallint REFERENCES country(key_country),
- times_ timestamp)
На рис. 6.26 приведен результат выполнения команд CREATE TABLE и ALTER TABLE для таблицы Model, а на рис. 6.27 - список всех созданных таблиц в Server Manager.
Рис. 6.26. Отображение данных для таблицы Model в Manage Tables
Рис. 6.27.
Приведем правила SQL Server для присвоения идентификаторов полей:
- Названия должны быть длиной от 1 до 30 символов.
- Первым символом может быть буква или знаки "_", "@",
"#". Идентификаторы, которые начинаются с "@", зарезервированы
для локальных переменных, а идентификаторы, которые начинаются с "#",
зарезервированы для временных объектов.
- Остальными символами могут быть буквы, цифры, знаки "#"
или "$".
- Пробелы внутри названий не допускаются.
- Названия полей должны быть уникальными для одного и того
же пользователя в одной и той же таблице.
- Названия колонок должны быть уникальными внутри одной таблицы.
Самое время сделать несколько замечаний относительно использования русского языка в названиях таблиц и полей. Естественно, что все рассматриваемые СУБД, работающие под управлением Windows 95, прекрасно поддерживают
эту возможность. Оказывается, такой на порядок более серьезный продукт,
как SQL Server, также позволяет создавать таблицы с русскими полями,
более того, имя таблицы также может быть русским. Не возникает проблем
и при наращивании БД (upsizing) с русскими названиями полей и таблиц
в архитектуру клиент-сервер. Например:
- CREATE TABLE Таблица_с_русскими_полями (код smallint IDENTITY(1,1)
- PRIMARY KEY CLUSTERED, наименование varchar(20) NOT NULL, время timestamp)
На рис. 6.28 приведен результат выполнения данного примера.
После создания таблиц необходимо позаботиться о привилегиях доступа пользователей к той или иной таблице или полю. Привилегии доступа
выделяются пользователям или группам посредством оператора GRANT
и изымаются с помощью оператора REVOKE. Эти привилегии,
как правило, присваивает владелец соответствующих объектов (он же -
администратор базы данных).
Рис. 6.28.
Применительно к таблицам и представлениям можно управлять следующими правами доступа:
- SELECT - право на выборку данных;
- INSERT - право на добавление данных;
- DELETE - право на удаление данных;
- UPDATE - право на обновление данных (можно указать определенные столбцы, разрешенные для обновления);
- REFERENCES - право на использование внешних ключей, ссылающихся на данную таблицу (можно указать определенные столбцы).
Допустим, что у нас в системе два пользователя, Karina и Lena, которые входят в одно подразделение Piter_group, и нам необходимо предоставить полномочия, указанные в табл. 6.6.
Таблица 6.6. Образец назначения привилегий доступа для пользователей
Таблицы | Поля | SELECT | INSERT | DELETE | UPDATE |
Country | key_country | | Karina | Karina |
name_country | Karina, Lena | Karina | Karina | Karina, Lena |
times_ | | | Karina | Karina |
Firm | key_firm | | | Lena | Lena |
name_firm | Karina, Lena | Lena | Lena | Karina, Lena |
key_country | | | Lena | Lena |
times_ | | | Lena | Lena |
Для назначения указанных полномочий создаем группу Piter_group:
- sp_addgroup piter_group
Последовательно создаем процедуры регистрации с именами login_lev1, login_lev2 и соответствующими им паролями lev1, lev2 для БД Auto_Store:
- sp_addlogin login_lev1, lev1, auto_store
- sp_addlogin login_lev2, lev2, auto_store
Созданные процедуры регистрации появляются в списке, который можно просмотреть в Server Manager, как это показано на рис. 6.29.
Рис. 6.29. Список Logins - результат выполнения хранимой процедуры sp_addlogin
Создаем пользователей с именами Karina и Lena для группы Piter_group:
- sp_adduser login_lev1, karina, piter_group
- sp_adduser login_lev2, lena, piter_group
Пользователей в новой группе вы можете увидеть в соответствующем списке Server Manager, как это показано на рис. 6.30. Появились новые пользователи, что является результатом хранимых процедур sp_addgroup, sp_adduser.
Рис. 6.30.
С помощью команд GRANT и REVOKE устанавливаем привилегии:
- GRANT insert, delete ON firm TO Lena
- GRANT insert, delete ON country TO Karina
- REVOKE insert, delete ON firm FROM Karina
- REVOKE insert, delete ON country FROM Lena
- GRANT update, select ON country (name_country) TO Karina, Lena
- GRANT update, select ON firm (name_firm) TO Karina, Lena
- REVOKE update,select ON country (key_country, times_) FROM Karina, Lena
- REVOKE update,select ON firm (key_firm, key_country, times_) FROM Karina, Lena
Появившиеся права доступа отображаются в Редакторе управления правами доступа, как это показано на рис. 6.31, а более детальную информацию
можно получить, как это показано на рис. 6.32.
Рис. 6.31.
Рис. 6.32.
Планирование процесса наращивания
Наращивание (upsizing) - это процесс, в ходе которого
на внешнем сервере создается база данных с той же табличной структурой,
с теми же данными и, возможно, со многими другими атрибутами, что
и у исходной локальной базы данных, например Visual FoxPro.
С помощью наращивания на базе существующего приложения, которое работает на локальном компьютере или файл-сервере, создается приложение, функционирующее в архитектуре клиент-сервер.
Создавая приложение, которое вы собираетесь наращивать, необходимо так выбирать особенности проектируемой архитектуры приложения и программной
модели, чтобы добиться максимальной производительности работы на внешнем
источнике данных.
Рассмотрим процесс наращивания приложения, созданного в Visual FoxPro.
Этот процесс можно начинать сразу после того, как вы продумаете все
детали работы приложения клиент-сервер и будет готов локальный прототип.
Локальный прототип представляет собой рабочую модель приложения,
в которой для описания данных используются таблицы и представления
Visual FoxPro.
Для переноса баз данных и содержащихся в них таблиц и представлений из локального прототипа на внешний сервер MS SQL Server самый простой
путь - использование Мастера наращивания (Upsizing Wizard).
Мастер наращивания создает базу данных SQL Server, которая, насколько это возможно, дублирует функциональные возможности таблиц базы данных
Visual FoxPro. Вы также можете переадресовать представления Visual
FoxPro, чтобы они использовали не локальные данные, а вновь созданные
внешние данные. С помощью Мастера наращивания можно выполнить следующие
действия:
- Переместить локальные данные на внешний сервер.
- Преобразовать таблицы локальной базы данных и локальные представления в таблицы внешней базы данных и внешние представления.
- Осуществить миграцию локального приложения в приложение
клиент-сервер.
Хотя Мастер наращивания обращается к серверам SQL Server, вы можете создать приложение клиент-сервер для любого внешнего источника данных
ODBC. Для серверов, отличных от SQL Server, можно с помощью функций
сквозного запроса SQL создать внешние таблицы, а затем с помощью Visual
FoxPro создать внешние представления, осуществляющие доступ к таблицам
сервера.
Перед проведением наращивания следует убедиться, что вы обладаете необходимыми полномочиями для доступа к серверу, оценить размер базы
данных и проверить, достаточно ли места на диске сервера. Кроме того,
необходимо предпринять определенные действия в том случае, если наращивание
производится на нескольких дисках или устройствах.
В первую очередь убедитесь, что на диске сервера достаточно свободного места. Если Мастер наращивания исчерпает все дисковое пространство
на сервере, он прекратит работу, оставив на сервере базу данных и
устройства в том объеме, в каком сможет их создать. Вы можете удалить
неудачно созданные устройства, базы данных и таблицы с помощью средства
администрирования SQL Server.
Чтобы запустить Мастер наращивания, нужно иметь определенные полномочия на работу с сервером SQL Server, на который будет осуществляться наращивание.
Диапазон требуемых полномочий зависит от круга решаемых задач:
- Чтобы провести наращивание в существующую базу данных,
нужны полномочия CREATE TABLE и CREATE DEFAULT.
- Чтобы построить новую базу данных, нужны полномочия CREATE
DATABASE и SELECT на доступ к системным таблицам базы данных Master.
- Чтобы создавать новые устройства, вы должны быть системным
администратором.
Когда вы создаете новую базу данных, Мастер наращивания просит выбрать устройства для базы данных и для журнала. Нужно также установить размер
базы данных и устройств.
Когда сервер SQL Server создает базу данных, он резервирует фиксированную область пространства для этой базы данных на одном или нескольких
устройствах. Не вся эта область обязательно будет использована базой
данных. Размер базы данных просто определяет границы, до которых база
данных может расти, прежде чем будет исчерпано все место.
После создания базы данных на SQL Server можно увеличить ее размер.
Чтобы оценить размер базы данных, посмотрите, каковы размеры файлов DBF в Visual FoxPro для таблиц, которые вы намерены наращивать, и
оцените скорость, с какой будет расти новая база данных на сервере
SQL Server. В среднем, каждый мегабайт данных Visual FoxPro требует,
по крайней мере, 1,3 - 1,5 мегабайт в среде SQL Server.
Если на диске сервера много места, умножьте размер своих таблиц Visual FoxPro на два. Это гарантирует, что у Мастера наращивания будет достаточно
пространства для наращивания базы данных и даже останется место для
увеличения объема ваших данных в дальнейшем. Если вы рассчитываете
добавлять много информации в базу данных, увеличьте величину этого
коэффициента.
Все базы данных и журналы SQL Server размещаются на устройствах. Устройство - это одновременно и логическая область, в которую заносятся базы данных и журналы, и физический файл. Чтобы создать устройство, SQL Server
создает файл, тем самым резервируя на диске определенную часть пространства
для собственных нужд.
Мастер наращивания показывает, сколько свободного места имеется на существующих устройствах SQL Server. Выберите устройство, на котором
объем свободного пространства не меньше, чем оценочный размер базы
данных.
Если ни одно из существующих устройств не обладает достаточным количеством свободного пространства, можно создать новое устройство с помощью
Мастера наращивания. Новые устройства должны иметь размер, по крайней
мере не меньший, чем оценочный размер базы данных. Если это возможно,
задайте для устройства больший объем, чем требуется для базы данных,
чтобы вы смогли впоследствии расширить ее или поместить на то же самое
устройство другие базы данных или журналы.
Размер устройства изменить нельзя. Убедитесь в том, что вы создаете достаточно вместительные устройства.
В большинстве случаев Мастер наращивания обеспечивает контроль над устройствами SQL Server в более чем достаточном объеме. Тем не менее,
если на сервере имеется несколько дисков или если вы хотите разместить
базу данных или журнал на нескольких устройствах, можно создать устройства
до запуска Мастера наращивания.
Если на сервере установлено более одного физического жесткого диска, можно разместить базу данных на одном диске, а журнал базы данных -
на другом. При сбое диска у вас будет больше шансов восстановить базу
данных в том случае, если она разведена с журналом по разным физическим
дискам.
Мастер наращивания позволяет создавать новые устройства, но только на одном физическом диске - на том, который является устройством
главной базы данных Master.
Чтобы разместить базу данных и журнал на отдельных дисках, убедитесь, что на обоих дисках имеются достаточно большие устройства, и при необходимости
создайте новые устройства. Запустите Мастер наращивания.
SQL Server допускает размещение баз данных и журналов на нескольких устройствах. Однако в Мастере наращивания можно задать только одно
устройство для базы данных и одно для журнала.
Чтобы задать несколько устройств для базы данных или журнала, сделайте эти устройства (и только их) устройствами, принимаемыми по умолчанию.
Затем запустите Мастер наращивания и выберите Default для устройства
базы данных или журнала.
Если для новой базы данных или журнала SQL Server не требуется использовать все устройства, принимаемые по умолчанию, SQL Server задействует только
устройства, необходимые для размещения базы данных или журнала.
Перед созданием новой внешней базы данных убедитесь в наличии источника данных ODBC или именованного соединения в базе данных Visual FoxPro,
осуществляющей доступ к серверу SQL Server.
Перед проведением наращивания было бы разумно создать резервную копию базы данных (файлов DBC, DCT и DCX). Мастер наращивания не модифицирует
файлы DBF, а работает с файлом DBC непосредственно, открывая его время
от времени как таблицу, переименовывая таблицы и представления при
создании новых удаленных представлений. Если вы сделали копию базы
данных, то сможете возвратить ее в состояние, предшествовавшее началу
наращивания, заменив модифицированные файлы DBC, DCT и DCX копиями
с исходным содержимым и отменив тем самым все переименования и создание
новых представлений.
Мастер наращивания пытается открыть все таблицы в базе данных для монопольного пользования, а если какие-либо таблицы уже открыты и
имеют статус совместного пользования, то Мастер наращивания закрывает
их и открывает вновь в монопольном режиме. Открытие таблиц перед наращиванием
в монопольном режиме позволяет предохранить их от попыток пользователей
модифицировать записи. Если какие-либо таблицы нельзя открыть для
монопольного использования, Мастер наращивания выдает соответствующее
сообщение.
После того как вы создали источник данных ODBC и сделали все необходимые приготовления на компьютере клиента и на сервере, можно приступать
к наращиванию.
- В меню Tools выберите команду Wizards, а затем выберите Upsizing.
- Последующий процесс выполняется в диалоговом режиме, в привычном
стиле Мастеров, используемых в Visual FoxPro. На рис. 6.33 приведен
первый шаг работы - выбор локальной БД. Вы можете в любой момент
нажать кнопку Cancel и прекратить процесс. На сервере не выполняется
никаких действий, пока не нажата кнопка Finish.
Рис. 6.33. Первый шаг при использовании Мастера наращивания
- После того как вы нажмете кнопку Finish, Мастер
наращивания начинает экспортировать базу данных на сервер.
Кнопка Finish становится доступной после введения основной
информации, требуемой для наращивания. Если нажать кнопку Finish до
того, как будут пройдены все экраны мастера, Мастер наращивания использует
для оставшихся шагов значения, принимаемые по умолчанию.
Наращивание может занять много времени, что зависит от величины
данных, объема сетевого трафика и количества запросов, одновременно
обрабатываемых сервером. Большие таблицы могут экспортироваться часами.
Например, БД, состоящая из трех таблиц, каждая из которых содержала
более ста тысяч записей, у авторов переносилась на сервер дольше 8
часов. Мы, конечно, схитрили и запланировали этот грандиозный процесс
на ночь, что позволило избежать утомительного ожидания и горячих споров,
когда же нажимать клавиши Ctrl+Alt+Del.
Если вы хотите сократить время переноса БД на сервер, советуем вам
при возможности удалить из таблиц поля примечаний и поля типа General.
В нашем случае после удаления из таблиц полей примечаний процесс переноса
занял чуть более 3 часов. После переноса БД эти поля можно восстановить
непосредственно на сервере.
Если в процессе экспортирования данных Мастером наращивания
возникают какие-либо ошибки, он выдает запрос, нужно ли сохранять
информацию об ошибках. Если сохранять информацию нужно - генерируется
отчет об ошибках.
Большинство ошибок связано с недостатком места на устройстве
базы данных или журнала на используемом сервере или с недостаточным
объемом внешней базы данных, которая не в состоянии принять данные,
экспортируемые на сервер. Убедитесь, что на выбранных устройствах
много свободного места и что размер базы данных установлен достаточно
большим.
Чтобы завершить процесс наращивания на сервере, вы можете
выполнить следующие действия:
- Убедиться, что таблицы, которые вы намерены редактировать
в Visual FoxPro, являются обновляемыми.
- Установить полномочия для базы данных, чтобы пользователи
могли получать доступ к нужным объектам.
- Защитить результаты работы, сделав новую базу данных
восстанавливаемой на случай повреждения или потери данных.
Чтобы таблицу можно было обновлять в Visual FoxPro, она должна
иметь уникальный индекс. Мастер наращивания может экспортировать имеющийся
уникальный индекс, но не в состоянии создать такой индекс, если он
отсутствует. Убедитесь, что таблицы, которые вы намерены редактировать
в Visual FoxPro, являются обновляемыми.
SQL Server назначает своей базе данных и ее объектам набор
полномочий, принимаемых по умолчанию. Установите полномочия для внешней
базы данных, чтобы пользователи имели доступ к нужным объектам.
Полномочия, принимаемые для новой базы данных по умолчанию,
делают ее доступной только системным администраторам и владельцу базы
данных.
Вы можете добавить новых пользователей и группы пользователей,
используя на сервере SQL Server приложение Security Manager или системные
процедуры sр_adduser и sp_addgroup.
Подробнее о том, как добавлять пользователей и группы, вы
можете узнать из приводимого ниже примера.
Чтобы предоставить полномочия доступа к таблицам, воспользуйтесь приложением SQL Object Manager или командами GRANT и REVOKE.
Когда на сервере SQL Server создается база данных, в системные
таблицы главной базы данных Master добавляются новые записи. Сделав
дамп базы данных Master, вы получите резервную копию, отражающую все
последние изменения.
Составьте план регулярного сохранения резервных копий содержимого базы данных, чтобы при возникновении серьезной проблемы вы могли восстановить
базу данных из резервной копии.
Функция зеркального дублирования устройства выполняет постоянное дублирование информации с одного устройства SQL Server на другое.
Если первое устройство даст сбой, то можно перейти на второе, содержащее
актуальную копию всех транзакций.
Если ожидаются многочисленные изменения в базе данных в промежутке между выполнением резервных копий и нельзя потерять ни одно из этих
изменений, воспользуйтесь средством дублирования устройств. Оно будет
наиболее эффективным, когда устройства находятся на раздельных дисках,
поскольку если они находятся на одном диске и этот диск даст сбой,
будут потеряны оба устройства.
А теперь рассмотрим выполнение процесса наращивания локальной БД с помощью технологии сквозных запросов SQL .
Приложение клиент-сервер может получать доступ к данным на сервере двумя способами:
- С помощью внешних представлений.
- Средствами сквозных запросов SQL.
Внешние представления - это самый популярный и простой
метод доступа к внешним данным и их обновления. Мастер наращивания
может автоматически создавать внешние представления в базе данных
в процессе наращивания, также возможно создание внешних представлений
с помощью Visual FoxPro после наращивания. Подробнее о внешних представлениях
вы прочитаете в дальнейшем.
Технология сквозных запросов SQL позволяет посылать оператор
SQL непосредственно на сервер. Поскольку операторы сквозного запроса
SQL выполняются на сервере, они позволяют существенно повысить производительность
работы приложения. В табл. 6.7 сравниваются технологии использования
внешних представлений и сквозных запросов SQL.
Таблица 6.7. Сравнение внешних представлений и сквозных запросов SQL
Удаленное представление | Сквозные запросы SQL |
Базируется на операторе SQL SELECT | Базируется на любом операторе SQL, открывая доступ к операторам определения данных или к выполнению хранимых процедур сервера |
Выбирает одно результирующее множество | Выбирает одно или несколько
результирующих множеств |
Обеспечивает встроенное управление соединениями | Требует явного управления
соединениями |
Предоставляет встроенную стандартную информацию обновления для операций
обновления, вставки и удаления | Не предоставляет информации обновления
по умолчанию |
Обеспечивает неявное выполнение SQL и выборку данных | Обеспечивает
явное выполнение SQL и управление результатами выборки |
Не обеспечивает управление транзакциями | Обеспечивает явное управление
транзакциями |
Постоянно хранит свойства в базе данных | Обеспечивает временные свойства
для курсора сквозного запроса SQL, основанного на свойствах сеанса |
Использует асинхронную постепенную выборку при выполнении кода SQL |
Полностью поддерживает программируемую асинхронную выборку |
Таким образом, технология сквозных запросов SQL предоставляет
следующие преимущества по сравнению с внешними представлениями:
- Вы можете пользоваться функциональными возможностями,
специфическими для сервера, например хранимыми процедурами и встроенными
функциями на базе сервера.
- Вы можете использовать расширенные возможности SQL,
поддерживаемые сервером, а также команды определения данных, администрирования
сервера и защиты.
- Вы получаете более полный контроль над операторами Update,
Delete и Insert сквозных запросов SQL.
- Вы расширяете возможности контроля над внешними транзакциями.
Visual FoxPro может обрабатывать сквозные запросы SQL, возвращающие
более одного результирующего множества.
Сквозные запросы SQL имеют и ряд недостатков. Основные из них:
- По умолчанию сквозной запрос SQL всегда возвращает не
обновляемый моментальный "снимок" внешних данных, хранящихся
в активном курсоре представления. Курсор можно сделать обновляемым,
установив соответствующие свойства с помощью функции CURSORSETPROP().
Напротив, обновляемое внешнее представление обычно не требует установки
свойств для обновления внешних данных.
- Команды SQL нужно вводить прямо в окне команд или в программе,
не пользуясь графическим конструктором представлений.
Независимо от того, какая технология используется - внешние
представления или сквозные запросы SQL, вы можете выполнять запросы
и обновлять внешние данные. Практика показывает, что обычно используются
как внешние представления, так и сквозные запросы SQL.
Сквозной запрос SQL (SQL pass-through) обеспечивает прямой
доступ к внешнему серверу с помощью функций сквозного запроса SQL.
Эти функции расширяют возможности доступа к серверу и управления им, предлагаемые представлениями. Вы можете, например, составлять описание
данных на внешнем сервере, устанавливать свойства сервера и обращаться
к хранимым процедурам сервера.
Сквозной запрос SQL является наилучшим средством для создания результирующих множеств, предназначенных только для чтения, и для использования любого
другого синтаксиса SQL. В отличие от представления, которое является
результирующим множеством оператора SQL SELECT, сквозные
запросы SQL позволяют посылать на сервер все что угодно, используя
функцию SQLEXEC() для системы Visual FoxPro. Подробнее об
отдельных функциях см. главу 8. В конце данной главы приведен пример
использования технологии SQL pass-through на Visual FoxPro.
С помощью сквозных запросов SQL вы сами можете создавать курсоры. Механизм сквозных запросов SQL предлагает хотя и более непосредственный,
но менее долговечный доступ к серверу, чем представления. Если описания
представлений хранятся в базе данных на постоянной основе, то курсоры,
созданные сквозными запросами SQL, существуют только в рамках текущего
сеанса.
Чтобы с помощью сквозных запросов SQL подсоединиться к внешнему источнику данных ODBC, сначала вызовите функцию Visual FoxPro SQLCONNECT(), которая создает соединение. После этого можно пользоваться функциями сквозных запросов SQL Visual FoxPro для передачи команд во внешний
источник данных на выполнение. Если создать соединение с помощью сквозных
запросов SQL, информация об этом соединении не будет сохранена в базе
данных в качестве определения именованного соединения.
Как пользоваться функциями сквозных запросов SQL в Visual FoxPro?
- Проверьте способность системы соединить компьютер с источником
данных. Воспользуйтесь утилитой Test ODBC в составе ODBC или ей подобной.
- Установите соединение с источником данных с помощью функции
SQLCONNECT() или SQLSTRINGCONNECT().
Например, если вы соединяете Visual FoxPro с источником данных master на сервере SQL Server, вам следует зарегистрироваться в качестве системного
администратора (идентификатор пользователя "sa") с паролем
"", выдав следующую команду:
- lhandle=SQLCONNECT('master','sa','')
- Воспользуйтесь функциями сквозных запросов SQL в составе
Visual FoxPro для извлечения данных в курсоры Visual FoxPro и обработки
этих данных с помощью стандартных команд и функций Visual FoxPro.
Например, можно выдать запрос в таблицу Customer и просмотреть полученный
курсор с помощью следующей команды:
- ? SQLEXEC (lhandle, "select * from customer" , ; "my_cursor")
- BROWSE
- Отсоединитесь от источника данных с помощью функции SQLDISCONNECT().
- =SQLDISCONNECT(lhandle)
Пример использования технологии SQL pass-through на Visual FoxPro
- SET CONSOLE OFF
-
- * Установка соединения с источником данных
- lhandle=SQLCONNECT('master','sa','')
- IF lhandle>>0 && Проверка на наличие связи с SQL Server
-
- * Следующие три строчки программного кода удаляют
- * устройство Rdev_lib и устройство Rdev_log,
- * так как впоследствии мы создаем новые устройства с
- * подобными именами и со своими параметрами
- use_m=SQLEXEC(lhandle,"USE master")
- mlibr=SQLEXEC(lhandle,"sp_dropdevice Rdev_lib, delfile")
- mlogr=SQLEXEC(lhandle,"sp_dropdevice Rdev_log, delfile")
-
- * Создаем устройство для нашей БД
- mlib=SQLEXEC(lhandle,"DISK INIT ;
- NAME = 'Rdev_lib', ;
- PHYSNAME = 'C:\SQL_60\DATA\SAMP_LIB.DAT', ;
- VDEVNO=1, ;
- SIZE = 5120")
-
- * Создаем устройство для журнала БД
- mlog=SQLEXEC(lhandle,"DISK INIT ; &
- NAME = 'Rdev_log', ;
- PHYSNAME = 'C:\SQL_60\DATA\SAMP_LOG.DAT', ;
- VDEVNO=2, ;
- SIZE = 2048")
-
- * Если процесс создания
- * устройств прошел успешно
- * Проверка наличия БД auto_store
- * на сервере, и, если она существует,
- * мы ее удаляем
- IF mlib>>0 AND mlog>>0
- =SQLEXEC(lhandle,"IF EXISTS ( SELECT name FROM ; sysdatabases ;
- WHERE name IN ('auto_store') );
- BEGIN DROP DATABASE auto_store END")
-
- * Создаем базу данных auto_store, которая будет
- * размещаться на двух
- * устройствах Rdev_lib и устройстве для журнала
- * транзакций базы данных Rdev_log
- creat_data=SQLEXEC(lhandle,"CREATE DATABASE auto_store ;
- ON Rdev_lib = 10 LOG ON Rdev_log = 4")
- * Если процесс создания БД прошел успешно
- IF creat_data>>0
- =SQLEXEC(lhandle,"USE auto_store")
- * Проверка наличия таблицы country на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name FROM sysobjects;
- WHERE type = 'U' AND name = 'country');
- DROP TABLE country")
- * Создаем таблицу Сountry
- cr_country=SQLEXEC(lhandle, ;
- "CREATE TABLE country (key_country smallint ; IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_country varchar(20) ;
- NOT NULL, times_ timestamp)")
-
- * Проверка наличия таблицы Firm на сервере, и, если она
- * существует мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'firm') ;
- DROP TABLE firm")
-
- * Создаем таблицу Firm
- cr_firm=SQLEXEC(lhandle, ;
- "CREATE TABLE firm (key_firm smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_firm varchar(20) NOT NULL, ;
- key_country smallint REFERENCES country(key_country), ;
- times_ timestamp)")
-
- * Проверка наличия таблицы Fuel_oil на сервере,
- * и, если она существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'fuel_oil') ;
- DROP TABLE fuel_oil")
-
- * Создаем таблицу fuel_oil
- cr_fuel=SQLEXEC(lhandle, ;
- "CREATE TABLE fuel_oil (key_fuel_oil smallint ; IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_fuel_oil varchar(20) NOT NULL,;
- times_ timestamp)")
-
- * Проверка наличия таблицы Tyre на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'tyre') ;
- DROP TABLE tyre")
-
- * Создаем таблицу Tyre
- cr_tyre=SQLEXEC(lhandle, ;
- "CREATE TABLE tyre (key_tyre smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_tyre varchar(20) NOT NULL, ;
- times_ timestamp)")
-
- * Проверка наличия таблицы Body на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'body') ;
- DROP TABLE body")
-
- * Создаем таблицу body
- cr_body=SQLEXEC(lhandle,;
- "CREATE TABLE body (key_body smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_body varchar(20) NOT NULL, ;
- times_ timestamp)")
-
- * Проверка наличия таблицы Model на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'model') ;
- DROP TABLE model")
-
- * Создаем таблицу Model
- cr_model1=SQLEXEC(lhandle, ;
- "CREATE TABLE model (key_model smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_model varchar(20) NOT NULL, ;
- key_firm smallint DEFAULT 1 REFERENCES firm(key_firm), ;
- swept_volume numeric(5) DEFAULT 1 CHECK ;
- (swept_volume>>1) NULL)")
- cr_model2=SQLEXEC(lhandle, ;
- "ALTER TABLE model ADD quantity_drum numeric(2) ;
- DEFAULT 1 ;
- CHECK (quantity_drum>>=1) NULL, capacity numeric(5,1) NULL, torgue numeric(5,1) NULL, key_fuel_oil ;
- smallint DEFAULT 1 ;
- REFERENCES fuel_oil(key_fuel_oil), top_speed numeric(5,1) NULL") cr_model3=SQLEXEC(lhandle, ;
- "ALTER TABLE model ADD starting numeric(4,1) NULL, ;
- key_tyre smallint DEFAULT 1 REFERENCES tyre(key_tyre), ;
- key_body smallint DEFAULT 1 REFERENCES body(key_body), ;
- quantity_door numeric(1) NULL, ;
- quantity_sead numeric(2) NULL")
- cr_model4=SQLEXEC(lhandle, ;
- "ALTER TABLE model ADD length numeric(5) NULL, ;
- width numeric(4) NULL, height numeric(4) NULL, ; expense_90 ;
- numeric(4,1) NULL, expense_120 numeric(4,1) NULL, ;
- expense_town numeric(4,1) NULL, times_ timestamp")
-
- * Проверка наличия таблицы Automobile_passenger_car
- * на сервере, и, если она существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects ;
- WHERE type = 'U' AND name = 'automobile_passenger_car') ;
- DROP TABLE automobile_passenger_car")
-
- * Создаем таблицу Automobile_passenger_car
- cr_auto=SQLEXEC(lhandle, ;
- "CREATE TABLE automobile_passenger_car ;
- (key_auto smallint IDENTITY(1,1) PRIMARY KEY CLUSTERED, ;
- key_model smallint REFERENCES model(key_model), ;
- date_issue datetime, cost numeric(10,2), times_ ; timestamp)")
-
- * Проверка наличия таблицы Customer на сервере, и, если
- * она существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'customer') ;
- DROP TABLE customer")
-
- * Создаем таблицу customer
- cr_customer1=SQLEXEC(lhandle, ;
- "CREATE TABLE customer (key_customer smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, name_customer varchar(30) ;
- NOT NULL, address varchar(30), tel varchar(12), ; fax varchar(12), ;
- last_name varchar(17), first_name varchar(17))") ;
- cr_customer2=SQLEXEC(lhandle, ;
- "ALTER TABLE customer ADD patronymic varchar(17), juridical bit, comment text, times_ timestamp")
-
- * Проверка наличия таблицы Sale на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'sale') ;
- DROP TABLE sale")
-
- && Создаем таблицу sale
- cr_sale=SQLEXEC(lhandle,;
- "CREATE TABLE sale (account_ smallint ;
- PRIMARY KEY CLUSTERED, date_sale datetime, ;
- sum_ numeric(10,2), times_ timestamp)")
-
- * Проверка наличия таблицы Account на сервере, и, если она
- * существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'account') ;
- DROP TABLE account")
-
- * Создаем таблицу Account
- cr_account1=SQLEXEC(lhandle, ;
- "CREATE TABLE account (number_record smallint ; IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, account_ smallint REFERENCES ;
- sale(account_), key_customer smallint REFERENCES ;
- customer(key_customer), key_auto smallint REFERENCES ;
- automobile_passenger_car(key_auto))")
- cr_account2=SQLEXEC(lhandle, ;
- "ALTER TABLE account ADD date_write datetime, selled ;
- bit, sum_ numeric(10,2), times_ timestamp")
-
- * Проверка наличия таблицы Salesman на сервере, и, если
- * она существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'salesman') ;
- DROP TABLE salesman")
-
- * Создаем таблицу Salesman
- cr_salesman=SQLEXEC(lhandle, ;
- "CREATE TABLE salesman (key_salman smallint ; IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, last_name varchar(17), ;
- first_name varchar(17), patronymic varchar(17), ; times_ timestamp)")
-
- * Проверка наличия таблицы Order_ на сервере, и, если
- * она существует, мы ее удаляем
- =SQLEXEC(lhandle,"IF EXISTS (SELECT name ;
- FROM sysobjects WHERE type = 'U' AND name = 'order') ;
- DROP TABLE order_")
- * Создаем таблицу Order_
- cr_order=SQLEXEC(lhandle, ;
- "CREATE TABLE order_ (key_order smallint IDENTITY(1,1) ;
- PRIMARY KEY CLUSTERED, key_customer smallint REFERENCES ;
- customer(key_customer), key_model smallint REFERENCES ;
- model(key_model), key_salman smallint REFERENCES ;
- salesman(key_salman), times_ timestamp)")
- ELSE
- WAIT WIND "Не могу создать базу данных !"
- ENDIF
- ELSE
- WAIT WIND "Не могу создать устройство !" + CHR(13)+ ;
- "возможные причины:" +CHR(13)+" - нет места на диске"+CHR(13)+ ;
- " - нет полномочий на данную операцию"+CHR(13)+ ;
- " - путь указан неверно"
- ENDIF
-
- * Регистрация
- =SQLEXEC(lhandle,"USE auto_store")
- * Проверка наличия группы Piter_group на сервере, и, если
- * она существует, мы ее удаляем
- =SQLEXEC(lhandle,"sp_dropgroup piter_group")
-
- * Создаем группу piter_group
- addg=SQLEXEC(lhandle,"sp_addgroup piter_group")
- * Если процесс создания группы прошел успешно
- IF addg>>0
- * Последовательно создаем процедуры регистрации с
- * именами login_lev1, * login_lev2,
- * login_lev3, login_lev4, login_lev5 и соответствующими
- * им паролями lev1,
- * lev2, lev3, lev4, lev5 для БД Auto_store
- =SQLEXEC(lhandle,"sp_addlogin login_lev1, lev1, ; auto_store")
- =SQLEXEC(lhandle,"sp_addlogin login_lev2, lev2, ; auto_store")
- =SQLEXEC(lhandle,"sp_addlogin login_lev3, lev3, ; auto_store")
- =SQLEXEC(lhandle,"sp_addlogin login_lev4, lev4, ; auto_store")
- =SQLEXEC(lhandle,"sp_addlogin login_lev5, lev5, ; auto_store")
-
- * Последовательно создаем пользователей с именами Ruben, Karina, Lena, Elena и Ira для группы Piter_group
- =SQLEXEC(lhandle,"sp_adduser login_lev1, Ruben, ; piter_group")
- =SQLEXEC(lhandle,"sp_adduser login_lev2, Karina, ; piter_group")
- =SQLEXEC(lhandle,"sp_adduser login_lev3, Lena, ; piter_group")
- =SQLEXEC(lhandle,"sp_adduser login_lev4, Elena, ; piter_group")
- =SQLEXEC(lhandle,"sp_adduser login_lev5, Ira, ; piter_group")
- ELSE
- WAIT WIND 'Группу PITER_GROUP создать невозможно'
- ENDIF
-
- * Заполнение таблиц БД
- =SQLEXEC(lhandle,"USE auto_store")
-
- * Заполнение таблицы Country
- =SQLEXEC(lhandle,"INSERT country (name_country) VALUES ; ('Италия')")
- . . .
- =SQLEXEC(lhandle,"INSERT country (name_country) VALUES ; ('Япония')")
- . . .
- * Заполнение таблицы Firm
- =SQLEXEC(lhandle,"INSERT firm (name_firm,key_country) ; VALUES ('Alfa Romeo',1)")
- . . .
-
- && Заполнение таблицы Fuel_oil
- =SQLEXEC(lhandle,"INSERT fuel_oil (name_fuel_oil) ;
- VALUES ('Дизельное топливо')")
- . . .
-
- && Заполнение таблицы Tyre
- =SQLEXEC(lhandle,"INSERT tyre (name_tyre) VALUES ('4.5 ; J')")
- . . .
-
-
- * Заполнение таблицы Body
- =SQLEXEC(lhandle,"INSERT body (name_body) VALUES ; ('Хэтчбек')")
- . . .
-
- * Заполнение таблицы Model
- =SQLEXEC(lhandle,"INSERT model ; (name_model,key_firm,swept_volume, ;
- quantity_drum,key_fuel_oil,key_tyre,key_body) VALUES ; ('145 1.4',1,1351,4,3,3,1)")
- . . .
-
- * Заполнение таблицы Automobile_passenger_car
- =SQLEXEC(lhandle,"INSERT automobile_passenger_car ; (key_model,date_issue,cost);
- VALUES (1,'7/7/94',10000)")
- . . .
-
- * Заполнение таблицы Customer
- =SQLEXEC(lhandle,"INSERT customer ; (name_customer,address,tel, ;
- first_name,juridical) ;
- VALUES ('Общество национальных героев','CПб ; ул М Маклая','77710','Юлиан',1)")
- . . .
-
- * Заполнение таблицы Sale
- =SQLEXEC(lhandle,"INSERT sale
- (account_,date_sale,sum_) ;
- VALUES (101,'5/1/96',10000)")
- . . .
-
- * Заполнение таблицы Account
- =SQLEXEC(lhandle,"INSERT account ; (account_,key_customer,key_auto, ;
- date_write,selled,sum_) VALUES ; (101,1,1,'1/1/96',1,10000)")
- . . .
-
- * Заполнение таблицы Salesman
- =SQLEXEC(lhandle,"INSERT salesman ; (last_name,first_name,patronymic) ;
- VALUES ('Ажуров','Аристарх','Ариевич')")
- . . .
-
- * Заполнение таблицы Order_
- =SQLEXEC(lhandle,"INSERT order_ ; (key_customer,key_model,key_salman) ;
- VALUES (1,1,1)")
- . . .
-
- * Создание привилегий (прав) доступа к полям таблиц БД
- =SQLEXEC(lhandle,"USE auto_store")
- =SQLEXEC(lhandle,"GRANT insert, delete ON model ; TO ruben")
- =SQLEXEC(lhandle,"GRANT update,select ON model ;
- TO ruben, karina, lena, elena, ira")
- =SQLEXEC(lhandle,"REVOKE update,select ON customer ; (comment) ;
- FROM karina, lena")
- . . .
-
- * Разрываем соединение с источником данных ODBC
- =SQLDISCONNECT(lhandle)
- ELSE
- WAIT WIND "Связаться с сервером не удается !"
- ENDIF
-
Глава 5 || Содержание || Глава 7
|