2 votes

Comment incrémenter automatiquement une colonne de la base de données iSeries lors d'une insertion via SQL à partir de plusieurs sites web ?

Question saugrenue. Je sais. Voici le scénario :

Mon client possède plusieurs sites web ColdFusion qui utilisent tous la même bibliothèque sur la même base de données iSeries. Supposons, pour les besoins de l'argumentation, que la requête SQL suivante puisse être exécutée à partir de n'importe lequel de ces sites Web :

<cfquery datasource="myDS">
    INSERT INTO XQX.myTable
       (
        x_ID,
        x_Name,
        x_Phone
       )
    VALUES
       (
        #myId#,
        #Name#,
        #Phone#
       )
</cfquery>

(Je sais qu'il n'y a pas de CFQUERYPARAMs, etc., supposons simplement pour des raisons de simplicité que la requête ci-dessus est A-Ok)

Je pourrais générer l'Id en interrogeant la table avant l'insertion pour obtenir la valeur maximale, puis en l'incrémentant, comme suit :

<cfquery name="qMaxId" datasource="myDS">
    SELECT MAX(x_Id) AS MaxId
    FROM XQX.myTable
</cfquery>

<cfset myId = qMaxId.MaxId + 1 />

Mais je crains que deux utilisateurs n'utilisent la table au même moment et n'obtiennent tous deux la même "nouvelle" Id.

Qu'en pensez-vous ?

3voto

Clockwork-Muse Points 6806

En particulier dans un contexte web, vous devrait s'inquiéter des utilisateurs simultanés. Il y a deux problèmes inhérents à la tentative de générer l'identifiant avec MAX() comme ceci :

  1. L'accès n'est pas "synchronisé" et deux utilisateurs se retrouvent avec le même identifiant.
  2. Vous do synchroniser" l'accès, et vous créez un goulot d'étranglement pour les insertions de tables.

DB2 (qui est standard sur un iSeries, en général) a quelque chose qui s'appelle un SEQUENCE que vous pouvez interroger pour générer vos identifiants.
Je ne connais rien à coldfusion, mais quelque chose comme ça :

<cfquery name="qNextId" datasource="myDS"> 
    SELECT NEXTVAL FOR [sequencename] AS NextId 
    FROM Sysibm.Sysdummy1
</cfquery> 

<cfset myId = qNextId.NextId />

3voto

Buck Calabro Points 7115

En plus de la SEQUENCE mentionnée par @X-Zero, l'administrateur IBM DB2 peut placer une colonne auto-incrémentée appelée IDENTITÉ dans la base de données.

create MYTABLE ...
(ID int 
    generated always as IDENTITY(Start with 1 
                                 Increment by 1)
...

3voto

WarrenT Points 3287

Vous pouvez utiliser un objet Séquence. Par exemple

CREATE SEQUENCE XQX.mySeqObj
    as {numeric-datatype}

Le type de données peut être SMALLINT, INTEGER, BIGINT, DECIMAL ou NUMERIC, avec une échelle de zéro (c'est-à-dire sans décimales). Une zone de données est créée pour stocker la valeur.

Vous pouvez alors utiliser un NEXT VALUE FOR pour récupérer et incrémenter la séquence, comme dans l'expression

INSERT INTO XQX.myTable
   (
    x_ID,
    x_Name,
    x_Phone
   )
VALUES
   (
    NEXT VALUE FOR XQX.mySeqObj,
    #Name#,
    #Phone#
   )

Si vous souhaitez connaître la valeur antérieure attribuée dans la session en cours, vous pouvez utiliser l'expression PREVIOUS VALUE FOR mySeqObj mais, naturellement, seulement après avoir utilisé un NEXT VALUE l'expression dans le cadre de votre session.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X