Правильная ссылка на эту страницу
http://az-design.ru/Support/DataBase/SQL/CelkoJ/02h005.shtml

ГЛАВА 5.
Схемы кодировки данных

       Никто не записывает данные сразу в БД. Сначала их соответствующим способом кодируют и лишь затем помещают в столбец. Слова принадлежат к определенному языку и составляются из букв; данные измерений записываются числами. Правда, к буквам и числам мы настолько привыкли, что уже не рассматриваем их в качестве кодов. Часто мы также не задумываемся о том, что одну и ту же сущность или свойство можно идентифицировать (и, следовательно, закодировать) различными способами. Как обозначить пациента больницы — именем или номером медицинского страхового полиса? Это может зависеть от того, для кого предназначается база данных — для врача или для страховой компании. Как идентифицировать песню — по названию, по позиции в альбоме или обоими способами? Или стоит включить в БД мелодию — в виде нот или в виде файла мультимедиа? Никто не обучает программистов составлению схем кодировки, поэтому зачастую они составляются “на лету”. Причем во многих случаях самодельной схеме отдается предпочтение даже при наличии общепринятого стандарта кодирования. Начинающие программисты считают, что о разработке схемы кодировки они вообще заботиться не должны — это дело компьютера, пусть он и разбирается. С появлением SQL такое отношение только укрепилось благодаря иллюзии, что любые ошибки проекта можно позже исправить с помощью оператора ALTER.
       Да, компьютер способен решить множество проблем, но программы для ввода и проверки данных очень сложны и трудны в обслуживании. Запросы к базам данных с замысловатыми схемами кодировки сложны в разработке и ресурсоемки в исполнении. При этом рано или поздно разбираться с кодированием все равно придется человеку. Неудачные схемы кодировки обязательно приводят к неверному вводу и выводу и в конце концов становятся причиной появления некорректной модели данных.

Плохие схемы кодировки

       В качестве примера рассмотрим систему учета автомобилей в одном южном штате. Она начиналась, как система с перфокартами, написанная на Коболе. Большинство читателей, вероятно, слишком молоды, чтобы помнить перфокарты. Напоминаю: перфокарта — это лист жесткой бумаги, на котором двоичному представлению символов соответствует набор пробитых и непробитых позиций. Возможные позиции для отверстий выстроены в 80 вертикальных колонок, каждая из которых используется для кодирования одного символа — отсюда фиксированная длина строки. Перфокарты пробивались на специальном устройстве с клавиатурой наподобие клавиатуры пишущей машинки: по мере того как оператор набирал текст, устройство автоматически меняло перфокарты.
       В исходной системе учета автомобилей на каждой карточке выделялась одна колонка для одноразрядного кода типа автомобиля: частный, с наемным шофером, такси, грузовик, маршрутный автобус и т.п. Шло время, и в систему добавлялись новые типы — для ветеранов различных войн, для университетских выпускников, в общем, для любой группы лоббистов, которая обладала достаточной политической властью, чтобы пробить себе право на специальный номерной знак.
       Скоро количество типов превысило 10, и одноразрядной системы для них хватать перестало. Место для добавления еще одного разряда на перфокартах было, но в Коболе используются поля фиксированной длины, и потому изменение разметки карты было невозможно без корректировки программ и настройки перфорирующих устройств.
       Поначалу проблема была решена следующим образом: оператор вместо цифры вводил знак препинания, расположенный на одной с цифрой клавише. Сначала в схему попал один знак препинания, за ним другой, и вскоре в системе кодов были все символы, соответствующие верхнему ряду клавиш на клавиатуре.
       К несчастью, размещение знаков препинания на клавиатуре менялось от устройства к устройству, поэтому перед обновлением базы данных для каждого набора перфокарт приходилось разрабатывать специальную программу для преобразования раскладки к оригинальным кодам модели IBM 026. Такая практика продолжалась даже тогда, когда все эти устройства переместились в свой механический рай.
       Просто контролировать попадание кода в заданный числовой диапазон было нельзя. Приходилось использовать простую программу, которая проверяла совпадение вводимого кода с более чем 20 допустимыми значениями. Звучит как будто не очень внушительно, но учтите — за один только квартал система должна была обработать более трех миллионов записей.
       При этом нужно было еще помнить, на какой именно машине создана данная запись. Естественно, количество ошибок было очень велико. Если бы код с самого начала сделали двухразрядным (от 00 до 99), никаких проблем не возникло бы. Если бы я создавал эту систему сегодня, я бы просто завел для номера столбец типа INTEGER и мог бы себе позволить столько номеров, сколько понадобится.
       О втором примере сообщило в 1987 г. издание Information Systems Week. Собственно, вся история была заключена в первом предложении: “По-видимому, хаос и огромное число ошибок в работе новой системы управления соцобеспечением Нью-Йорка связаны с чрезмерным увеличением количества кодов, необходимых для ввода данных, и с вытекающей из этого сложностью обучения операторов”. В остальной части статьи рассказывалось о попытке объединить в новой системе несколько старых. В результате слияния количество ошибок возросло с 2 более чем до 20%, поскольку толком слить имевшиеся схемы кодировки так и не удалось.
       Как при встрече распознать плохую схему кодировки? Один из характерных признаков — отсутствие возможности расширения. Поговорите с кем-нибудь, кому приходилось переконфигурировать систему с записями фиксированной длины при переходе от старых к новым почтовым индексам. Физически в SQL такой проблемы нет, но она может проявиться на логическом уровне.
       Другое свойство плохих схем — неоднозначные коды. Наверное, самый забавный случай связан с попыткой ввести в итальянскую телефонную систему “службу точного времени”. Для нее был подобран трехзначный телефонный номер, совпавший с междугородным кодом Милана, в результате чего никто не мог дозвониться в Милан, не узнав попутно, который час.
       Такие вещи происходят чаще, чем кажется, причем наиболее типичная форма ошибки — слишком вольная трактовка кода, соответствующего случаю “Другое”. Очень разные случаи кодируются как идентичные, и в результате выполнения запроса пользователь получает некорректную информацию.
       В плохой схеме кодировки нет кодов для отсутствующих, неизвестных, неприменимых или неклассифицируемых значений. В классической истории рассказывается о человеке, который ради шутки зарегистрировал для своей машины номерной знак “NONE” и вскоре получил по почте тысячи штрафных квитанций. В дорожной полиции не было специального кода для случаев, когда на квитанции не указан номер машины, и потому в поле для номера они писали просто “none” (нет). Как только в БД появился номерной знак этого несчастного, СУБД зарегистрировала совпадение и отправила на его адрес все неоплаченные квитанции, в которых отсутствовал номер автомобиля.
       Вы, вероятно, скажете, что в SQL эту проблему легко решить с помощью значения NULL? Увы, к сожалению, во многих функциях SQL оно игнорируется. SQL-запрос:

SELECT tag_nbr, SUM(fme) 
  FROM tickets 
  GROUP BY tag_nbr;

предназначенный для выдачи суммы штрафов для каждого автомобиля, сгруппирует все записи, не содержащие номера, и выдаст полную сумму для этой группы, словно эти записи относятся к одной машине. Но вам, скорее всего, хотелось бы видеть информацию по каждому такому случаю в отдельности, потому что вряд ли во всей Калифорнии отыщется всего один автомобиль без номера.
       Имеются также небольшие, но существенные различия между пропущенными, неизвестными, неприменимыми, неклассифицируемыми и ошибочными значениями. Например, в международной классификации заболеваний код 999 999 применяется для неклассифицируемой болезни, то есть, болезни, наличие которой у пациента сомнений не вызывает, но диагностировать которую не удается. Это безрадостное состояние, конечно, отличается от отсутствующего кода заболевания (пациент только что пришел в больницу, может быть, даже и не болен), неприменимого кода (осложнения беременности для мужчины), неизвестного кода (болен, ожидает результаты анализов) или ошибочного кода (в графе для температуры пациента значится 100°С).

Типы схем кодировки

       Далее я расскажу о своей классификации схем кодировки и приведу рекомендации по их использованию. Вы могли уже встречать некоторые из этих идей в библиотечном деле или в других областях, но применительно к обработке данных, насколько я знаю, никто классификацию разрабатывать не пытался.

Перечисляющая кодировка

       Перечисляющая кодировка состоит в упорядочении значений атрибута и последующем присвоении каждому значению числа или буквы. Числа обычно предпочтительнее букв, поскольку при добавлении новых значений их можно увеличивать безгранично. Перечисляющие схемы хороши для коротких списков, по по мере увеличения длины их эффективность падает.
       Запомнить длинный список кодов сложно, да и упорядоченность с добавлением новых значений, скорее всего, будет нарушена. Упорядочивать значения лучше всего на основе их естественного чередования, если такое имеется. Это может быть хронологический порядок (1 случилось раньше, чем 2) или порядок выполнения (1 необходимо сделать раньше, чем 2). Иногда используют такой порядок: сначала часто встречающиеся значения, потом — реже встречающиеся значения. Наиболее частым случаям можно присвоить коды покороче. Уместны списки, упорядоченные по физическим характеристикам (масса, цвет и пр.).
       Высказавшись в пользу естественного упорядочения, я должен признать, что гораздо чаще в реальной жизни встречается алфавитный порядок, поскольку его легче реализовать на компьютере. В стандарте ANSI X3.31, например, имена округов США сначала выстроены по алфавиту (отдельно в каждом штате), а затем пронумерованы.

Кодировка единиц измерения

       Эта кодировка обозначает единицы измерения — фунты, метры, вольты, литры. Как правило, единица измерения не записывается в столбец, а просто подразумевается, но может присутствовать в нем и в явном виде. Последнее часто происходит с “денежными” столбцами, в которые подставляется символ доллара, фунта, йены и пр.
       Подробнее о шкалах и измерениях — в главе 4.

Кодировка аббревиатурами

       Сокращения нужны, чтобы сэкономить пространство, занимаемое значением атрибута, но вместе с тем сохранить его понятность. Аббревиатура может быть как переменной, так и постоянной длины, но компьютерщикам, конечно, ближе второй вариант. В качестве примера взгляните на двух-буквенные обозначения штатов (СА — Калифорния, AL — Алабама), которые пришли на смену сокращениям переменной длины (соответственно, Calif, и Ala.).
       Добротная система аббревиатур очень удобна, но по мере роста количества кодируемых значений повышается вероятность путаницы. Трехбуквенные коды больших аэропортов еще можно запомнить: LAX — Лос-Анжелес, SFO — Сан-Франциско, SVO — Шереметьево, но разобраться с кодами небольших аэропортов гораздо сложнее.
       Еще один пример — стандартные коды стран ISO-3166, которые могут быть двухбуквенными, трехбуквенными или числовыми. Их поддерживает сетевой координационный центр RIPE.

Алгоритмические коды

       Алгоритмическая кодировка заключается в создании кода из значения по определенному алгоритму. Алгоритм должен быть обратимым, чтобы из кода можно было восстановить исходное значение. Хотя это и не обязательно, код обычно бывает короче (по крайней мере, его размер ограничен сверху) и упорядоченнее исходных значений. Наиболее типичным видом алгоритмического кодирования является шифрование — очень важный процесс, заслуживающий отдельного рассмотрения.
       В астрономии используется алгоритмическое кодирование дней — так называемая юлианская дата, которая представляет собой количество дней, прошедших с определенного дня (1 января 4713 г. до н. э.) в далеком прошлом. Юлианский день фактически есть преобразование даты в целое число. Для более приземленных целей удобна упрощенная юлианская дата — количество дней, прошедших с начала года. Она, очевидно, заключена в пределах от 1 до Зб5 или 366. Применение алгоритма требует компьютерного времени как на вводе, так и на выводе данных, но кодирование, как правило, окупает эти затраты, так как позволяет легко осуществлять поиск и расчеты, которые были бы невозможны с исходными данными.
       Другой пример — хэш-функции, которые преобразуют одни численные значения в другие, предназначенные для хранения. Вариантом алгоритмической кодировки можно также считать округление чисел перед помещением в БД.
       Разница между аббревиатурой и алгоритмом не особенно четкая. Сокращение можно считать особым случаем алгоритма, описывающим удаление или замену букв. Чтобы все-таки разделить их, обращайте внимание на следующие признаки
       1. То, что легко понимается человеком, является аббревиатурой.
       2. Результат алгоритмического кодирования легкому пониманию не поддается.
       3. Алгоритмическое кодирование может возвращать один и тот же код для нескольких значений. Аббревиатура всегда однозначна.

Иерархические схемы кодировки

       В иерархической схеме кодировки набор значений разделяется на несколько категорий, те, в свою очередь, — на несколько подкатегорий, и так далее, пока не будет достигнут некий нижний уровень. Такие схемы называют также вложенными или древовидными. У каждой категории есть определенное значение, а подкатегории его уточняют.
       Наиболее очевидный пример — почтовый индекс, разделяющий территорию США на отдельные регионы. При чтении слева направо каждая следующая цифра уточняет расположение адресата: регион, штат, город и, наконец, почтовое отделение. Рассмотрим индекс 30310. Номера с 30000 до 39999 соответствуют юго-востоку США. Номера с 30000 по 30399 распределены по Джорджии, а индексы с 30300 по 30399 указывают на Атланту. Весь индекс, 30310, идентифицирует почтовое отделение на западной окраине города. Для расшифровки индекса его нужно читать по цифрам слева направо — сначала одну цифру, потом две, потом оставшиеся две.
       Другой пример — библиотечная классификация DDC (Dewey Decimal Classification), применяемая в американских библиотеках. Номера в шестой сотне (начинающиеся с 5) покрывают “Естественные науки”, номера 510-519 соответствуют математике и, наконец, код 512 обозначает алгебру. Схему можно расширять далее, добавляя позиции после десятичной точки для обозначения подразделов алгебры.
       Иерархические схемы кодировки хороши для работы с большими объемами данных, обладающих естественной иерархической структурой. Структурированную информацию легко организовать и представить, но при разработке подобных схем также возникают проблемы.
       Во-первых, древовидная структура не обязана быть сбалансированной: для некоторых категорий необходимо больше кодов, чем для других. В системе DDC мало кодов для восточных и древних религий, что отражает предпочтение, отдававшееся христианским и иудаистским текстам. Между тем, в наши дни в Библиотеке Конгресса США явно лидирует буддизм — книг по нему больше, чем по любой другой религии Земли.
       Во-вторых, размещение определенных категорий на дереве может со временем оказаться неудачным. Например, в системе DDC книги по логике представлены кодом 164 из раздела “Философия”, тогда как более уместен был бы код из математического раздела. В XIX веке математической логики просто не было, а сегодня мало кому придет в голову искать книги по логике в философском разделе. Создатель системы DDC просто закрепил в ней понятия своего времени — как поступают и многие современные программисты.

Векторные коды

       Вектор состоит из фиксированного числа компонентов. Они могут быть упорядоченными и неупорядоченными, обладать постоянной или переменной длиной, быть взаимно зависимыми или независимыми, но они всегда присутствуют в заданном количестве, и код имеет смысл лишь при наличии всех компонентов.
       Самый распространенный векторный код — дата, состоящая из числа, месяца и года. Компоненты даты, конечно, имеют некоторый смысл и сами по себе, но во всей полноте суть даты раскрывается лишь при наличии всех трех компонентов. Порядок их расположения особого значения не имеет: в мировой практике вы, вероятно, найдете все возможные сочетания. Допустимые значения для числа зависят от года (високосный или нет) и месяца (который может иметь 28, 29, 30 или 31 день). Компоненты могут разделяться точками (28.09.2005), косыми чертами (28/09/2005), пробелами (28 сентября 2005 г.) или вообще никак не разделяться (28092005).
       Другой пример — код ISO размеров автомобильных покрышек, составляемый из диаметра колеса в дюймах, типа покрышки (буквенный код) и ее ширины в миллиметрах. Код 15R155 соответствует 15-дюймовой радиальной покрышке шириной 155 миллиметров, а код 15SR155 — покрышке тех же размеров, но с опоясывающим металлическим кордом. Несмотря на смесь американских и международных единиц это вполне общее физическое описание покрышки.
       Векторные схемы информативны, кроме того, они позволяют подобрать для каждого компонента наилучший способ кодирования, но вместе с тем иногда приходится придумывать, как разделить код на составные части (во многих СУБД имеются функции для разделения на компоненты дат, адресов и имен). Сортировка по компонентам практически невозможна, разве что в том порядке, в каком они стоят в коде.
       Еще один недостаток заключается в том, что неудачный выбор кода всего для одного компонента делает бесполезной всю схему. Расширение кода тоже проблематично. Что если в код покрышки нужно будет включить еще толщину в миллиметрах? Раз появляется еще одно число, его придется отделять пунктуацией. Вообще, такие переделки обычно чреваты необходимостью вносить правки в очень многие программы.

Составные коды

       Составной код представляет собой комбинацию произвольного числа нескольких компонентов. Как и в векторной кодировке, компоненты могут быть упорядоченными и неупорядоченными, зависимыми и независимыми, разделяться пунктуацией, пробелами и пр. Часто в составном коде присутствует иерархическая структура, которая выстраивается с помощью уточняющих компонентов, которые добавляются к коду справа. Иногда в качестве составного кода используется список свойств, каждое из которых может присутствовать или отсутствовать. Порядок компонентов тоже не является обязательным.
       Составные коды были популярны в мастерских начала XX в. К изделию прикреплялся бумажный ярлык, на котором каждый рабочий записью подтверждал завершение очередного этапа обработки. Составные коды и по сей день используются в авиационной промышленности: с помощью длинного кода описывается набор деталей, входящих в состав компонента (его называют корневым или родительским), который расположен в начале кода. Еще один вариант составного кода — неупорядоченный кворум-код. Чтобы некое условие считалось выполненным, в таком коде должно присутствовать n компонентов из k. Например, чтобы деталь считалась прошедшей контроль качества, ее должны одобрить любые три инспектора из пяти.
       Самый популярный составной код — список ключевых слов, стоящий в начале какого-либо документа и описывающий его содержание. Ключевые слова назначаются документу автором или библиотекарем. Как правило, они выбираются из ограниченного специализированного словаря. В начале компьютерной эры популярность составных кодов снизилась, поскольку из-за переменной длины их трудно было хранить в первых компьютерных системах, в которых записи имели фиксированную длину (помните перфокарты?). Чтобы такие коды можно было корректно сортировать, их приходилось хранить в виде строк, выровненных влево.
       Неудачно разработанный составной код может быть неоднозначным. Например, какой код стоит в начале цепочки “1234” — 1 или 12? В базах данных составные коды обычно преобразуются в набор флажков “да/нет”, расположенных в смежных столбцах файла, то есть, фактически из истинных составных кодов превращаются в булевы векторные коды.

Общие правила разработки кодировок

       В этом разделе приведены общие рекомендации по разработке кодировок. Не стоит воспринимать их как жесткие правила — у всех у них есть исключения.

Опирайтесь на существующие стандарты кодирования

       Использование стандартных схем кодирования — очевидная рекомендация. Применение одних и тех же кодов существенно облегчает сбор данных и обмен ими. Кроме того, можно быть уверенным в том, что специалист, который кроме разработки кодировки ничем иным не занимался, справился с этой задачей лучше, чем человек, которому приходится придумывать коды и одновременно обслуживать базу данных.
       Если область, в которой вам приходится работать, для вас в новинку, непременно обратитесь к эксперту. Это кажется очевидным, но мне пришлось однажды работать над проектом музыкальной БД, в котором программисты старательно избегали разговоров с профессиональными библиотекарями, также участвовавшими в проекте. В результате, записи идентифицировались по GUID, а не по номерам из каталога Шванна (Schwann), что было бы вполне логично. Не нашли эксперта — самостоятельно ищите стандарты в Интернете. Проверьте, нет ли нужного стандарта ISO, правительственного стандарта, почитайте материалы конкретных промышленных групп и организаций.

Предусматривайте возможность расширения

       Обязательно предусматривайте возможность расширения кодировки. Оператором ALTER можно превратить однобуквенный код в двухбуквенный, но нельзя изменить размещение символов в отчетах и на экране. Обязательно задавайте размер кода на одну позицию больше, чем по вашему мнению необходимо. Визуально строка “01” гораздо больше похожа на код, чем просто “1”, которую легко спутать с количеством.

Явно задавайте коды для отсутствующих значений

Обоснование
       Старайтесь по возможности избегать кодов NULL, задавая в схеме кодирования специальные коды для отсутствующих значений. В SQL значения NULL обрабатываются не так, как обычные значения. Кроме того, NULL ничего не говорит о том, какое именно значение отсутствует.
       Часто для отсутствующих значений применяют коды, состоящие из одних нулей или одних девяток. Например, в ISO пол кодируется так: 0 — неизвестный, 1 — мужской, 2 — женский, 9 — не определен. Последний код используется, например, для обозначения субъектов права, у которых нет пола, скажем, корпораций.
       В версиях Фортрана до стандарта 1977 г. “чистые” (без единого отверстия) столбцы перфокарты считались нулями. С другой стороны, столбец, в котором действительно был записан ноль, содержал пробитые отверстия. Этим, кстати, пользовались в целях безопасности, специально добавляя нули в левой части кода, чтобы довести его до фиксированной длины, не оставляя “чистых” столбцов. В Фортране-77 проблема путаницы между пустым значением и нулевым значением была решена, но она все еще живет в непродуманных SQL-системах, которые неспособны отличить NULL от пустой строки или нуля.
       Коды отсутствующих значений, состоящие из девяток или букв “Z”, при сортировке оказываются в конце экрана или отчета. Расположение значений NULL при сортировке зависит от реализации.

Исключения
       Совсем избежать значений NULL нельзя, поскольку в ряде случаев они существенно облегчают вычисления.

Не показывайте коды пользователю

       По возможности старайтесь не показывать конечному пользователю “чистые” коды, а переводите их в понятные значения. Это, конечно, не относится к общеупотребительным кодам, которые и так будут распознаны пользователем. Скажем, большинству людей двухбуквенное обозначение штата понятно без расшифровки. С другой стороны, мало кто сможет без перевода разобраться в сложных кодах оплаты, которые применяются некоторыми телефонными компаниями.
       Трансляция кодов включает в себя их форматирование. Иногда достаточно включить в код пунктуацию (дефисы, запятые) или символ денежной единицы. Однако, в многоуровневой архитектуре форматирование осуществляется не в БД, а в интерфейсной программе. Типичная для новичка ошибка — попытка вставить лишние нули или разделители в числовое значение. Превратив тем самым число в строку, вы теряете все возможности проведения вычислений с числовыми и календарными значениями.
       Для трансляции кодов применяются специальные таблицы. Они не являются представлением сущности или отношения. Обращение к ним подобно вызову функции в процедурном языке. Общий вид такой таблицы таков:

CREATE TABLE Какие-тоКоды 
   (код <тип_данных> NOT NULL PRIMARY KEY,
    определение <тип_данных> NOT NULL);

Иногда определение также включается в состав первичного ключа. В описание столбца с кодом могут включаться ограничения СНЕСК(), но, как правило, внутри приложения особо беспокоиться о проверках не приходится, ибо такие таблицы разрабатываются за пределами БД и используются только для чтения.

Не помещайте все коды в одну таблицу

       Бывают случаи, когда некий бездарный способ действия настолько распространен, что получает собственное имя. В особо тяжелых случаях, как и положено болезни, вместо имени применяется аббревиатура. Впервые мне пришлось столкнуться с болезнью OTLT (One True Lookup Table, единая истинная таблица кодов) в 1998 г., в одном из форумов CompuServe, и с тех пор в различных группах новостей я вижу ее ежегодно.
       Суть этой болезни в том, что вместо создания собственной таблицы для каждой кодировки, мы все кодировки помещаем в одну огромную таблицу. Схема этой таблицы выглядит так:

CREATE TABLE OTLT (
   тип_кода     INTEGER MOT NULL,
   код          VARCHAR(n) NOT NULL,
   определение  VARCHAR(m) NOT NULL,
PRIMARY KEY (тип_кода, код));

       На практике числа m и n обычно равны чему-то вроде 255 или 50 — значениям по умолчанию для данного SQL-продукта.
       Оправдать объединение всех кодировок в одну таблицу обычно пытаются тем, что в этом случае для поддержания всех кодировок программисту достаточно написать одну интерфейсную программу. Но это полный маразм, которому ни в коем случае нельзя поддаваться. Прежде чем читать следующие разделы, попробуйте самостоятельно составить список недостатков этой методики, а потом сверьте с моим списком. Не упустил ли я чего-нибудь?
       1. Нормализация. Если взглянуть в корень, то этот подход не оправдывает себя, так как представляет собой попытку нарушить требования первой нормальной формы. Я, конечно, вижу, что у таблицы OTLT есть первичный ключ и что все столбцы в базе данных SQL должны быть скалярными и принадлежать к одному типу данных. И тем не менее я уверенно утверждаю, что эта таблица не приведена к первой нормальной форме. Тот факт, что два домена используют один и тот же тип данных, еще не делает их одним и тем же атрибутом. Добавочный столбец “тип_кода” меняет домен других столбцов и тем самым противоречит требованиям первой нормальной формы, поскольку не является атомарным. Таблица должна моделировать один набор сущностей или одно отношение, а не сотни их. Как говорил Аристотель: “Быть чем-то значит быть чем-то конкретным. Не быть чем-то конкретным илибыть чем-то вообще значит быть ничем”.
       2. Объем памяти. Для хранения таблицы OTLT требуется больше памяти,чем для отдельных таблиц с кодировками — из-за лишнего столбца стипом кода. Представьте себе, что вы объединили в одной таблице международную классификацию болезней (ICD) и библиотечную классификацию DDC. Каждый раз при переходе к другой кодировке вам придется извлекать таблицу OTLT целиком.
       3. Типы данных. Всем кодировкам насильственно приписан один типданных: строка максимальной длины, которая может потребоваться в настоящем или будущем для одной из кодировок таблицы. Тип VARCHAR(n) не всегда представляет собой лучший способ хранения данных. Кто-нибудь обязательно вставит в таблицу огромную строку, которая замечательно выглядит на экране, но в своей невидимой правой части содержит лишние пробелы или другие символы. Во многих SQL-продуктах с точки зрения хранения и доступа к данным предпочтительнее применять тип CHAR(n). С числовыми кодами можно выполнять арифметические операции, проверять диапазоны, контрольные цифры и т.п. с помощью ограничений СНЕСК(). Коды в виде дат можно преобразовывать в названия праздников и других событий. Не существует универсального типа данных, который подходил бы ко всем случаям. Если в одной кодировке допустимы значения NULL, в таблице OTLT они будут допустимы во всех кодировках.
       4. Проверка. Единственный способ применить ограничение CHECK() в таблице OTLT — написать огромную конструкцию CASE:

CREATE TABLE OTLT
   (тип_кода CHAR(n) NOT NULL
             CHECK (тип_кода IN (<тип 1>, .... <тип n>)),
    код      VARCHAR(n) NOT NULL
             CHECK (CASE WHEN тип_кода = <тип 1>
                         AND <проверка 1>
                         THEN 1
--предполагаем, что в вашем SQL-продукте размер CASE неограничен
                         WHEN тип_кода = <тип п>
                          AND <проверка п>
                         THEN 1
                         ELSE О END = 1),
    определение VARCHAR(m) NOT NULL,
PRIMARY KEY (тип_кода, код));

       Это означает, что проверка будет занимать очень много времени, поскольку любое изменение нужно будет проверять во всех конструкциях WHEN, пока SQL не найдет то из них, что возвращает TRUE. Придется также добавить ограничение CHECKQ в описание столбца “тип_ко-да”, чтобы пользователь не мог создать ошибочную кодировку.
       5. Гибкость. В таблице OTLT предусмотрен один столбец для кода, стало быть, ее нельзя использовать для кодов, состоящих из n значений,если n > 1. Допустим, если я хочу преобразовывать в название местности пару координат “широта-долгота”, мне придется добавить в таблицу еще один столбец.
       6. Обслуживание. В разных кодировках возможно одно и то же значение кода, поэтому вам придется постоянно следить за тем, с какой именно кодировкой вы работаете. Например, как код 1CD, так и код DDC имеют одну структуру — три цифры, точка, три цифры.
       7. Безопасность. Чтобы запретить некоторым пользователям просмотр одной из кодировок, к таблице OTLT придется добавить представления,в которых с группой пользователей сопоставлялся бы тип кода, который им разрешено изменять. В этом случае от оправдания единой таблицы вообще мало что остается: в интерфейсе теперь приходится иметь дело с несколькими представлениями почти так же, как пришлось бы работать с несколькими таблицами.
       8. Отображение. В интерфейсную программу приходится передавать все кодировки без исключения, что связано с большими накладными расходами и является потенциальным источником ошибок.

Храните коды в базе данных

       Таблицы с кодами должны быть частью БД. Их можно использовать для проверки вводимых данных, для преобразования кодов, для создания документации.
       В 1993 г. я был потрясен, увидев, как в одной из крупнейших больниц Лос-Анжелеса служащая по старинке искала коды болезней в огромной амбарной книге, вместо того чтобы вывести их на экран терминала. В больнице все еще работали старые мэйнфреймы IBM с терминалами 3270, на которых оператор даже справочную систему не мог вызвать. В системе “клиент-сервер” таблицу с кодами для уменьшения сетевого трафика можно загрузить на отдельные рабочие станции. Еще лучше сделать на основе этой таблицы раскрывающийся список, чтобы уменьшить вероятность опечаток. Изменения в кодах в этом случае не заставят переписывать приложение. Если коды меняются со временем, в таблицу можно включить столбцы с датами начала и окончания действия кода. Это позволит корректно обращаться не только к актуальным, но и к старым данным.

Многосимвольные кодировки

       Некоторые СУБД поддерживают кодировки ASCII, EBCDIC и Unicode. Вам необходимо знать об этом, чтобы корректно настраивать сравнения и нормализацию текста.
       Предикат “<строка> IS [NOT] NORMALIZED” в стандарте SQL-99 констатирует, относится ли строка Unicode к одной из четырех нормальных форм (т. е. D, С, KD и КС). Термин нормальная форма имеет здесь значение, отличное от его применения в реляционном контексте. В модели Unicode один символ может составляться из нескольких других символов. Над некоторыми латинскими буквами могут вставляться диакритические знаки.
       Определенные последовательности букв заменяются лигатурами. В некоторых языках, например корейском и вьетнамском, иероглифы составляются в результате объединения символов как по вертикали, так и по горизонтали. В некоторых языках одна и та же буква отображается по-разному в зависимости от положения в слове, например сигма в греческом или и с акцентом в чешском. Говоря коротко, писать — это не просто ставить буквы друг за другом.
       В стандарте Unicode определен порядок таких конструкций в соответствующих нормальных формах. Один и тот же видимый результат можно получить с помощью разного расположения символов или даже с помощью разных наборов символов, но при организации поиска по тексту вам удобнее будет знать, что текст нормализован, чем пытаться анализировать буквы, лигатуры, иероглифы “на лету”. За подробностями и бесплатным ПО обращайтесь на сайт www.unicode.org.




<<< Пред. Оглавление
 
След. >>>

Дата последнего изменения:
Thursday, 21-Aug-2014 09:10:55 MSK


Постоянный адрес статьи:
http://az-design.ru/Support/DataBase/SQL/CelkoJ/02h005.shtml