|


Реализация ключевых полей в формате 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);
|

|