I - PROLEGOMENES
Actuellement, L'objet séquence ne permet pas de générer des clés uniques en fonction d'un paramètre variable. Exemple :
Comment générer des numéros uniques de factures, par année civile. C.à.d, numérotation des factures 1, 2, 3 pour l'année 2014, puis en recommence la numérotation 1, 2, 3, .. pour 2015 et ainsi de suite ?
Sachant que dans la pratique, un comptable travaille sur plusieurs années simultanées. Il doit traiter en même temps les factures de fin 2014 et les factures début 2015.
Dans ce contexte si on veut utiliser les séquences, il faudra une séquence par année civile, en plus, il faudra recourir systématiquement au SQL Dynamique pour utiliser la bonne séquence en fonction de l'année cible (2014, 2015 etc..). En effet, le nom d'une séquence dans les instructions comme NEXT VALUE FOR <Nom_de_la_sequence> ne peut pas être remplacée par une variable.
II - CE QUI MANQUE A SQL SERVER
D'après moi, il manque la notion de groupe ou collection d'objet séquences.
Il manque la possibilité d'avoir un groupe d'objets séquences (SEQUENCE) où chaque élément du groupe (ie chaque séquence sera identifiée par une clé unique de type sysname par exemple ).
Cela permettra de générer des clés uniques en fonction d'une paramètre (ou cle) variable (exemple des numéros uniques par année civile). comme expliqué ci-haut, l'objet séquence ne permet pas de le faire sans une gymnastique complexe (SQL Dynamaique etc..)
Ci-dessous quelques exemple pour expliquer et étayer mon idée (suggestion d'évolution) :
Exemple 1 : Groupe de séquence : GRP_SEQENCe_NUMERO_FACTURE_ANNEE représenté ci-dessous comme collection (key, {objet SEQUENCE}) :
1 2 3 4
| Key Objet Séquence
'2014' {objet SEQUENCE}
'2015' {objet SEQUENCE}
'2016' {objet SEQUENCE} |
Dans la synoptique ci-dessus, j'ai utilisé des années au format chaîne de caractères pour illustrer mon exemple, mais le concept reste générale, j'aurais pu choisir 'Compteur1', 'Compteur2', etc. comme le montre l'exemple n° 2 :
Exemple 2 : Groupe de séquence : GRP_SEQENCE_COMPTEUR Exemple :
1 2 3 4
| Key Objet Séquence
'Compteut_1' {objet SEQUENCE}
'Compteut_2' {objet SEQUENCE}
'Compteut_3' {objet SEQUENCE} |
Chaque Objet séquence ({objet SEQUENCE}) représentera une séquence (SEQUENCE) telle existe déjà actuellement sous SQL Server depuis la version SQL Server 2012.
Il faudra ensuite enrichir le langage T-SQL pour permettre la manipulation des groupes de séquences :
Création d'un groupe de séquence
CREATE GROUP SEQUENCE dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE;
Ajouter une Clé/Séquence au groupe de séquences GRP_SEQENCE_NUMERO_FACTURE_ANNEE.
GROUP SEQUENCE étant un nouveau mot clé réservé du langage T-SQL
1 2
| ALTER GROUP SEQUENCE dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE dbo.GRP_SEQUENCE ADD KEY '2014' START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 999999999 NO CYCLE
ALTER GROUP SEQUENCE dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE dbo.GRP_SEQUENCE ADD KEY '2015' START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 999999999 NO CYCLE |
Supprimer une Clé/séquence d'un groupe de séquence
ALTER GROUP SEQUENCE dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE dbo.GRP_SEQUENCE DROP KEY '2014';
Obtenir les informations détaillées pour chacune des clés du groupe de séquences
Remarque :
. sys.GroupSequences serait une nouvelle table système
. on obtiendrais un peu près l'équivalent de la vue système sys.Sequences, mais une ligne par clé (key) du groupe de séquence
1 2 3
| SELECT * FROM sys.GroupSequences
WHERE SCHEMA_NAME(Schema_id) = 'dbo'
AND name 'GRP_SEQENCE_NUMERO_FACTURE_ANNEE' ; |
Utilisation de l'objet groupe de séquences.
L'exemple ci-dessous permettra d'obtenir le numéro suivant de l'objet séquence ayant pour clé '2014', appartenant au groupe de séquences dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE
Tout l'intérêt de l'exposé est là :
. Il faut que la syntaxe soit "souple" sans que l'on soit obligé de recourir au SQL Dynamique.
. Il faut que l'on puisse utiliser les variables pour la clé (Key) de la séquence
Exemple 1.1 :
Il faut que l'instruction ci-dessous ne génère pas d'erreur si la clé '2014' n'existe pas dans le groupe de séquences. Si la clé n'existe pas l'instruction ci-dessous retournera NULL,
SELECT NEXT VALUE FOR dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE WITH( KEY('2014') )
Exemple 1.2
. Il faut que l'on puisse utiliser les variables pour la clé (Key) de la séquence
1 2 3
| DECLARE @Cle sysname;
SET @Cle = '2015'
SELECT NEXT VALUE FOR dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE WITH( KEY(@Cle)) |
On pourrait prévoir une option RAISERROR, afin de générer le cas échéant une erreur de sévérité 16 si la clé (dans notre exemple '2014') n'existe pas.
SELECT NEXT VALUE FOR dbo.GRP_SEQENCE_NUMERO_FACTURE_ANNEE WITH( KEY('2014'), RAISERROR )
III - CONCLUSION
En fait l'objectif et mon souhait c'est l'implémentation native dans SQL Server, au travers les objets séquences (et le nouvel objet groupe de séquences) de la solution proposée par SQLPRo dans son excellent article http://sqlpro.developpez.com/cours/clefs/ paragraphe "3.2. La solution : une table des clefs". SQLPro propose une solution éprouvée fiable et sûre pour une gestion des clés (un distributeur de clé unique).
solution que personnellement, j'ai déjà, mis en œuvre, dans plusieurs applications et je pense que cette solution mérite d'être généralisée et intégrée nativement dans SQL Server au travers les objets séquence et le nouvel objet groupe de séquences). Cela permet notamment :
- d'Eviter de créer une table exprès pour les séquences applicatives (Cf table LesClefs dans l'article de SQLPro), ce point est moins important
- Le plus important étant de masquer au développeur lambda (non expérimenté), la complexité de jongler avec les niveaux d'isolation pour générer des clés uniques en fonction d'un paramètre variable (exemple des clés unique par année civile).
Qu'en pensez-vous ?
A+
Partager