Je ne suis pas sûr de poster au bon endroit, mais j'ai fait une petite recherche dans la partie "SQL" de ce site et il ne m'a pas l'air d'y avoir grand chose...
Ma question :
J'ai une table (firebird) avec une clé primaire (NUM_ELEMENT, NUM_CLIENT). NUM_CLIENT est récupéré à partir d'une autre table. Je voudrais que le NUM_ELEMENT soit autoincrémenté, mais pour un client. C'est à dire, que si j'ai un client A et un client B, que j'ai les éléments 1, 2, 3 et 4 pour le A, et 1 et 2 pour le B, quand j'insère un nouvel enregistrement pour B, je voudrais qu'il prenne le n°3. Je sais coder ça en delphi, mais je me demandais s'il existait une façon de coder ça en trigger avec un générator ou un truc du genre. Pour le moment, je n'arrive pas à indiquer à mon générator qu'il faut que cette incrémentation soit conditionnée...
si j'ai bien compris, l'idée serait de créer un générator dynamiquement pour chaque nouveau client, puis de récupérer l'id quand c'est nécessaire.
J'utilise Zeos pour mes accès à Firebird. Il existe un objet TZSequence dans cette bibliothèque. J'ai fait un objet autour de TZSequence :
unit dbm_sequence;
interface
uses
ZConnection, ZSequence, Classes, dbm_connection;
type
TSerialGP = (gpsDocIn, gpsMemo, gpsDocCli, gpsWSer);
TDBM_sequence = class(TZSequence)
public
constructor Create(AOwner: TComponent; Connection: TDBM_connection); reintroduce; overload;
function SerialByName(s_gen: string): integer;
function Serial(gps_gen: TSerialGP): integer;
function Get(gps_gen: TSerialGP): integer;
end;
const
AS_GEN: array[TSerialGP] of string = (
'GEN_DIN' // document entrant
,'GEN_MEMO' // notes et mémos
,'GEN_DOCCLI' // documents clients traités
,'GEN_WSER' // sérial générique
);
implementation
uses
SysUtils;
{ TGPZSequence }
constructor TDBM_sequence.Create(AOwner: TComponent; Connection: TDBM_connection);
begin
inherited Create(AOwner);
Self.Connection := Connection.getConnection;
end;
function TDBM_sequence.Get(gps_gen: TSerialGP): integer;
begin
Result := Serial(gps_gen);
end;
function TDBM_sequence.Serial(gps_gen: TSerialGP): integer;
begin
SequenceName := UpperCase(AS_GEN[gps_gen]);
Result := GetNextValue;
Assert(Result > 0);
end;
function TDBM_sequence.SerialByName(s_gen: string): integer;
begin
SequenceName := UpperCase(s_gen);
Result := GetNextValue;
Assert(Result > 0);
end;
end.
Tu pourrais t'en inspirer selon la bibliothèque que tu utilises.
Il faudrait ajouter une méthode du genre :
procedure addGenerator(const codeClient: string);
qui créerait le generator du client.
Quand tu as besoin d'une valeur, tu crées une instance de TDBM_sequence et tu récupères la valeur par instance.SerialByName(codeClient)
Enfin, quelque chose comme cela, si cela peux t'aider.
Le code de TDBM_connection :
unit dbm_object;
interface
uses
ZConnection;
type
TDBM_object = class(TObject)
protected
connection: TZConnection;
public
constructor Create(connection: TZConnection); virtual;
destructor Destroy; override;
function getConnection: TZConnection;
end;
implementation
{ TDBM_object }
constructor TDBM_object.Create(connection: TZConnection);
begin
Self.connection := connection;
end;
destructor TDBM_object.Destroy;
begin
inherited;
end;
function TDBM_object.getConnection: TZConnection;
begin
Result := connection;
end;
end.
unit dbm_connection;
interface
uses
dbm_object, ZConnection;
type
TDBM_connection = class(TDBM_object)
private
_connection: TZConnection;
public
constructor Create(connection: TZConnection);
procedure startTransaction;
procedure commit;
procedure rollback;
function inTransaction: boolean;
function connected: boolean;
procedure connect;
procedure disconnect;
function getConnection: TZConnection;
end;
implementation
{ TDBM_connection }
procedure TDBM_connection.commit;
begin
if inTransaction then
getConnection.Commit;
end;
procedure TDBM_connection.connect;
begin
if not connected then
getConnection.Connect;
end;
function TDBM_connection.connected: boolean;
begin
Result := getConnection.Connected;
end;
constructor TDBM_connection.Create(connection: TZConnection);
begin
_connection := connection;
end;
procedure TDBM_connection.disconnect;
begin
if connected then
getConnection.Disconnect;
end;
function TDBM_connection.getConnection: TZConnection;
begin
Result := _connection;
end;
function TDBM_connection.inTransaction: boolean;
begin
Result := getConnection.InTransaction;
end;
procedure TDBM_connection.rollback;
begin
if inTransaction then
getConnection.Rollback;
end;
procedure TDBM_connection.startTransaction;
begin
if not inTransaction then
getConnection.StartTransaction;
end;
end.
Bonjour,
tu as une relation 1-N entre la table CLIENTS et
ENREGISTREMENTS ce qui se traduit dans ta base
par deux clés primaires, deux generators, deux triggers et une contrainte sur la foreign keys de ENREGISTREMENTS.
lors de l'insertion dans enregistrements, il suffit de caler le CLIENT et son code s'introduit automatiquement dans la table et le generator incrémente automatiquement la clé de ENREGISTREMENTS.