ВВЕДЕНИЕ В СИСТЕМЫ УПРАВЛЕНИЯ БАЗАМИ ДАННЫХ

       

Ограничения кортежа


Определение 10. Ограничения целостности кортежа представляют собой ограничения, накладываемые на допустимые значения отдельного кортежа отношения, и не являющиеся ограничением целостности атрибута. Требование, что ограничение относится к отдельному кортежу отношения, означает, что для его проверки не требуется никакой информации о других кортежах отношения.

Пример 6. Атрибут "Возраст сотрудника" в таблице "Спецподразделение", может иметь дополнительное ограничение "Возраст сотрудника не менее 25 и не более 45", помимо того, что этот атрибут уже имеет ограничение, определяемое доменом - "Возраст сотрудника не менее 18 и не более 65".

Приведенное ограничение кортежа, по сути, является дополнительным ограничением на значения одного атрибута. В этом случае допустимы два решения. Можно объявить новый домен "Возраст сотрудника спецподразделения" и тогда ограничение кортежа становится ограничением домена и атрибута, либо рассматривать это ограничение именно как ограничение кортежа. Оба решения имеют свои положительные и отрицательные стороны.

Замечание. Тут имеются некоторые возможности для оптимизации. Формально, при изменении значения данного атрибута необходимо проверить два ограничения - ограничение атрибута и ограничение кортежа. Но в данном случае ограничение кортежа сильнее ограничения атрибута и достаточно проверить только ограничение кортежа. Разумно построенная СУБД могла бы выявлять такие случаи и уменьшать лишнюю работу.

Пример 7. Для отношения "Сотрудники" можно сформулировать следующее ограничение: если атрибут "Должность" принимает значение "Директор", то атрибут "Зарплата" содержит значение не менее 1000$.

Это ограничение связывает два атрибута одного кортежа.

Пример 8. В накладной можно установить следующую взаимосвязь атрибутов - "Цена*Количество=Сумма", связывающую атрибуты "Цена", "Количество", "Сумма".

Данный пример кажется неестественным, т.к.
сумма является явно избыточным атрибутом, значение которого просто выводятся из значений других атрибутов. Поэтому кажется, что лучше хранить только два базовых атрибута "Цена" и "Количество", а сумму вычислять во время выполнения запросов по мере необходимости. Так, собственно, требует реляционная теория, стремящаяся свести избыточность к минимуму. В практике, однако, дело обстоит сложнее. Например, каждая строка реальной накладной может содержать следующие данные о товаре:



Базовый ли атрибут

Наиме-нование атрибута Описание атрибута Формула для вычислимого атрибута
Name Наименование товара Да
N Количество Да  
P1 Учетная цена товара Да  
S1 Учетная сумма на все количество   S1 = N*P1
PerSent Процент наценки на единицу товара Да  
P2 Наценка на единицу товара   P2 = P1*PerSent/100
S2 Сумму наценки на все количество   S2 = N*P2
P3 Цену товара с учетом наценки   P3 = P1+P2
S3 Сумму на все количество с учетом наценки   S3 = N*P3
NDS Процент НДС Да  
P4 Сумма НДС на единицу товара   P4 = P2*NDS/100
S4 Сумма НДС на все количество   S4 = N*P4
P5 Цена товара с НДС   P5 = P3+P4
S5 Сумма на все количество с НДС   S5 = N*P5
Таблица 3 Атрибуты товара

Базовыми, т.е. требующими ввода данных являются всего 5 атрибутов (выделены серым цветом). Все остальные атрибуты вычисляются по базовым. Нужно ли хранить в отношении только базовые атрибуты, или желательно хранить все атрибуты, пересчитывая значения вычислимых атрибутов каждый раз при изменении базовых?

Решение 1. Пусть в отношении решено хранить только базовые атрибуты.

Достоинства решения:

  • Структура отношения полностью неизбыточна.
  • Не требуется дополнительного программного кода для поддержания целостности кортежа.
  • Экономится дисковое пространство.
  • Уменьшается трафик сети.

    Недостатки решения:

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


    Одни и те же формулы используются во многих местах, поэтому все операторы отбора данных будут содержать одинаковые фрагменты кода с одними и теми же формулами. Имеется риск в разных местах вычислять одни и те же данные по разным формулам.
  • При изменении логики вычислений (что бывает довольно часто при изменении законодательства), необходимо изменить одни и те же фрагменты кода во всех местах, где они встречаются. Это сильно затрудняет модификацию приложений.
  • Если возникает нерегламентированный запрос, то человек, формулирующий запрос должен помнить все эти формулы.

    Решение 2. Предположим, что в отношении решено хранить все атрибуты, в том числе и вычислимые.

    Достоинства решения:

  • Код, поддерживающий целостность кортежа (и содержащий формулы для вычислимых атрибутов), хранится в одном месте, например в триггере, связанном с данным отношением.
  • При изменении логики вычислений, изменения в формулы требуется внести только в одном месте (в триггере).
  • Запросы к базе данных содержат меньше формул и поэтому более просты.
  • Легче формулировать нерегламентированные запросы, т.к. в запросе используются атрибуты, имеющие для бухгалтера конкретный смысл.

    Недостатки решения:

  • При изменении логики расчета надобность в некоторых атрибутах может исчезнуть, зато может появиться потребность в новых атрибутах. Это потребует перестройки структуры отношения, что является весьма болезненной операцией для работающей системы.
  • Структура отношения становится более сложной и запутанной.
  • Увеличивается объем базы данных.
  • Увеличивается трафик сети.

    Как видим, оба решения имеют свои достоинства и недостатки. Важно то, что программный код, содержащий эти формулы, не исчезает ни в каком из этих решений (да и куда он денется, раз такова предметная область!). Только в одном случае код хранится в одном месте, а в другом может быть "размазан" по всему приложению.

    На самом деле данный пример сильно упрощен, т.к. еще одной неприятной особенностью наших бухгалтерий является то, что все расчеты должны вестись с определенной точностью, а именно - до копеек.


    Возникает проблема округления, а это еще более усложняет формулы для расчетов цен. Простой пример - вычисление НДС содержит операцию деления, следовательно может приводить к бесконечным дробям типа 15,519999… Такую дробь необходимо округлить до 15.52. Если продается одна единица товара, то это не страшно, но если продается несколько единиц товара, то сумму НДС на все количество можно считать по разным формулам:

  • S4 = N* ROUND(P2*NDS/100) - СНАЧАЛА округлить при вычислении НДС на единицу товара, а ПОТОМ умножить на все количество, или
  • S4 = ROUND(N*P2*NDS/100) - СНАЧАЛА умножить на все количество, а ПОТОМ округлить до требуемого знака.

    Лирическое отступление. Автор, как математик по образованию (к.ф.-м.н.), считает, что верной, безусловно, является первая формула. Действительно, вычисляя по первой формуле, мы получим одну и ту же сумму НДС независимо от того, продали мы одну партию товара, содержащую 50 единиц, или продали 50 партий по одной единице в каждой. При вычислениях по второй формуле сумма НДС в партии, состоящий из 50 единиц товара отличается от суммы НДС по 50 партиям по одной единице товара в каждой. Разработав несколько складских программ, автор получал разные ответы на этот вопрос в разных бухгалтерия, разные ответы на этот вопрос в одной бухгалтерии в разное время, и разные ответы на этот вопрос в разных налоговых инспекциях. В конечном итоге, автор пришел к грустному выводу, что для того, чтобы стать бухгалтером, его способностей и образования недостаточно.

    Другие решения. Можно попытаться использовать и другие решения, для облегчения разработки и сопровождения в данном случае. Например, можно хранить в базовом отношении только базовые атрибуты, а для работы бухгалтерии использовать заранее подготовленные представления (динамические отношения, задаваемые оператором SQL). Тогда логика расчетов будет храниться в одном SQL-операторе, определяющем это представление. Другим вариантом может быть сохранение формул в виде хранимых процедур и функций базы данных.

    Проверка ограничения. К моменту проверки ограничения кортежа должны быть проверены ограничения целостности атрибутов, входящих в этот кортеж.

    Ограничение кортежа является немедленно проверяемым ограничением. Действительно, ограничение кортежа не зависит ни от каких других объектов базы данных, кроме атрибутов, входящих в состав кортежа. Поэтому никакие изменения в других объектах не могут повлиять на истинность ограничения.


    Содержание раздела