|
Программирование >> Проектирование баз данных
Данные в столбцы типа DATE в Oracle заносятся с точностью до секунды. Если требуется хранить значения с более высокой точностью, можно воспользоваться следующими приемами: 1. Хранить их в фиксированном формате в символьном поле (например, 1998 02 19 21 4057.223456 ). В этом случае время регистрируется с точностью до миллисекунд и правильно будет выполнено сопоставление дат, но расчет разницы дат превратиться в довольно утомительную процедуру. 2. Проблему расчета разницы дат можно рещить, сохраняя дату и время как число миллисекунд, микросекунд или наносекунд, истекщих с фиксированного момента времени. Недостаток этого подхода в том, что потребуется функция, конвертирующая эти значения в формат, приемлемый для отображения и выдачи сообщений, однако с 38-значными числами у вас вряд ли будут проблемы с точностью. 3. Возможен хорощий компромисс; хранить дату, усеченную до ближайщей секунды, в столбце типа DATE, а остаток в наносекундах (или выбранных вами единицах) в отдельном столбце типа NUMBER. При этом дата обязательно должна быть усечена, а не округлена! Отметим, что в Огас1е7 версии 7.1 и выще, где есть возможность вызывать пользовательские PL/SQL-функции из SQL, несколько проще управлять нерегламентированными отчетами, основанными на таблицах, в которых для хранения дат используются совершенно искусственные методы. Если таблица содержит показания датчика, регистрируемые с точностью до миллисекунд, можно создать представления (необновляемые), в которых эти данные будут содержаться в нужном нам виде. Вот пример определения такого представления: CREATE VIEW sensor readings vl ( sensor id , sensor narae , reading taken , reading value ) AS SELECT r.sensor id , s.sensor name , readings.point in time text(r.read date, r.read msec) , reading value FROM sensor readings r , sensors s WHERE s.sensor id = r.sensor id; В отличие от некоторых других РСУБД, в Oracle есть только один тип данных для регистрации информации о датах и времени, и многие посчитали бы, что Oracle сейчас в этом отнощении немножко не дотягивает до стандарта SQL ANSI-92. В Oracle значение типа DATE всегда содержит временной компонент - независимо от того, хотите ли вы этого и считаете ли вы его значащим. Если время не указано или усечено с помощью функции TRUNC, то оно регистрируется как полночь. Рекомендуем использовать правила именования, позволяющие отличить столбцы, в которых хранятся только даты, от столбцов, содержащих и дату, и время. Например, APPOINTMENT DT - столбец, включающий дату и время, а APPOINTMENT D - столбец, содержащий только дату. Кроме того, желательно активно противодействовать тому, чтобы в столбцах, предназначенных только для дат, хранился временной компонент. В следующем примере демонстрируются и метод профилактики (отклонение не соответствующих значений при помощи ограничения), и метод лечения (усечение времени при помощи триггера). Выбор за вами. Советуем воспользоваться хотя бы одним из этих приемов, так как при наличии в одном столбце таблицы дат со временем и дат без времени вы можете получить в результате сравнения неожиданные и нежелательные результаты. Если же вас волнуют последствия отключения триггеров (например, во время загрузки большого массива данных), то используйте и профилактику, и лечение. CREATE TABLE events ( event code VARCHAR2(10) CONSTRAINT event code exist FOREIN KEY REFERENCES event types , event date DATE CONSTRAINT event date no time CHECK (event date = TRUNC(event date)) - preventin CREATE TRIGGER event date BEFOR INSERT OR UPDATE ON events FOR EACH ROW BEGIN ;new.event date := TRUNC(;new.event date); END; - cure Одна из распространенных причин возникновения проблем с датами - неверное определение разработчиком маски формата в программе. Типичными примерами таких ошибок являются использование ММ вместо Ml для обозначения минут (ММ - это месяц в числовом формате) и использование НН вместо НН24 для обозначения часов (при 24-часовом формате измерения времени). К несчастью, у разработчика есть только одно средство для предотвращения таких ошибок - внимательно просматривать код! Впрочем, если у вас есть программы проверки кода, они могут найти подозрительные маски формата дат. Так, например, маска DD-MON-YYYY НН:ММ подозрительна вдвойне, потому что: дважды содержит месяц и часы заданы в 12-часовом формате без указания а.ш./р.ш. В связи с неотвратимым приближением 2000-го года может возникнуть масса проблем, связанных с датами. Уже появляются рассказы о том, как из-за серьезности ожидаемых последствий переписываются целые системы. Для минимизации этих проблем в последующие годы будут использоваться Все возможные защитные методы кодирования и проверки. (Подробнее этот вопрос рассматривается в приложении Б.) Обработка дат более подробно освещается в главе 7. Строковые данные Большинство символьных, или строковых, данных хранится в Oracle в столбцах типа CHAR или VARCHAR2. Между этими типами есть существенное различие: данные типа CHAR иугеют фиксированную длину и могут содержать максимум 255 символов, тогда как данные типа VARCHAR2 имеют действительно переменную длину и могут содержать максимум 2000 символов. Если текстовые данные не имеют действительно фиксированного размера (например, не являются односимвольным значением флага), рекомендуем использовать VARCHAR2, так как это гораздо безопаснее. Однако что делать, если столбец может содержать свыше 2000 символов? Б этом случае можно воспользоваться одним из приведенных ниже методов: присвоить столбцу тип LONG (ниже мы укажем, с какими оговорками следует использовать этот тип); разбить данные на несколько столбцов (это делать не рекомендуется!); поместить их в справочную таблицу (при этом их размер практически неограничен, так как они могут занимать много строк). В большинстве ситуаций наиболее предпоггителен последний вариант. Для Oracle? он является основным, если мы хотим ссылаться на эти данные в предикатных предложениях, т.е. в предложениях WHERE и HAVING. Семантика сравнения строк Семантика сравнения SQL имеет несколько ловушек. Например, проблемы могут возникнуть при сравнении усеченных значений дат со значениями дат, которые содержат и время, а также при сравнении чисел с разной степенью точности. Кроме того, проблемы могут появиться и при сравнении символьных строк разной длины. Необходимо помнить также о том, что в SQL все строковые литералы считаются (совершенно обоснованно) имеющими фиксированную длину (т.е. имеют тип данных CHAR). Со строками одинаковой длины проблем нет. Они просто сопоставляются символ за символом. Если же две строки имеют разную длину и какая-то из них является строкой фиксированной длины, то более короткая строка набивается пробелами до длины второй строки. Так, если у нас два столбца типа VARCHAR2, А и В, которые содержат значения аЬ и аЬ, , то SQL сообщит, что А не равен В. Если же сравнить аЬ и аЬ буквально, как литералы, то SQL скажет, что они равны. К сожалению, ваше мнение по этому поводу не имеет никакого значения, потому что так построен алгоритм сравнения. Единственная разумная мера - сделать так, чтобы приложение не вставляло в столбцы типа VARCHAR незначащие конечные пробелы. (Средства Oracle, кроме SQL*Plus, обычно автоматически удаляют их независимо от того, значащие они или нет.)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |