Subject Re: [firebird-support] Autoincremented Fields in Delphi
Author Helen Borrie
At 10:27 PM 15/07/2005 +0000, you wrote:
>Hi everybody:
>
>I'm trying to use an autoincrement field in a table, the field is part
>of the primary key. First I used a trigger calling a generator, but
>when insert a new record in my Delphi application i discover is
>neccesary to write any value in the field BEFORE the post operation,
>otherwise an error occurs. Then I read best way to do that is thru a
>StoredProcedure, well, I cant't find where call that procedure. Any
>sugestion?

Retain the trigger, because it will ensure that you get a unique new value, regardless of the client program that performs an insert. But write the trigger this way:

create trigger bi_mynames for mynames
active before insert position 0
as
begin
if (new.MyCoe is null) then
new.MyCode = gen_id(MoreCodes, 1);
end

In your Delphi application, as you observe, a primary key is set up to be a Required field. The most painless strategy in Delphi is to fetch the new value into the application during the BeforeInsert event (not to be confused with the "BEFORE INSERT" phase of an Insert operation on the server!!)

How you go about this depends on the data access components you are using. IB Objects encapsulates the grabbing of a generator value in its statement classes by way of the GeneratorLinks property. It also has its own inbuilt Gen_ID() function. I expect FIBPlus, and even poor old IBX provide something equivalent.

If you are using the VCL/BDE for your Delphi apps (NOT the wisest of ideas, natch!) then you will have to roll your own generator value fetching function, something like the following:

function MyDM.GetGeneratorValue(GeneratorName: string; IncValue: integer): Int64;
var
qr: TQuery;
begin
qr := TQuery.Create(self);
with qr do
try
DatabaseName := MyDatabase.DatabaseName;
SQL.Add('SELECT GEN_ID(' + GeneratorName + ', ' +IntToStr(IncValue) + ') ');
SQL.Add('FROM RDB$DATABASE');
Open;
Result := Fields[0].AsInt64;
finally
Close;
Free;
end;
end;

Call this function in BeforeInsert to pull the value into the field:
MyDataset.FieldByName('MyCode').AsInt64 := GetGeneratorValue('MoreCodes', 1);

Some points:

1. There are some FAQ entries on this subject on the Firebird website.
2. Although there are lots of Delphi users subscribed in firebird-support, each with his or her favourite data access suite, this list is NOT a Delphi support list. You'll need to get yourself into a list or newsgroup that supports the particular flavour of data access that you decide to use.

./hb