Привет, я ищу общие ошибки, которые программисты pl/sql делают, когда они программируют приложения, которые имеют дело с большими денежными расчетами. (Скидки, налог, ставки и т.д.) Я использовал java и hibernate для денежных вычислений, насколько я помню, java имеет набор правил и лучших практик, таких как BigDecimal, чтобы сохранить точность и т.д. Сейчас я пытаюсь улучшить свои навыки pl/sql при работе с финансовыми модулями вот почему я хочу знать эту ошибку и избегать их. Также есть ли какая-либо существующая мантра или передовая практика pl/sql для этого? Спасибо заранее, ребята.
Каковы распространенные ошибки, которые программисты pl/sql делают с вычислением денег?
Ответ 1
Используя этот пример:
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 используйте переменные bind, привязанные к типу (включая длину/масштаб/точность) базовой таблицы.
Ответ 2
Вот 2 быстрых подсказки:
Практический совет Oracle: используйте NUMBER (без scale/prec) как в виде столбца таблицы, так и в PL/SQL.. экономит вам много головных болей. NUMBER (x, y) не сохраняет вам никаких циклов хранения или процессора.
Общий намек (сначала вы хотите иметь большую картинку):
-
Во-первых, изучите, каковы ваши конкретные требования к приложениям относительно десятичной арифметики: действительно ли вы делаете налог? если да, то США или ЕС? правила округления различаются в зависимости от юрисдикции и/или применения. Поддерживает ли 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
Ответ 3
Проблема с использованием типов денежных средств на любом языке:
- Усечение. Когда вы должны округлить, но результат будет усечен.
- Округление. Когда вы должны усечь, но он округлен.
Если вы внимательно относитесь к этим на каждом шагу, обработка ДЕНЕГ не является такой трудной задачей.