|
Программирование >> Проектирование баз данных
Некоторые особенности использования неопределенных значений В этом разделе освещаются некоторые проблемы, возникающие при использовании неопределенных значений. Цогда одно неопределенное значение равно другому неопределен ноту знач еншо Давайте обратимся у нашему списку и рассмотрим утверждение, что одно неопределенное значение не равно другому неопределенному значению. Необходимо отметить, что в Oracle существует исключение из этого правила, касающееся использования неопределенного значения в ограничении UNIQUE. Если мы определяем, что комбинация столбцов должна быть уникальной и для одного из них допускается неопределенное значение, то в целях обеспечения ограничения UNIQUE одно неопределенное значение считается равным другому неопределенному значению. Предположим, что таблица X имеет ограничение UNIQUE на столбцах А и В, где В допускает неопределенное значение. Если вы попытаетесь дважды вставить строку, в которой А=1, а значение В не определено, то вторая операция не выполнится из-за нарушения ограничения UNIQUE. Таким образом, в данном конкретном и необычном случае одно неопределенное значение считается равным другому! Следствия неравенства неопределенных значенш1 Давайте рассмотрим одно следствие неравенства двух неопределенных значений (с учетом нашего исключения). Допустим, у нас есть два SQL-запроса: /* 1. */ SELECT * FROM t WHERE t.a = X UNION SELECT * FROM t WHERE t.a О X /* 2. */ SELECT * FROM t WHERE t.a = t.a Ha первый взгляд кажется, что эти запросы должны возвратить все строки таблицы Т. Однако ни один из них не возвратит строки, в которых значение Не определено. Это надо учитывать при разработке отчета или приложения. Принимающего параметр, который будет использоваться как предикат в условии WHERE. Если параметр не определен, то SQL-запрос должен Вернуть только те строки, в которых предикатный столбец не определен, о противном случае он должен вернуть строки, совпадающие с параметром. Это приводит к тому, что нам приходится написать уродливый и потенциально опасный SQL-запрос такого вида: SELECT * FROM t WHERE NVL(:p, NVL(t.a,$NULL)) = NVL(t.a,$NULL) Почему OH уродлив? Да потому, что его не так просто понять и из него не ясно, чего мы хотим добиться. Почему он опасен? Потому что мы используем $NULL как волшебное значение и предполагаем, что столбец А никогда не будет содержать такое значение. Если же это не так, то наща логика разрушится! Последствия для программистов Как насчет ЗОЕ-языков? Если мы используем прекомпиляторы Oracle, то можем ввести индикаторные переменные в соответствии со стандартом ANSI для встроенного SQL. Это означает,- что для каждой внешней переменной в программе, которая соответствует столбцу, допускающему неопределенное значение, мы вводим вторую переменную, с помощью которой наша программа и Oracle показывают, является ли соответствующая переменная неопределенной. В Рго*С эти переменные объявляются как короткие целые. Вот пример, в котором индикаторные переменные используются во встроенном SQL-предложении: EXEC SQL UPDATE t SET t.a = :a:a ind WHERE t.b = :b:b ind; A что произойдет, если мы используем не прекомпилятор, а Visual Basic и драйвер ODBC? Возможны проблемы, поскольку в Visual Basic эквивалента неопределенному значению нет. Работая с символьными строками, можно трактовать пустую строку как неопределенное значение, но числа и даты создают сложности. Часто кодирование и декодирование неопределенных значений выполняют между базой данных и базовым языком. Это, опять-таки, опасно, потому что в таком языке, как Visual Basic, не всегда можно выбрать для представления неопределенного значения число, которое не встречается в столбце базы данных. В таких случаях, может быть, лучше (а иногда и необходимо) иметь в таблице индикаторный столбец, в котором хранится флаг, показывающий, содержит ли главный столбец реальное значение. Использование закодированных значений вместо неопределенного значения Как проектировщикам нам нужно просмотреть все атрибуты в логической модели или столбцы в физической модели, для которых допускается неопределенное значение. Следует относиться к таким столбцам с подозрением и свести их количество к минимуму, учитывая проблемы, о которых мы упоминали выше. Необходимо выяснить, может ли неопределенное значение в данном столбце иметь разное толкование и, если может, важно ли различать эти случаи? Допустим, мы регистрируем сведения о людях и одним из столбцов в таблице PERSONS является столбец SOCIAL SECURITY NO. По каким причинам для этого столбца допускается неопределенное значение? Во-первых, если человек - несовершеннолетний, то у него еще может не быть номера социального страхования (значение Not Applicable, не применимо ). Во-вторых, не каждый может сообщить свой номер сразу же; в этом случае мы не хотим, чтобы это сдерживало процесс регистрации человека (значение Currently Unspecified, на данный момент не задано ). И наконец, если мы регистрируем бродягу, то у него, несомненно, есть номер, но он может не знать его или не иметь возможности определить (значение Unknown, не известно ). Если нужно различать эти значения (Not Applicable, Currently Unspecified, Unknown), TO следует рассмотреть возможность использования не неопределенного, а закодированного значения. В принципе, мы могли бы применить неопределенное значение для одного из вышеуказанных значений, а остальные закодировать. Конечно, выбирая закодированное значение, вы должны обязательно выбрать такое значение, которое в реальной жизни не встречается. Например, если SOCIAL SECURITY NO - численное значение, то для закодированных элементов можно использовать отрицательные значения. Это, помимо прочего, упрощает поиск закодированных значений, если их не нужно дифференцировать, - например, найти записи, у которых SOCIAL SECURITY NO меньше нуля. Однако использовать отрицательные числа для кодирования неопределенного значения, которое может использоваться в агрегатной функции, например при вычислении среднего или минимального номера социального страхования, весьма опасно. Преимущество неопределенных значений в том, что они при вычислении агрегатных функций игнорируются. К счастью, арифметические операции с номерами социального страхования приходится выполнять крайне редко. Международная организация по стандартизации (ISO) разработала стандартные правила кодирования. Например, для кодирования пола или рода ISO предложила следующий стандарт: 0 = Не известен 1 = Мужской 2 = Женский 9 = Не применим Обратите внимание на то, что не известен и не применим заданы разными кодами.* При использовании такой схемы кодирования рекомендуется хранить коды и их значения в базе данных. Получается, что комитет [SO либо никогда не слышал о гермафродитах, либо решил проигнорировать их существование
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |