Конференция "Базы" » Объясните тонконсти хранения чисел [IB6.x]
 
  • Zemen (21.11.08 17:08) [0]
    Имеем СУБД Firebird 1.5. Вопрос касается в данном случае только этой системы.

    Создаю таблицу:
    CREATE TABLE CAR(SP SPEED NUMERIC(15,2));

    Что значит 15 (разрядность) и точность (2). В книжке написано, разрядность общее число цифр в числе, а точность - число знаков после запятой. Точность задает формат отображения либо хранения чисел ?
  • Zemen (21.11.08 17:13) [1]
    Вопрос возник по следующей причине. Есть таблица А, числовые колонки которой имеют тип NUMERIC(15,2). В результате расчетов в числовые колонки заносятся числовые значения, у которых количество знаков после запятой больше 2-х. При этом такое в базе они все эти знаки сохраняются!
  • Правильный$Вася (21.11.08 17:36) [2]
    из справки по IB6
    NUMERIC datatype
    NUMERIC(x,y)
    In the syntax above, InterBase stores exactly x digits. Of that number, exactly y digits are to the right of the decimal point. For example,
    NUMERIC(5,2)
    declares that a column of this type always holds numbers with exactly 5 digits, with exactly two digits to the right of the decimal point: ppp.ss

  • Правильный$Вася (21.11.08 17:40) [3]
    The following table summarizes how InterBase stores NUMERIC and
    DECIMAL datatypes based on precision and scale:
    Datatype specified as… Datatype stored as…
    NUMERIC     INTEGER
    NUMERIC(4) SMALLINT
    NUMERIC(9) INTEGER
    NUMERIC(10) • DOUBLE PRECISION in dialect1
                      • INT64 in dialect 3
    NUMERIC(4,2) SMALLINT
    NUMERIC(9,3) INTEGER
    NUMERIC(10,4) • DOUBLE PRECISION in dialect1
                        • INT64 in dialect 3

  • Anatoly Podgoretsky © (21.11.08 19:04) [4]
    > Zemen  (21.11.2008 17:08:00)  [0]

    Есть два подхода к этому, когда точность (более правильно) это разрядность, а число знаков после запятой иногда почему то называется размер. Много путаницы внесли старые СУБД, типа dBase и FoxPro. Когда 15 означало не точность или число знаков, а число байт для хранения, а точность там называлось количесто знаков после запятой ( с точностью до Х знаков после запятой - наверно слышал такую фразу). Вот подобная запись означала в общем случае 13 знаков (из них две после запятой) + запятая + знак числа. В современных 15 это точность (precision - в твоей терминологии разрядность?) и 2 количество знаков после запятой, формат чисел BCD (не относится к обработке).
  • Anatoly Podgoretsky © (21.11.08 19:05) [5]
    > Zemen  (21.11.2008 17:13:01)  [1]

    Для Numeric - тогда это ошибка данной СУБД
  • Anatoly Podgoretsky © (21.11.08 19:06) [6]
    > Правильный$Вася  (21.11.2008 17:36:02)  [2]

    С ИБ надо быть поосторожнее, поскольку это зависит от уровня, на первом уровне это Float, на третьем BCD
  • Anatoly Podgoretsky © (21.11.08 19:09) [7]
    > Правильный$Вася  (21.11.2008 17:40:03)  [3]

    Вот они эти особенности IB тот вообще 4 внутренних формата для NUMERIC.
  • Johnmen © (21.11.08 19:26) [8]

    > Anatoly Podgoretsky ©   (21.11.08 19:09) [7]

    NUMERIC в ИБ это вообще не формат.
  • Anatoly Podgoretsky © (21.11.08 20:40) [9]
    > Johnmen  (21.11.2008 19:26:08)  [8]

    Я могу и поправиться - это тип
  • Johnmen © (21.11.08 21:07) [10]

    > Anatoly Podgoretsky ©   (21.11.08 20:40) [9]

    Псевдотип, если точнее...
    :)
  • Anatoly Podgoretsky © (21.11.08 23:45) [11]
    > Johnmen  (21.11.2008 21:07:10)  [10]

    Ну не буду спорить, но что бардак, так точно.
  • Loginov Dmitry © (22.11.08 00:10) [12]
    > Есть таблица А, числовые колонки которой имеют тип NUMERIC(15,
    > 2). В результате расчетов в числовые колонки заносятся числовые
    > значения, у которых количество знаков после запятой больше
    > 2-х. При этом такое в базе они все эти знаки сохраняются!


    Нет, в базе сохраняются именно 2 знака запятой. Более того, все число физически хранится в целочисленном формате (для 3-го (актуального сейчас) диалекта - см [3]). "Благодаря" этому, не так-то просто увеличить число знаков после запятой в процессе эксплуатации, так что если есть сомнения, лучше заранее брать с запасом ))
  • Zemen (24.11.08 12:51) [13]
    Проше прощения за отсутствие, коллеги, был в отъезде.

    Обсуждения ушли в сторону. То, что по разному хранит, это одно. Но такое поведение вообще нормально ? Причем обнаружил такую вещь. При с нуля таблицы по схеме: CREATE TABLE, INSERT, UPDATE такая ситуация не наблюдается. Если делаю UPDATE SET FFF = 0.12344124, то потом вижу значение FFF = 0.12. Получается, что все-таки СУБД округлила при обновлении под тип поля. Но в тоже самое время есть старая таблица с точно таким же типом поля. Попытка выполнить такой же запрос обновления, и в таблице сидят неокругленные значения с 8 знаками после запятой!
  • Правильный$Вася (24.11.08 12:57) [14]
    ты так и не уточнил диалект
    а это важно
  • Zemen (24.11.08 12:59) [15]
    Диалект изначально третий, но перевод БД на третий диалект ситуацию не изменил.
  • Zemen (24.11.08 13:00) [16]
    Сейчас попробую сделать демо-базу с двумя таблицами в качестве примера.
  • Виталий Панасенко (24.11.08 14:08) [17]

    > Zemen   (24.11.08 12:59) [15]
    >
    > Диалект изначально третий, но перевод БД на третий диалект
    > ситуацию не изменил.

    А в старой - 1-й...
  • Zemen (24.11.08 14:29) [18]
    Эврика! Диагноз поставлен, но адекватного решения похоже нет.

    Никакой демо-базы делать не нужно. Рассматриваем только разрядность от 10 чисел. В диалекте 1 тип Numeric(15,2) хранится как DOUBLE PRECISION. При обновлении никакого округления не возникает, значение 0.12345678 хранится как есть. Диалект 3 тот же самый тип хранится как INT64. Значение 0.12345678 при обновлении округляется до 0.12.

    Однако при переводе базы с первого диалекта на третий поведение не меняется. Это, конечно, удивило. Поля, созданные в первом диалекте, после перевода на третий ведут себя по старому, т.е. как DOUBLE PRECISION.  Смена типа через ALTER TYPE дает ошибку, т.к. СУБД не может конвертировать значения из DOUBLE PRECISION в INT64. Новые же поля ведут себя ожидаемо. Это - диагноз :).

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

    Не ошибся ли я в своих изыскания и есть ли другие пути решения ?
  • Правильный$Вася (24.11.08 15:23) [19]
    выгрузить в скрипт, залить его в правильную?
 
Конференция "Базы" » Объясните тонконсти хранения чисел [IB6.x]
Есть новые Нет новых   [134477   +39][b:0][p:0.001]