Mega Code Archive

 
Categories / Delphi / Ide Indy
 

How To Create An Auto Increment Key Using InterBase And Delphi

Title: How To Create An "Auto-Increment" Key Using InterBase And Delphi Question: Creating an autoincrementing key using InterBase requires a little more work than Paradox, and if not done properly can create errors when using the BDE. Answer: Problems can occur when inserting data into an InterBase table with an autoincrement key using the BDE: it "loses" the record because the value of the primary key field (which it is using to keep track of the record) changes at he server, the client has no knowledge of the value that is inserted into the primary key field. The solution (for an example table COUNTRY, that has a generated primary key field of COUNTRY_ID) is: ON THE SERVER: 1) create a generator create generator g_country_id; 2) create the table create table country( COUNTRY_ID D_PRIMARY_KEY not null, COUNTRY_NAME D_DESCRIPTION, COUNTRY_ABRVN varchar(10), COUNTRY_CODE D_SHORT_DESCRIPTION); /* Primary Key */ alter table country add constraint PK_COUNTRY primary key (COUNTRY_ID); /* Triggers */ /* this trigger will not usually be used, as the value of the COUNTRY_ID will be defined at the client, using the stored procedure p_get_country_id It should be included anyway, for safety, standardization, etc. */ create trigger tbi_set_country_id for COUNTRY active before insert position 0 AS BEGIN IF (NEW.COUNTRY_ID IS NULL) THEN NEW.COUNTRY_ID = GEN_ID(G_COUNTRY_ID, 1); END 3) create a stored procedure that returns the generated key value: create procedure p_get_country_id returns (COUNTRY_ID integer) as BEGIN COUNTRY_ID = GEN_ID(G_COUNTRY_ID, 1); END IN THE CLIENT CODE: 4) At the client, when a new record is created, define the primary key value using a stored procedure (the following assumes you are using Delphi, which one would have to be mad not to... ): Assumes a TTable (this process works just as well with TQuery objects) object name tblCountry and a TStoredProc object named spGetCountryID, in a TDataModule named dmCommon: procedure TdmCommon.tblCountryNewRecord(DataSet: TDataSet); begin with spGetCountryID do begin ExecProc; DataSet.FieldByName('COUNTRY_ID').AsInteger := ParamByName('COUNTRY_ID').AsInteger; end; end; Some people prefer to put the code that calls the procedure and assigns the key in the BeforePost event: this is not wrong, just a matter of style. Also, you can save some time/effort at the client by writing a shared procedure that all of your datasets call directly on the OnNewRecord event. Since the dataset is passed, you can change the Stored Procedure to be called based on the dataset name. It might make your code a little cleaner or easier to maintain, see below: procedure TdmCommon.AllTablesGetKeyOnNewRecord(DataSet:TDataSet); var sFieldName : string; spGetKey : TStoredProc; begin with DataSet do begin if Name = 'tblCountry' then begin sFieldName := 'COUNTRY_ID'; spGetKey := spGetCountryID; end else if Name = 'wwtblLanguage' then begin sFieldName := 'Language_ID'; spGetKey := spGetLanguageID; end; end; with spGetKey do begin ExecProc; DataSet.FieldByName(sFieldName).AsInteger := ParamByName(sFieldName).AsInteger; end; end;