[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Неявное преобразование типов в Постгре.
sergeiss
Наступил на грабли, часа 2 "прыгал", пока понял причину... Решил поделиться - вдруг кому поможет тоже? smile.gif

Вобщем, предыстория простая. Есть данные, которые готовятся где-то (это в данном случае не важно). На сервер они поступают в виде четко структурированного CSV файла, который грузится целиком по команде Постгре "copy ... from ....".
В процессе загрузки срабатывает триггер, в котором делаются дополнительные вычисления, записываемые в ту же запись в той же таблице.
Происходит это всё на автомате в ночное время, с утра нужно только убедиться, что всё прошло нормально.
И почти 2 года всё грузилось без проблем...

Но вот сегодня я получил такое сообщение об ошибке:
ERROR:  integer out of range
CONTEXT: PL/pgSQL function "count_integral_quality" line 54 at assignment
COPY block_3111_3112, line 322: "'2010-03-06', 2815, 30651, 7, 41, 1,d, 3, 23, 174, 8,0, 0, 0,0, 0, 0,0, 0, 0,1, 42, 4,0, 0, 0,1, 42,..."


Полез в функцию.
CREATE OR REPLACE FUNCTION count_integral_quality()
...
declare
...
val_top real;
....


val_top :=
new.tpr_rx_qual_lev_reports_1_2 * val_1 * 1 / 254. +
new.tpr_rx_qual_lev_reports_1_3 * val_1 * 2 / 254. +
new.tpr_rx_qual_lev_reports_1_4 * val_1 * 3 / 254. +
new.tpr_rx_qual_lev_reports_1_5 * val_1 * 4 / 254. +
....


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

Взял все исходные данные, просчитал проблемную строку в Экселе... Итоговое выражение получается 57 млн. То есть, для вещественного нормально. И только там, в Эксле заметил, что промежуточные результаты (отдельные слагаемые, точнее, произведения из числителя) реально превышают число, которое можно записать в 32 битное целое!!!
Опять же, хорошо, что я стал делать эту проверку пошагово, внимательно глядя на все промежуточные результаты.

Попробовал фиксированные коэффициенты в числителе сделать вещественными...
new.tpr_rx_qual_lev_reports_1_2 * val_1 * 1. / 254. +
new.tpr_rx_qual_lev_reports_1_3 * val_1 * 2. / 254. +
new.tpr_rx_qual_lev_reports_1_4 * val_1 * 3. / 254. +
new.tpr_rx_qual_lev_reports_1_5 * val_1 * 4. / 254. +
....

И заработало!!!

А я-то думал, что величина 254. (с точкой) влияет сразу же на то, чтобы результат был вещественный... Но у Постгре свои взгляды на это.

Вывод. Внимательнее надо быть с типами данных. И чем более четко указываешь, что ты хочешь, тем выше вероятность того, что всё будет работать исправно.

PS. Я тему зафиксирую сразу же. Убрать ее из топа всегда можно будет.



Спустя 43 минуты, 44 секунды (9.03.2010 - 12:09) glock18 написал(а):
четкость отнюдь не вариант в постгре. при размышлении на тему "какой бы индекс припаять", постгре смотрит на типы данных. разумеется, они должны соответствовать полностью. (unsigned int != signed int, int != smallint).

если поле в таблице типа smallint, а число подставляются в запрос - будет или не будет применен индекс, зависит от того с кавычками число поставлено или нет. без кавычек - индекс не будет применен, с ними - будет. в свете самой темы должно быть понятно почему именно так.

Спустя 10 месяцев, 14 дней, 11 часов, 38 минут, 55 секунд (23.01.2011 - 23:48) Dezigo написал(а):
при работе с файлами лучше в sql - тоже использовать exeption. А так зачёт.


_____________
* Хэлп по PHP
* Описалово по JavaScript
* Хэлп и СУБД для PostgreSQL

* Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги.

* "накапливаю умение телепатии" (С) и "гуглю за ваш счет" (С)

user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.