![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Объясните тонконсти хранения чисел [IB6.x]
Zemen © (2008-11-21 17:08:00)Имеем СУБД Firebird 1.5. Вопрос касается в данном случае только этой системы.
Создаю таблицу:
CREATE TABLE CAR(SP SPEED NUMERIC(15,2));
Что значит 15 (разрядность) и точность (2). В книжке написано, разрядность общее число цифр в числе, а точность - число знаков после запятой. Точность задает формат отображения либо хранения чисел ?
Johnmen (2008-11-24 20:54:00) [1]
> Обсуждения ушли в сторону.
Чего тут обсуждать-то? Документацию лень открыть?
Правильный$Вася (2008-11-24 18:21:00) [2]"никогда не хватает времени, чтобы что-то сделать правильно
зато чтобы переделать, причем N раз, время находится"
вольный перефраз из законов Мерфи
Zemen (2008-11-24 17:25:00) [3]
> выгрузить в скрипт, залить его в правильную?
Сейчас это фантастика. Дешевле будет заплатки лепить :)
Правильный$Вася (2008-11-24 15:23:00) [4]выгрузить в скрипт, залить его в правильную?
Zemen (2008-11-24 14:29:00) [5]Эврика! Диагноз поставлен, но адекватного решения похоже нет.
Никакой демо-базы делать не нужно. Рассматриваем только разрядность от 10 чисел. В диалекте 1 тип Numeric(15,2) хранится как DOUBLE PRECISION. При обновлении никакого округления не возникает, значение 0.12345678 хранится как есть. Диалект 3 тот же самый тип хранится как INT64. Значение 0.12345678 при обновлении округляется до 0.12.
Однако при переводе базы с первого диалекта на третий поведение не меняется. Это, конечно, удивило. Поля, созданные в первом диалекте, после перевода на третий ведут себя по старому, т.е. как DOUBLE PRECISION. Смена типа через ALTER TYPE дает ошибку, т.к. СУБД не может конвертировать значения из DOUBLE PRECISION в INT64. Новые же поля ведут себя ожидаемо. Это - диагноз :).
Теперь решение. Переход на третий диалект без полной перетряски базы не поможет. По сути надо писать отдельную программу, которая для каждого числового поля будет переписывать данные. В настоящее время это исключено. Тогда придется, учитывая данную особенность, вносить изменения в программый код, т.е. плодить заплатки или боротся со следствием, а не причиной, что требует гораздо больше времени и сил. Такие, вот, пироги.
Не ошибся ли я в своих изыскания и есть ли другие пути решения ?
Виталий Панасенко (2008-11-24 14:08:00) [6]
> Zemen (24.11.08 12:59) [15]
>
> Диалект изначально третий, но перевод БД на третий диалект
> ситуацию не изменил.
А в старой - 1-й...
Zemen (2008-11-24 13:00:00) [7]Сейчас попробую сделать демо-базу с двумя таблицами в качестве примера.
Zemen (2008-11-24 12:59:00) [8]Диалект изначально третий, но перевод БД на третий диалект ситуацию не изменил.
Правильный$Вася (2008-11-24 12:57:00) [9]ты так и не уточнил диалект
а это важно
Zemen (2008-11-24 12:51:00) [10]Проше прощения за отсутствие, коллеги, был в отъезде.
Обсуждения ушли в сторону. То, что по разному хранит, это одно. Но такое поведение вообще нормально ? Причем обнаружил такую вещь. При с нуля таблицы по схеме: CREATE TABLE, INSERT, UPDATE такая ситуация не наблюдается. Если делаю UPDATE SET FFF = 0.12344124, то потом вижу значение FFF = 0.12. Получается, что все-таки СУБД округлила при обновлении под тип поля. Но в тоже самое время есть старая таблица с точно таким же типом поля. Попытка выполнить такой же запрос обновления, и в таблице сидят неокругленные значения с 8 знаками после запятой!
Loginov Dmitry (2008-11-22 00:10:00) [11]> Есть таблица А, числовые колонки которой имеют тип NUMERIC(15,
> 2). В результате расчетов в числовые колонки заносятся числовые
> значения, у которых количество знаков после запятой больше
> 2-х. При этом такое в базе они все эти знаки сохраняются!
Нет, в базе сохраняются именно 2 знака запятой. Более того, все число физически хранится в целочисленном формате (для 3-го (актуального сейчас) диалекта - см [3]). "Благодаря" этому, не так-то просто увеличить число знаков после запятой в процессе эксплуатации, так что если есть сомнения, лучше заранее брать с запасом ))
Anatoly Podgoretsky (2008-11-21 23:45:00) [12]> Johnmen (21.11.2008 21:07:10) [10]
Ну не буду спорить, но что бардак, так точно.
Johnmen (2008-11-21 21:07:00) [13]
> Anatoly Podgoretsky © (21.11.08 20:40) [9]
Псевдотип, если точнее...
:)
Anatoly Podgoretsky (2008-11-21 20:40:00) [14]> Johnmen (21.11.2008 19:26:08) [8]
Я могу и поправиться - это тип
Johnmen (2008-11-21 19:26:00) [15]
> Anatoly Podgoretsky © (21.11.08 19:09) [7]
NUMERIC в ИБ это вообще не формат.
Anatoly Podgoretsky (2008-11-21 19:09:00) [16]> Правильный$Вася (21.11.2008 17:40:03) [3]
Вот они эти особенности IB тот вообще 4 внутренних формата для NUMERIC.
Anatoly Podgoretsky (2008-11-21 19:06:00) [17]> Правильный$Вася (21.11.2008 17:36:02) [2]
С ИБ надо быть поосторожнее, поскольку это зависит от уровня, на первом уровне это Float, на третьем BCD
Anatoly Podgoretsky (2008-11-21 19:05:00) [18]> Zemen (21.11.2008 17:13:01) [1]
Для Numeric - тогда это ошибка данной СУБД
Anatoly Podgoretsky (2008-11-21 19:04:00) [19]> Zemen (21.11.2008 17:08:00) [0]
Есть два подхода к этому, когда точность (более правильно) это разрядность, а число знаков после запятой иногда почему то называется размер. Много путаницы внесли старые СУБД, типа dBase и FoxPro. Когда 15 означало не точность или число знаков, а число байт для хранения, а точность там называлось количесто знаков после запятой ( с точностью до Х знаков после запятой - наверно слышал такую фразу). Вот подобная запись означала в общем случае 13 знаков (из них две после запятой) + запятая + знак числа. В современных 15 это точность (precision - в твоей терминологии разрядность?) и 2 количество знаков после запятой, формат чисел BCD (не относится к обработке).
Правильный$Вася (2008-11-21 17:40:00) [20]
The following table summarizes how InterBase storesNUMERIC 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