При закрытии подписчики были переданы в рассылку "Килограмм килобайтов" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Delphi и Interbase: Часть II, запросы и метаданные
Традиционное лирическое отступление
Первым делом хочется сказать спасибо куче народа, осилившей первую статью и до сих пор присылающих письма. Я старался ответить всем, но кому-то мог и не успеть по причине выпадания из инета почти на полгода. Извиняюсь, если кто-то моих ответов не дождался или по каким-то ещё причинам не получил. Но я решил продолжить бог знает сколько времени назад начатый проект исключительно благодаря всем тем, кто писал и до сих пор продолжает писать. Ещё раз – спасибо. Вкратце остановлюсь на двух типовых ошибках, возникших при сборке демо-проекта из первой статьи.
О чём пойдёт речь далее. Во-первых, об обещанных метаданных, т.е. о том, как именно IB хранит сведения о структуре базы, как эти сведения из него выковырять, и для чего эти сведения нужны. А для этого нам понадобится «во-вторых - научится строить запросы к БД и как-то отображать их результаты. Для простоты будет использоваться (и наращиваться) пример из предыдущей статьи. Как и ранее, изложение будет строится по принципу «давайте поглядим, что это мы тут понаписали». Т.е. сначала будет приводится код, а потом объяснение, как это всё живёт. Материал не был и не будет систематическим изложением чего-либо, если по ходу работы я буду касаться вещей, о которых ещё не говорил – то по возможности буду останавливаться и говорить. Я сильно подозреваю, что материал будет выложен пока не весь, потому что чисто физически подготовить и вывалить всё сразу не хватает ни рук, ни времени. Пока будет выложено неполное описание системных таблиц, которое будет закончено где-то через неделю, и потом пойдёт речь уже о том, что как и что на основе этих таблиц можно получить. Также готовится третья часть, в которой по шагам расписано создание простейшего приложения на Delphi, работающего с СУБД Firebird, от постановки задачи, проектировая схемы БД, и до методов реализации пользовательского интерфейса. Ну а пока... Таки метаданные
Основной таблицей является rdb$relations. Основной в том смысле, что она содержит имена всех других таблиц, и зная одно это единственное имя, из БД можно достать буквально всё – все метаданные и сами данные, которые она содержит. (Многие поля, да и целые таблицы, используются только для внутренних процедур самого IB, практическое их применение с точки зрения разработки приложений мне неизвестно, и такие поля/таблицы я буду пропускать. Если кто-то захочет что-то поправить/дополнить – добро пожаловать). Удобства ради описания системных таблиц будут приведены в алфавитном порядке. Собственно говоря, материал ниже представляет собой достаточно вольный перевод из Language Reference, оставшемуся в наследство ещё от IB6.0, и на 99% он продолжает оставаться корректным и по сей день, но несоответствия возможны, особенно там, где дело касается различных бранчей различных клонов. Если у вас возникли подозрения о несоответсвии классического описания тому конкретному билду, которую вы используете, следует внимательно читать идущие с ним Release Notes. В свою очередь я буду благодарен за сведения о подобных несоответсвиях, и по мере накопления, буду стараться отражать их здесь. rdb$character_sets
В этой таблице хранятся все поддерживаемые базой наборы символов (чарсеты). Эта информация иногда бывает реально необходима, например, с вашей БД работают клиенты из разных стран (т.е. с разной локализацией ПО), и при подключении им необходимо выбрать из списка свою кодировку. Где этот список взять? Именно здесь.
Следует обратить внимание на последнее поле. Оно помогает определить, сколько места на самом деле будет занимать в базе объявленный тип строковых данных. Люди, уверенные, что char (10) занимает 10 байт –не совсем правы, всё зависит от того, какой набор символов указан для этого типа. В кодировке win1251 или ASCII десятисимвольная строка действительно займёт 10 байт (на самом деле – чуть больше, но я сознательно упрощаю), а вот в UNICODE, для которого на хранение символа отводится 3 байта – уже 30. Каждый набор символов может предоставлять несколько режимов сортировки (collation), и они хранятся в следующей простенькой таблице, а именно: rdb$collations
Если вы посмотрите на данные, которые содержит эта таблица, вам станет понятна разница между COLLATE, указываемым при созданнии символьного поля, и LC_CTYPE, указываемым в подключении к базе. И то и другое, зачастую, содержит одно и то же выражение, например, …=win1251, но в первом случае это режим сортировки, который будет использоватся при указании в запросе SELECT оператора ORDER_BY, а во втором случае – это указание набора символов, которые, собственно, и будут сортироватся. В данных этой таблицы вы увидите, что, например, одному набору символов CYRL («досовская» кодировка, в винде эквивалентно codepage=866) соответствуют аж три режима сортировки: CYRL, PDOX_CYRL и DB_RUS. rdb$field_dimensions
Как уже упоминалось, здесь для каждого поля c типом данных массив можно узнать размерности и границы этого массива.
Чтобы сразу всё стало понятно, приведу пример значений в этой таблице для домена NEW_DOMAIN, объявленного как массив [0:2,0:5].
Вообще говоря, использование массивов в качестве типов данных противоречит самой концепции реляционных баз, т.к. любая таблица, по сути, уже является массивом. Отображение этих типов, как правило, не поддерживает ни одна штатная (да и не только) утилита. Но тем не менее, функционал для работы с массивами есть, и в некоторых очень специфических случаях (например, хранение результатов каких-то измерений, хранение векторных фигур в виде массива их относительных координат) это тип данных может пригодится. Но следует учитывать, что в IB массив – это, скорее, эмуляция типа данных, а не самостоятельный тип данных в чистом виде, такой как varchar или integer, т.к. при создании поля типа «массив» реальным типом этого поля будет BLOB. rdb$fields
Вопреки названию, здесь живут не поля, а домены. В этом легко убедиться, если вы создадите в том же IBExpert’е новый домен – он появится именно здесь. Поэтому во избежание путаницы, применительно к метаданным IB, FIELD я буду называть доменом, а RELATION_FIELD – полем. Кстати говоря, даже если при создании нового поля в таблице вы не указываете домен, IB создаст его сам, обзовёт каким-нибудь малопонятным именем, типа RDB$1, и засунет его сюда. И в конечном итоге ваше «бездоменное» поле, на уровне метаданных, всё равно будет ссылаться на сгенерированный автоматически домен! Это одна из причин, почему хорошей практикой считается создавать домены ДЛЯ ВСЕХ создаваемых полей самому.
Полностью стытью можно прочитать по ссылкам: http://club.shelek.com/viewart.php?id=279 и также http://dib.shelek.com/dib02.html. -------------------------------------------------------------------------------- Как всегда, ждем вас также в разделе форума "Идеи для статей". Здесь собраны вопросы, ответы на которые не сформулировать в двух словах. Попробуйте свои силы. Подробнее по ссылке: http://forum.shelek.com/index.php/board,105.0.html -------------------------------------------------------------------------------- И не забудьте посетить наш "домик" на карте в Интернете по ссылке http://www.internetmap.info/cgi-bin/go.cgi?site_id=4131%22%20 А теперь прощаемся с Вами до следующего выпуска. С уважением, команда Клуба. |
В избранное | ||