Опубликован: 28.12.2011 | Уровень: для всех | Доступ: свободно
Лекция 3:

Создание, удаление и изменение структуры таблиц

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >
Типы BINARY_FLOAT и BINARY_DOUBLE

Эти два типа представляют собой второй после NUMBER используемый в Oracle формат хранения чисел, определяемый стандартом IEEE 754 для 32- и 64- разрядного внутреннего представления. Стандарт IEEE 754 реализован аппаратно во многих видах процессоров и программно в ряде языков программирования (Java).

Стандарт IEEE 754 определяет больше, чем просто формат хранения чисел. Он, например, предусматривает особые значения "не число" (Not a Number) и +/? бесконечность. В Oracle точно воспроизведен формат хранения, но не все прочие подробности — стандарта IEEE 754. Возможность сослаться на особые "значения" дают следующие обозначения:

BINARY_FLOAT_NAN 
BINARY_FLOAT_INFINITY 
BINARY_DOUBLE_NAN 
BINARY_DOUBLE_INFINITY 

Например:

SQL> SELECT -BINARY_FLOAT_INFINITY FROM dual;
-BINARY_FLOAT_INFINITY
----------------------
                  -Inf

Из-за несовместимости форматов простая передача данных из вида NUMBER в BINARY_FLOAT/DOUBLE и обратно может приводить к потере точности. Зато при общении СУБД посредством этих двух форматов с внешними средами, работающими на основе стандарта IEEE 754, точность, наоборот, будет сохраняться.

Строки текста

"Обычные" строки ("короткие" и в основной кодировке БД) хранятся в полях типов VARCHAR2 ( n ) и CHAR ( n ) . n задает для VARCHAR2 максимально допустимое число хранимых символов (длиною до 4000 байт с версии 8 и до 2000 байт ранее), а для CHAR — всегда одно и то же, фиксированное (до 2000 байт).

"Короткие" строки в дополнительной (так называемой "национальной") кодировке БД, которая всегда многобайтовая, хранятся в полях типов NVARCHAR2 (n) и NCHAR (n).

Для многобайтовой кодировки длину можно указывать как в символах (CHAR n), так и в байтах (BYTE n): по умолчанию считается последнее. Хотя это делается и нечасто, но при создании БД основной кодировкой может быть объявлена многобайтовая, поэтому определения вида VARCHAR2 ( CHAR 5 ) или CHAR ( BYTE 10 ) также приемлемы.

Типы CLOB и NCLOB (character LOB, large object, и national character LOB) используются для хранения "больших" строк текста длиною до 4 Гб — 1 до версии 9 включительно и до нескольких Тб начиная с версии 10. Сами значения этих типов обычно хранятся отдельно от обычных данных таблицы и доступ к ним осуществляется посредством так называемых "локаторов", однако для программирования на SQL эти подробности часто могут быть незаметны.

Тип VARCHAR2 не определен стандартом SQL и отличается от типа VARCHAR тем, что полагает строку из нуля символов отсутствующей строкой. Тип CLOB воплощен в Oracle в соответствии со стандартом.

Типы STRING, CHARACTER VARYING, NATIONAL CHARACTER VARYING и другие, совместимые с ANSI/ISO, реализуются с помощью VARCHAR2 и NVARCHAR2 и в Oracle вторичны.

Строки байтов

Тип RAW ( n ) аналогичен VARCHAR2 ( n ) с разницей максимально разрешенной длины — вплоть до 2000 байтов.

Тип BLOB (binary LOB) аналогичен CLOB и по сути описывает файл (поток байтов), возможно, очень большой и размещаемый в БД (речь при этом не идет о воспроизведении в БД Oracle файловой системы). С версии 11 такое помещение файла в БД Oracle может сопровождаться сокращением объемов хранения и оказаться выгодным с точки зрения компактности.

Тип BFILE (binary file) аналогичен BLOB, но только сам поток байтов хранится вне БД, а именно в файле. Утилитарно можно полагать его типом ссылки на файл ОС, где работает СУБД, то есть "на сервере". Тип может показаться удобным, так как облегчает доступ к данным, достижимым из Oracle, со стороны посторонних программ; однако он имеет ту особенность, что сами данные, расположенные вне БД, не затрагиваются процедурами резервного копирования и восстановления, а также командами управления транзакциями. В БД хранится только ссылка на внешний файл.

LONG и LONG RAW — устаревшие типы, сохраняемые ради обратной совместимости. Например, они встречаются в некоторых системных таблицах, спроектированных в прежние времена.

Моменты и интервалы времени

Тип DATE в Oracle не совпадает с одноименным типом в стандарте SQL и рассчитан на хранение одновременно шести компонентов момента времени: года, месяца, числа, часа, минут и секунд. По сути, он имеет в Oracle собственную, нестандартную реализацию. Шестикомпонентность типа DATE доставляет неудобства, когда требуется сохранить в БД только дату или только время суток.

Типы TIMESTAMP стандартны. В основном варианте TIMESTAMP хранит те же шесть компонент, что и DATE, но с точностью до наносекунд. Максимально допускаемую точность можно намеренно ограничить, указав в скобках n от 0 до 9. В расширенных вариантах тип включает еще зону времени (часовой пояс).

Интервальные типы INTERVAL YEAR TO MONTH и INTERVAL DAY TO SECOND соответствуют стандарту и позволяют хранить "грубые" интервалы (исчисляемые годами и месяцами) и "точные" (исчисляемые днями, часами, минутами и секундами).

Общие свойства типов

У типов данных в Oracle имеются общие свойства:

  • у всех типов дополнительно ко множеству допустимых величин наличествует особый символ NULL;
  • большинство типов допускает сравнение на равенство.
Пропущенные значения и NULL

NULL можно воспринимать формально (и механически следовать правилам выполнения операций с NULL), но пытаться интерпретировать эти обозначения в столбце таблицы можно по-разному: как "значение отсутствует" (например, "сотрудник не получал комиссионных") и как "неизвестно какое" из допустимых "значение" (например, "сотрудник получил какие-то комиссионные, неизвестные БД"). К сожалению это не одно и то же, равно как и наделения NULL этими двумя смыслами в жизни недостаточно (хотя и хватает для описания 99% возникающих ситуаций). По этим причинам, хотя на первый взгляд возможность опустить значение в столбце за его отсутствием может и показаться привлекательной, последующая работа с такими данными способна принести программисту значительно больше неприятностей из-за необходимости учета при составлении запросов неформализованных в схеме сведений о данных, усложнения запросов и возникающих рисков ошибиться при программировании. Примеры подобных неприятностей обозначены в разных местах текста ниже.

Стандарт SQL допускает NULL, но оговаривает, что во имя надежности обращения к данным программисту следует всячески избегать пропусков значений в столбцах либо уж употреблять их лишь в смысле "значение неизвестно" (unknown). Стандарт называет NULL особым значением, общим для всех типов, и обрекает себя тем самым на критику со стороны специалистов, полагающих, что правильнее назвать NULL символом1 Смотри книгу Дейт К. Дж., Дарвен Х. Основы будущих систем баз данных. Третий манифест. Перевод с английского. Изд. 2, 2004. Примечательно, что один из критиков — автор этой книги, в свое время входил в состав одного из национальных комитетов ISO по стандартизации SQL; это красноречиво характеризует демократические институты, к числу которых относится ISO., так как он не удовлетворяет признакам значения. Действительно, если x "имеет значение" NULL, то x = x не истина, что довольно необычно. Это уже проблема не интерпретации, а принятых правил употребления.

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

Что касается реляционной теории, то первые 10 лет своего существования она не рассматривала пропущенных значений вовсе и не имела дела с NULL, после чего мнения специалистов разошлись: одни (в их числе Э. Кодд) посчитали возможным (хотя и нежелательным на деле) использование пропущенных значений, а другие настаивали на их недопущении. То есть разрешение значениям в базе отсутствовать, вместе с вытекающей из этого необходимостью громоздкого аппарата их учета, можно считать одним из предлагаемых расширений, притом спорным, реляционной модели.

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

Например, если требуется учесть возможность отсутствия комиссионных у работника, атрибут "комиссионные" можно исключить из отношения "сотрудники" и перенести в дополнительное отношение:


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

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

Сравнение значений на равенство

Сравнение значений на равенство — более безобидное и очевидное свойство типов в Oracle. Однако для некоторых встроенных "сложных" типов, не говоря уже об объектных, созданных программистом, оно не выполняется. Например, Oracle не позволяет сравнить в запросе SQL два значения типов LOB или XMLTYPE. В приводимом ниже доказательстве команда VARIABLE предназначена для определения в SQL*Plus переменной указанного типа и не имеет отношения к SQL:

VARIABLE x CLOB
VARIABLE y CLOB
SELECT 'ok' FROM dual WHERE :x = :y;
-- ошибка !

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

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >
Ярослав Прозоров
Ярослав Прозоров

В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS"  представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции.

Володимир Миколайчук
Володимир Миколайчук
Помогите разобраться поетапно с логикой запроса
-------TOOLS
NAME PRICE TYPE
drill 155 A
sawzall 192 N
mitre saw 292 M
router 86 I
RAD 145 M
jigsaw 128 I
screwdriver 77 P
------TOOL_TYPES
TYPE USAGE
A Always
I Often
M Sometimes
N Rarely
P Never

Запрос SQL:
SELECT t.type, SUM(t.price)
FROM tools t
GROUP BY t.type
HAVING SUM(t.price) >= (SELECT AVG(price)
FROM tools
WHERE type IN (SELECT type
FROM tool_types
WHERE usage = 'Often'));

И сколько строк он все таки вернет
Жанбек Сарсенов
Жанбек Сарсенов
Россия, Москва, Московский Государственный Университет имени Ломоносова М.В., 2002