Первичные ключи Oracle: NUMBER против NUMBER (7,0) - PullRequest
7 голосов
/ 05 августа 2009

Есть ли какая-то польза от указания точности на ПК? Достаточно ли 7,0, учитывая, что, вероятно, никогда не будет более нескольких тысяч записей?

Есть ли опасность не указывать точность?

Ответы [ 3 ]

10 голосов
/ 05 августа 2009

NUMBER(7, 0) просто ограничивает область значений.

Их внутренние представления не отличаются:

CREATE TABLE t_pk (col1 NUMBER(7, 0) NOT NULL, col2 NUMBER(38) NOT NULL)

INSERT
INTO    t_pk
VALUES  (9999999, 9999999)

SELECT  DUMP(col1), DUMP(col2)
FROM    t_pk

DUMP(col1)                        DUMP(col2)
---                               ---
Typ=2 Len=5: 196,10,100,100,100   Typ=2 Len=5: 196,10,100,100,100

В Oracle NUMBER s сохраняются как сотенные цифры числового значения, нормализованного до 0.01 <= N < 1 и с добавлением показателя степени.

В приведенном выше примере:

  • 196 является показателем 192 (4).
  • 10 является десятичным 9
  • 100 десятичные 99

Целое число читается в десятичном виде как 00.09 99 99 99 * (100 ^ 4) = 9,999,999

Чем больше цифр требуется для удовлетворения запрошенной точности, тем больше их будет сохранено, конечно.

Когда вы вставляете точное значение в менее точный столбец, оно просто округляется до точности столбца и сохраняется округленным.

Следовательно, с точки зрения производительности безопасно объявить столбец NUMBER(38), поскольку он не подразумевает накладных расходов на NUMBER(7, 0) (для чисел, соответствующих обоим типам).

Однако, если ваши PRIMARY KEY s являются целочисленными по природе, вам лучше указать точность как 0, чтобы убедиться, что никакое дробное значение не попадет в вашу таблицу.

Обновление:

@ Mac также указал, что клиенты могут полагаться на тип данных столбца для определения домена значений.

Если ваше приложение ожидает INT32, вы должны сделать свой номер NUMBER(9) или ниже (или любой тип, который ваш клиент считает конвертируемым в Int32).

4 голосов
/ 07 августа 2009

Что касается проблемы с базой данных, мне нечего добавить к ответу Кассной .

Но стоит отметить, что это может также оказать влияние на приложения, которые обращаются к базе данных (или, если быть более точным, на разработчиков этих приложений). Например, в .NET, если вы получите IDataRecord , включающий ваш первичный ключ (с использованием ODP .NET), вызов GetInt32 с треском провалится, когда ваш столбец определен как NUMBER (38 ) и завершается успешно, если определено как NUMBER (7) (даже когда значение находится в правильном диапазоне).

2 голосов
/ 06 августа 2009

Если вы не ожидаете больше, чем, скажем, 100K записей в таблице, если вы укажете PK с N (7,0), вы получите раннее предупреждение, если какой-нибудь сбегающий процесс закончится переполнением PK. Если вы указали его с помощью N (38), предупреждение не появится так рано, возможно.

Я бы всегда ошибался при ограничении размеров до наименьшего ожидаемого для «срока службы продукта» с разумным запасом погрешности.

...