Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Создание прибыльного сайта для начинающих" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Интернет для Delphi-программиста 59
Интернет для Delphi программиста.Выпуск : № 59 Здравствуйте уважаемые подписчики рассылки "Интернет для Delphi программиста". Данная рассылка предназначена для всех кого интересует Delphi, здесь будут выкладываться ссылки на различные ресурсы интернета так или иначе связанные с Delphi: книги, исходники, программы... Изучайте Delphi один из лучших языков программирования!!! ЗАДАТЬ ВОПРОС : Правила
рассылки: Новые вопросы.
Ответы.
Статья: "Создание баз данных в InterBase SQL Server." http://delphid.dax.ru/ Автор: Михаил Христосенко
Я не буду загромождать текст подробным описанием всех операторов для создания объектов в базе данных. Для этого есть документация. Наоборот, на простых примерах постараюсь показать как и когда нужно делать так или иначе. Здесь описывается работа с SQL сервером InterBase 6.0. Создание базы данныхБаза данных создается простым скриптом. Здесь и в дальнейшем я буду SQL операторы выделять жирным шрифтом.
CREATE DATABASE - это и есть
оператор, который создаст базу данных.
База данных будет представлять из себя
файл, который будет создан в каталоге,
указанном после оператора. Расширение
файла может быть любым, но принято, что GDB
- расширение для файла базы данных, а,
например, GBP - для резервной копии. Вы можете создать БД из нескольких файлов, которые будут заполняться данными по очереди. Или создать зеркало на другом жестком диске для защиты от крушения основного жесткого диска (см. документацию). Создание таблиц InterBase - это не
совсем то, о чем писал Кодд. Здесь
полностью не реализовано понятие домена.
Домены служат в InterBase не для связи таблиц
по первичному и внешнему ключу, а для
описания типа поля, определенного
пользователем. Более того, если Вы
начнете создавать таблицы с полями
стандартного типа, то каждому из этих
полей будет поставлен в соответствие
свой домен. Это приводит к тому, что
количество объектов в базе данных
прирастает за счет доменов прямо
пропорционально количеству полей всех
таблиц. Поэтому, обычно создают
достаточное количество доменов для
описания таблиц в БД, а потом создают
сами таблицы. Вот выдержка из реальной
базы данных для создания доменов:
Команда CREATE DOMAIN создает новый
домен. Далее, идет имя домена. Затем - его
тип. Есть множество типов данных,
которые поддерживает InterBase. Вы можете
узнать эту информацию из документации.
Далее, можно задать ограничения на
значение, заводимое в поле таблицы типа
этого домена. Например, NOT NULL
обязывает всегда заводить какие-нибудь
данные в это поле при добавлении новой
строки в таблицу, т.е. это поле
обязательно должно быть заполнено. DEFAULT
"F" заполняет поле значением по
умолчанию - символом "F".
Конструкция CHECK(VALUE = "T" OR
VALUE = "F") проверяет выход значения
поля за заданные границы. Конструкция COLLATE
PXW_CYRL позволяет правильно вести
сортировку строк таблицы по полю типа
этого домена. Эта конструкция
применяется при создании домена или при
объявлении индекса (об этом позже).
Конструкция CREATE DOMAIN FORMULA_TYPE BLOB SUB_TYPE
1 SEGMENT SIZE 256 CHARACTER SET WIN1251 создает
домен типа BLOB, т.е. набор байтов,
которые рассматриваются как текст (SUB_TYPE
1), странички в файле БД для этого текста
выделяются по 256 байт сразу и текст в
этом поле записывается в кодировке WIN1251.
Последние два домена могут хранить
информацию о пользователе и дату и время
о последнем изменении записи.
Оператор CREATE TABLE собственно, создает таблицу, далее идет её уникальное в пределах БД имя. Между скобками стоят определения столбиков таблицы и дополнительные операторы. Мы видим, что таблица состоит из четырех столбиков, а их тип описан через домены, которые мы описали ранее. Если Вы создадите еще одну таблицу с полем типа NAMES_TYPE, то количество доменов у Вас не увеличится, а если бы Вы создали две таблицы, у которых было бы по одному полю типа VARCHAR(45), то это привело бы к созданию двух доменов, описывающих эти поля. Причем, имена этих доменов присвоились бы по умолчанию, а значит, совершенно нечитабельные. Оператор PRIMARY KEY пределяет имя или имена полей, которые рассматриваются как первичный ключ. Поля первичного ключа должны быть NOT NULL и сочетание их значений должно быть уникально в пределах таблицы. Это как бы отпечаток пальцев записи - набор значений полей, по которым мы всегда сможем отличить одну запись от другой. Если Вы не можете выделить первичный ключ в таблице для хранения Ваших данных, значит, скорее всего, Вы недостаточно хорошо продумали все вопросы по хранению данных в таблице. Связывание таблицСвязать можно хотя бы две таблицы, поэтому определим вторую:
Во второй таблице есть поле
с типом IZMER_NUM - это домен, который
используется в первой таблице для
определения поля первичного ключа. Мы
можем создать внешний ключ для связи
двух таблиц: FOREIGN KEY(ID_IZMER_NAMES) REFERENCES
IZMER_NAMES(ID_NUM). Что буквально означает: "Внешний
ключ по полю ID_IZMER_NAMES как ссылка в
таблицу IZMER_NAMES по полю ID_NUM". Такая
связь гарантирует нам, что в таблице
IZMER_NAMES всегда будет присутствовать
строка с номером, который мы запишем в
поле ID_IZMER_NAMES. Если кто-нибудь попытается
удалить из справочника единиц измерения
строку, которую мы используем в
справочнике деятельности, то произойдет
исключительная ситуация. Такое
поведение БД называется контроль
ссылочной целостности.
Суррогатные ключиЕсть два типа ключевых полей. Первое - это естественные ключи. Возьмем, к примеру, медицинскую карту в поликлинике. Естественный ключ - это номер медицинской карты. На медицинскую карту "цепляются" талоны (связь главный - подчиненные), у которых естественный ключ - это номер медицинской карты больного, отчетный год и номер талона (с нового года нумерация начинается с единицы). К талонам "цепляются" посещения, у которых естественный ключ - номер медицинской карты больного, отчетный год, номер талона и дата посещения. К посещениям - услуги и т.д. Мы видим, что размер первичного ключа увеличивается, по крайней мере, на одно поле с каждой новой таблицей. Соответственно, растет вычислительная нагрузка, которую можно оценить мощностью домена, на сервер БД. Как же можно противостоять разрастанию первичного ключа? Многие программисты, и я в том числе, считают, что уникальность записи и первичный ключ - это понятия, вообще-то разные, поэтому мы всегда, где это нужно, применяем т.н. сокращение первичного ключа. Для этого используются суррогатные (т.е. неестественные) ключи. Что такое суррогатный ключ? Это поле целого типа, которое имеет уникальное значение, образующее домен с другими таблицами. Возьмем, для примера, случай с поликлиникой. Для таблицы с талонами вводится уникальное поле целого типа, в котором будет хранится последовательность целых чисел 1, 2, 3 ... N и т.д. Это поле объявлено первичным ключом, а чтобы не завести несколько талонов с одинаковыми номерами, объявляется уникальный индекс по полям отчетный год и номер талона. Внешний ключ, как и положено - по полю номера медицинской карты. В результате, мы сократили размер первичного ключа, который теперь является суррогатным. Эти целые числа будут использоваться в таблице с посещениями, где тоже можно сокращать первичный ключ. Заметьте, что в таблице с посещениями, теперь, не нужно хранить не номер медицинской карты, не отчетный год, не номер талона, а только значение первичного ключа, т.е. одно целое число на запись. Вот несколько примеров для
работы с суррогатными ключами.
Этот оператор создает т.н. генератор, где будет хранится предыдущее значение нашей уникальной последовательности целых чисел. Механизм гарантирует, что только один пользователь может иметь доступ к генератору в один момент времени. Остальные будут ждать, пока генератор не освободится.
Этим оператором мы установили начальное значение генератора. Далее, можно либо создать триггер, который сработает при добавлении новой записи в таблицу, либо создать простенькую процедуру, которая вернет очередное значение из генератора:
GEN_ID - это встроенная процедура, которая просто увеличивает значение генератора на величину, переданную во втором параметре и возвращает результат. Если Вы используете триггер, то после добавления новой записи, Вам придется обновлять весь набор данных, чтобы знать значение первичного ключа, поэтому лучше использовать процедуру. "Деревянные" спискиБывают случаи, когда отношение главный-подчиненный присуще записям одной и той же таблице, например, отношения между отделами организации или между структурами госаппарата и т.д. и т.п. Одна запись может быть главной для нескольких других, которые в свою очередь могут быть главными для следующих. Такая структура напоминает дерево с ветвями, расположенными вниз по таблице. Первая запись (записи) - главный узел (узлы) от которых идут ветви (подчиненные записи). Если эти записи имеют свои подчиненные (вложенные) записи, то они образуют следующие по иерархическому списку узлы. Проще всего, представить это в пространстве в виде слоев записей. Каждая запись может содержать в себе вложенный слой с записями. Несмотря на всю кажущуюся сложность, реализация такой структуры очень проста. Для этого нужно иметь, как минимум, два столбика в таблице: первый столбик - это суррогатный первичный ключ, а второй - ссылка на первый столбик со значением первичного ключа записи - владельца. Вот реализация такой таблицы:
Таблица содержит первичный ключ в поле ID_NUM, ссылку на главную запись в поле ID_OWNER, ссылку на единицу измерения в поле ID_IZMER, поле POZITION целого типа, определяющее позицию записи, для возможности перемещения записи вверх и низ, наименование вида дечтельности в поле NAME. Далее, идут счетчик и процедура для работы с первичным ключом.
Далее, идет индекс для сортировки строк по позиции. Имя POZITION принято мной не потому, что я не знаю о английском слове POSITION, а потому, что POSITION - зарезервированный идентификатор SQL.
Триггер UPDATE_ACTIVITIES обновляет значения полей, идентифицирующиз пользователя внесшего последние изменения.
Наконец, добавлен внешний индекс таблицы на саму себя. В описании таблице это нельзя было сделать,т.к. ни поля ID_OWNER, ни поля ID_NUM, ни самой таблицы не существовало.
Далее, идет процедура перемещения строки в слое данных вверх или низ. Подразумевается, что в слое не более 2147483646 строк.
Тут не хватает только триггера для начального определения значения поля POZITION. Я думаю, что Вы сможете самостоятельно создать триггер в качестве пробы сил. Работа с событиямиЭто совсем просто:
Осталось только зарегистрировать это событие в приложении пользователя, и если оно произойдет на сервере, то приложение пользователя его получит. Так можно, например, наблюдать за изменениями курсов валют на бирже. При изменении курса, клиент получает событие и пере открывает запрос, чтобы увидеть изменения. Работа с исключениямиДля начала, исключение нужно определить в БД.
Далее, нужно определить триггер, который поймает исключительную ситуацию. Например, при удалении главного узда дерева, удалится вся БД целиком. Понятно, что такого быть не должно. Давайте поймаем это исключение.
Если исключительная ситуация наступит, то пользователю ничего не останется сделать, кроме как отменить транзакцию. Процедуры, триггерыПонятия процедур и триггеров должно, прежде всего, ассоциироваться с понятием бизнес-логика. Процедуры реализуют документированный интерфейс к данным в БД, а триггеры - проверку корректности вводимых данных и закулисную работу. Если у Вас есть возможность переложить всю бизнес-логику на сервер в виде триггеров и процедур, то так и нужно поступать. Даже если Вы в программе контролируете правильность вводимых данных, не забудьте в БД продублировать это же в триггере. Такой подход гарантирует, что при написании дополнительного модуля или еще одной программы, оперирующей с данными БД, Вам не удастся нарушить правила работы с данными. Я думаю, что примеров триггеров и процедур было достаточно. Но, начинающие программисты часто отказываются от использования этого мощнейшего механизма БД из за досадных ошибок в синтаксисе запросов. Им кажется, что в приложении пользователя легче сделать то же самое, к тому же и работает оно быстрее... Это заблуждение. Одно дело, когда Вы пишете и тестируете программу локально, и совсем другое, когда к БД подключены пользователи. Никакая программа не сделает изменения в БД так же быстро и корректно, как встроенные механизмы. Вот тогда они будут работать локально, а ваша программа - по сети. Поэтому я дам без комментариев пример процедуры с большим количеством операторов. Из этого примера будет ясно где ставить, а где нет точки с запятыми, двоеточия и т.д. Думаю, что это поможет Вам в Ваших разработках.
Эта процедура используется сервером приложений для проверки прав пользователя в таблице в виде иерархического дерева. Понятно, что определить права пользователя к отдельной записи стандартными путями нельзя, поэтому вся БД работает под управлением сервера приложений и посредством DCOM дает интерфейсы клиентам. Т.к. сервер приложений запущен в адресном пространстве сервера, то такой подход к Security можно считать оправданным. UDF функцииОбычно, тут дают пример, как посчитать какую-нибудь математическую формулу, и вернуть её результат как столбик ответа на запрос. Я же решил показать пример со строками, т.к. это первое, на чем обычно впервые спотыкаются. Это только пример. В реальной БД такого не делают. Итак, добавим в таблицу ACTIVITIES поле TREE_INFO VARCHAR(255). Будем в нем хранить путь от главного узла. Этот путь проще всего строить в триггере по добавлению записи в таблицу. Но сама строка с путем будет создаваться в DLL. Для начала объявим нащу функцию в DLL:
Мы указали имя в БД, передаваемые переметры, возвращаемое значение, имя в DLL, и имя самой DLL. Эта библиотека должна находится в каталоге UDF. У меня это D:\Program Files\Borland\InterBase\UDF. А использовать функцию будем так:
В InterBase все UDF передают в параметрах ссылки, поэтому строку передают как указатель. Используются VARCHAR строки, т.к. они явно не дополняются пробелами до максимальной длины. Иначе, Вы бы уже ничего к ней не прибавили. Вот реализация DLL в Delphi:
Компоненты: TRotateImage
v1.4 TAnimateImage
v1.0 TmxLinkLabel v1.12 TmxXPButton v1.01 TicAscrollA v1.0.0.1 TCursorView v1.01 WavePlayer v1.01 PubStrGrid SortGrid v2.00 TStringAlignGrid v2.1 XStringПrid v2.6 Интересные и полезные сайты по Delphi: Если Вы хотите, чтобы Ваш сайт был в этом разделе пишите.
Немного юмора: :))
Дружественные рассылки: Все
кто хочет изучить Delphi и реально
научиться писать свои программы, ЦПИ "Эверест"
поможет Вам. 10 причин в пользу платного обучения в ЦПИ "Эверест"… 1. Когда Вы
платите деньги-
появляется дополнительный стимул
против лени: надо учиться, ведь деньги
уже уплачены….
5. Стоимость обучения
одного месяца в ЦПИ "Эверест"
сравнима с ценой хорошей книги. Но часто
ли Вам попадались книги, рассчитанные
именно на Вас. Мы же работаем
индивидуально.
8. А это значит, что …Мы
предлагаем получить "высшее
образование" - профессию
программиста всего за
1 год и 144 доллара, любой ВУЗ
попросит в 3 раза больше за один только
семестр. По всем вопросам обращайтесь ко мне. Если вы встретили в интернете
интересный сайт или статью, да и вообще, что угодно
связанное с Delphi, поделитесь ссылкой. Предложения, критику и пожелания пишите на e-mail. |
В избранное | ||