|


Реалізація ключових полів у форматі int64 у базі даних Interbase (Firebird)
Автор: Рудюк С.О.
Internet: rudjuk.kiev.ua
Поля у форматі Integer можуть приймати значення від -2147483648 до 2147483647. Для більшості систем цього цілком достатньо.
Проблеми починаються, коли необхідно розділити індексний простір між розподіленими базами даних.
Розглянемо, наприклад, бухгалтерську систему, що працює на великих підприємствах, в яких є кілька сладів та офісів. У центральному офісі збирається інформація з усіх точок та об'єднується у загальну велику базу даних. Для того щоб дані на різних точках не конфліктували один з одним необхідно розділити індексний простір. Наприклад, якщо у нас 20 таких точок, то можна виділити кожному підрозділу діапазони по 100 млн. варіантів. Цього до певного часу, до часу вистачить. За невеликого руху даних цього вистачить на кілька років. Через 5-10 років все ж таки доведеться вирішувати цю проблему. Набагато вигідніше це передбачити при первісному проектуванні програми, щоб потім не було "проблеми 2000".
Інший приклад додатку, де потрібні великі індексні поля – це різні системи тарифікацій (тарифікації інтернет, АТС). У таких системах щосекунди можуть додаватися десятки записів.
Крім того, при веденні логів змін у базі даних у таблиці логування також рекомендується створювати індекси більші, ніж Integer.
Int 64 в Interbase (Firebird)
В Interbase 6 для 64-х розрядного цілого введено тип BigInt. Для того щоб Ви могли створювати поля з типом даних BigInt необхідно вказати у базі даних, що застосовується 3-й діалект бази даних.
Число формату BigInt може приймати 10-18 ступеня варіантів. Int 64 та dbExpress
На жаль, у dbExpress тип Int 64 сприймається як TFMTBCDField, це приносить низку незручностей у роботі:
1) Не можливо просто виконати арифметичну операцію, а потрібно це робити через процедуру або привести до типу Int64, а потім виконати арифметичну операцію.
2) Хоч начебто за документацією тип BCD може мати 64 розряди, проте, як не дивно не сприймаються коректно числа, більші, ніж 10 у 15-му ступені. Натомість видається помилка про переповнення типу BCD.
3) Щоразу доводиться робити перетворення типів з BCD-типу Int64 і назад.
4) Іноді виникають дивні помилки про переповнення типу BCD. Це відбувається, коли у всіх розрядах типу BCD внесено 0.
5) Чомусь компонент SQLStoredProcedure погано працює з такими числами. Тому його доводиться замінювати звичайним запитом виклику процедури SQLQuery. Таких проблем у компонентах прямого доступу до Interbase немає!
Функції для перетворення BCD на Int64 і назад
Напишемо функцію для перетворення BCD на Int64.
function BcdToInt64(const Bcd: TBcd; Truncate: Boolean = False): Int64;
var
ABcd: TBcd;
begin
if (Truncate) and (BcdScale(Bcd) > 0 ) then
NormalizeBcd(Bcd,ABcd,Bcd.Precision,0)
else
ABcd := Bcd;
if BcdCompare(ABcd,Int64ToBcd(0))=0
then Result := 0
else Result := StrToInt64(BcdToStr(ABcd));
end;
|
Напишемо функцію перетворення з Int64 в BCD.
function Int64ToBcd(const AValue: Int64): TBcd;
begin
Result := StrToBcd(IntToStr(AValue));
end;
|
Так як іноді виникає помилка переповнення, коли всі розряди BCD-типу знаходяться в нулях, необхідно передати значення через функцію, що нормалізує це число:
function NormBcd(const AValue: TBcd): TBcd;
begin
if BcdCompare(AValue,Int64ToBcd(0))=0
then Result := Int64ToBcd(0)
else Result := AValue;
end;
|
Передача параметрів у dbExpress
Якщо ми встановлюємо параметр у компоненті SimpleDataSet, необхідно число з формату Int64 перетворювати на TFMTBCD.
With iqGetSecurName Do
Begin
Close;
Params.ParamByName('securid').AsFMTBCD
:=NormBcd(Int64ToBcd(VarInt64));
Open;
|
Для виконання арифметичних операцій необхідно число призвести до Int64.
VarInt64:=BcdToInt64(iqGetTypeDocTYPEDOCID.Value); |
Коли параметр встановлюється значенням поля типу TFMTBCD необхідно надходити так:
Params.ParamByName('SKLADID').AsFMTBCD
:=NormBcd(itSkladsSKLADID.Value);
|

|