Какие распространенные ошибки программисты pl / sql делают с вычислением денег? - PullRequest
11 голосов
/ 26 августа 2011

Привет! Я ищу распространенные ошибки, которые допускают программисты pl / sql, когда они программируют приложения, которые занимаются множеством денежных вычислений. (Скидки, налоги, ставки и т. Д.) Я использовал java и hibernate для денежных расчетов, насколько я помню, в java есть набор правил и лучших практик, таких как BigDecimal, для сохранения точности и т. Д. Сейчас я пытаюсь улучшить свои навыки pl / sql в работе с финансовыми модулями. Вот почему я хочу знать об этих ошибках и избегать их. Кроме того, есть ли существующая мантра или pl / sql передовой опыт для этого? Заранее спасибо, ребята.

Ответы [ 3 ]

6 голосов
/ 29 августа 2011

Вот 2 быстрых подсказки:

Практический совет Oracle: используйте NUMBER (без масштаба / предварительного) как в качестве типа столбца таблицы, так и в PL / SQL. Это избавит вас от многих головных болей.NUMBER (x, y) не экономит циклы хранения или ресурсов процессора.

Общая подсказка (сначала нужно получить большую картинку):

  • First, исследуйте, каковы ваши конкретные требования к приложениям относительно десятичной арифметики: вы платите налог?если да, то США или ЕС?правила округления различаются в зависимости от юрисдикции и / или применения.Поддерживает ли Oracle SQL желаемый материал?Есть ли PL / SQL?Если нет, то ошибка заключается в том, чтобы в любом случае использовать PL / SQL.

  • Предстоящий золотой стандарт для десятичной арифметики - IEEE decimal128.Возможно, вы захотите прочитать в Википедии и, возможно, http://www.carus -hannover.de / doc / DFP_PW6_in_SAP_NetWeaver_0907.pdf в качестве примера.Он поддерживает все виды округления и т. Д. Не знаю, когда речь заходит об Oracle QL / PL / SQL

6 голосов
/ 27 августа 2011

Используя этот пример:

create table t_val
  (id number(10,0),
  value number(5,2));

declare
  v_dummy number;
begin
  delete from t_val;
  for i in 9 .. 20 loop
    insert into t_val values (i, 1/i);
    select count(*)
    into v_dummy 
    from t_val 
    where value = 1/i;
    dbms_output.put_line(to_char(i,'00')||':'||v_dummy||':'||
              to_char(1/i,'000.999999'));  
  end loop;
  --
end;
/

select id, value from t_val order by 1;

Вы можете видеть, что код вставляет, например, 0,11111, который неявно округляется до 0,11 Когда код сразу пытается подсчитать значения для 0,11111, он не находит совпадений.

Аналогичным образом значения для (1/14) и (1/15) округляются до 0,07.

Это не проблема, специфичная для PL / SQL, и я видел похожие проблемы в коде Java и PHP, когда значение в «клиенте» округляется, когда оно попадает в базу данных. PL / SQL предлагает лучшее решение, так как вы можете объявить переменную типа определенной таблицы / столбца, и эта привязка сохраняется, даже если столбец изменяется.

declare
  v_value  t_val.value%type;
  v_dummy number;
begin
  delete from t_val;
  for i in 9 .. 20 loop
    v_value := 1/i;
    insert into t_val values (i, v_value);
    select count(*)
    into v_dummy 
    from t_val 
    where value = v_value;
    dbms_output.put_line(to_char(i,'00')||':'||v_dummy||':'||
            to_char(1/i,'000.999999')||':'||to_char(v_value,'000.999999'));  
  end loop;
  --
end;
/

Таким образом, при работе с оператором SQL рекомендуется использовать переменные связывания, привязанные к типу (включая длину / масштаб / точность) базовой таблицы.

5 голосов
/ 03 сентября 2011

Проблема с типами MONEY на любом языке:

  • Усечение - Когда вы должны были округлить, но вместо этого результат был усечен.
  • Округление - Когда вы должны были усечь, но он округлился.

Если вы внимательно относитесь к ним на каждом этапе, обработка MONEY не такая уж сложная работа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...