Ошибка SQL: переполнение BCD вызвано слишком большим объединением - PullRequest
1 голос
/ 25 сентября 2019

По какой-то причине исключение пустых значений из полей при использовании слишком большого количества объединенных результатов приводит к ошибкам переполнения BCD

Я устранил ошибку до 1 строки в выбранной части.

  • Если любая (из 4) коалесценция заменена на фиксированное значение, все в порядке
  • Если какая-либо коалесценция удалена, результат также в порядке
  • Если для какого-либо поля используется другое, ошибка остается

Замена '/' на '-' также дает результат, но не правильное значение.

Все поля являются числовыми (10,4).
Это версия Firebird2.5.8

select 
coalesce(Field1, 0) * coalesce(Field2, 0) * ((100 - coalesce(Field3, 0)) / 100) * ((100 + coalesce(Field4, 0)) / 100)
from Table

Ожидается вычисленный столбец, фактический результат - переполнение BCD

1 Ответ

1 голос
/ 25 сентября 2019

Не совсем ответ, просто тест.

Firebird 2.1.7, IBExpert, SQL Dialect 3

create table t58096187 (
 f1 numeric(10,4),
 f2 numeric(10,4),
 f3 numeric(10,4),
 f4 numeric(10,4)
);

insert into t58096187 values ( 50, 50, 50, 50 );

select
 coalesce(F1, 0) * coalesce(F2, 0) * ((100 - coalesce(F3, 0)) / 100) * ((100 + coalesce(F4, 0)) / 100)
from t58096187;

ОШИБКА: неудачное выполнение ... целочисленное переполнение ... причинастарший значащий бит результата для переноса


• Базы данных Dialect 3 позволяют сохранять числа (типы данных DECIMAL и NUMERIC) как INT64, если точность больше 9


Та же ошибка с Numeric(9,4), которую следует избегать, если int64 внутренний тип данных.

Если я объявлю поля как float, то select даст результат 1875, который находится в пределах Numeric(10,4) типа данных.

Может быть, какой-то промежуточный результат в обратном полировке выходит за пределы?


Это также работает, если во избежание использования INT64 используется

recreate table t58096187 (
 f1 numeric(6,2),
 f2 numeric(6,2),
 f3 numeric(6,2),
 f4 numeric(6,2)
)

Кажется, что Firebird 3.0.5 также затронут - https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=57729b31e0a5019aea68a136638d9f50

Нет ошибки - но результатов тоже нет!

Числовой-как-Int32 работает: https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=c4a4230e855b0ce4fd2b0c7b3b697cda

Сообщается как https://www.sql.ru/forum/1317439-a/


Предположение Марка о точности дробной части как причина, по которой это возможно, является правильным.

recreate table t58096187 (
 f1 numeric(10,4),
 f2 numeric(10,4),
 f3 numeric(10,4),
 f4 numeric(10,3)
)

Все еще работает.

https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=29a6c15d6e1854be230d29aea30307cf


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

select
 F1 * F2 * F3 * F4
from t58096187

И, вероятно, та же самая ошибка

https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=1f29aff4102ace57e8fa27d83e59b93f

...