Yo utilizo IDs para cada registro de la tabla y luego otros campos para los números de orden, pedido, factura, etc.
El ID es un campo obtenido de un generador y el número del documento se calcula en los triggers.
Todo lo hecho en un trigger está dentro de una misma transacción, por lo que si no hay errores al insertar/modificar, la base de datos se ha encargado de que no haya duplicados.
Yo trabajo con Firebird. Esta base tiene generadores que devuelven el número siguiente del actual.
En los eventos BeforePost es donde obtengo un número para mi ID y se lo asigno al parámetro del dataset. Este ID es imposible que se duplique, por lo solo queda esperar a que el SQL se complete y refrescar los datos que sean necesarios (NRO_DOCUMENTO, TOTALES, etc.)
Código Delphi
[-]
function TDMMain.DameGenerador(NomGen: string): integer;
var
Q : THYFIBQuery;
begin
Result := 0;
if (Trim(NomGen) > '') then
begin
Q := THYFIBQuery.Create(nil);
try
with Q do
begin
Close;
DataBase := Self.DataBase;
SQL.Text := 'SELECT GEN_ID(' + NomGen + ',1) FROM RDB$DATABASE';
ExecQuery;
Result := Fields[0].AsInteger;
Close;
FreeHandle;
end;
finally
FreeAndNil(Q);
end;
end;
end;
procedure TDMFacturas.QMCabeceraBeforePost(DataSet: TDataSet);
var
existe : smallint;
begin
if (DataSet.State = dsInsert) then
DataSet.FieldByName('ID_CAB_FACTURA_CLI').AsInteger := DMMain.DameGenerador('GEN_CAB_FACTURA_CLI');
[...]
end;
El trigger sería algo así:
Código SQL
[-]
créate trigger CAB_FACTURA_CLI_BI0 for FACTURA before insert 0
as
begin
if ((new.ID_CAB_FACTURA_CLI = 0) or (new.ID_CAB_FACTURA_CLI is null)) then
newID_CAB_FACTURA_CLI := GEN_ID(GEN_CAB_FACTURA_CLI, 1);
select max(numero) from CAB_FACTURA_CLI
where
empresa = new.empresa and
ejercicio = new.ejercicio and
serie = new.serie
into new.numero;
if ((numero =0) or (new.numero is null)) then
new.numero = 1;
[...]
end