-3
votes

Comment générer une clé unique personnalisée par an

Je voudrais générer une clé séquentielle personnalisée qui devrait redémarrer à chaque nouvel exercice financier. J'ai fourni une exemple de données avec le FinancialiaLear CODE> et CustomKey code> Colonnes.

Remarque: je veux m'assurer que la même valeur n'est pas au cours de deux ou plusieurs tentatives de Ajoutez des lignes en même temps. P>

Exemple de données: P>

ID    |   FinancialYear   |  CustomKey
1     |   2019            |  1
2     |   2019            |  2
3     |   2020            |  1


2 commentaires

Toute explication de la personne qui a décidé de le dérouler? Serait apprécié.


Les descentes devraient savoir qu'il s'agit d'un problème très courant pour toute application de facturation.


3 Réponses :


1
votes

Que diriez-vous d'utiliser Max Customkey + 1?

DECLARE @NextCustomKey AS INT = 0;

SELECT @NextCustomKey = ISNULL(MAX(CustomKey),0) + 1
FROM [TableName]
WHERE FinancialYear = 2019;

INSERT INTO [TableName] (
FinancialYear
,CustomKey
)
VALUES (
2019
,@NextCustomKey
);


6 commentaires

Merci pour votre réponse, mais qu'en est-il de la concurrence?


@Agh, le code entier à envelopper par transaction avec une isolation de lecture ou plus élevée répétable, cela va être votre concurrent


@Alexandervolok Autant que je sache, il peut y avoir une clé personnalisée en double si le nombre d'utilisateurs tente d'ajouter une ligne en même temps.


@Agh pas avec un niveau d'isolement de lecture répétable, dans ce niveau d'isolement, votre deuxième utilisateur attendra jusqu'à ce que le premier ait terminé sa transaction avant d'obtenir une valeur. Le problème est que cela peut ralentir votre demande (en attente d'autres utilisateurs) et augmenter de nombreuses impasses.


@Marcguillot Merci d'explication, mettra à jour mes connaissances :)


@Marcguillot Puis-je savoir comment puis-je rentrée la dernière valeur d'incrémentation si la transaction en échec.



1
votes

Personnellement, je crée une séquence pour chaque partition (chaque année dans ce cas), je n'ai donc pas besoin de vous inquiéter de la concurrence (j'avais des blocages de constantes et des décalages avant d'utiliser des séquences en raison des niveaux d'isolement élevé nécessaires pour éviter les clés de double isolation ).

Vous pouvez définir une procédure stockée pour récupérer facilement une nouvelle clé (création de nouvelles séquences de manière dynamique si nécessaire). P>

CREATE PROCEDURE [dbo].[COUNTER_Rollback]
    @YEAR integer,
    @COUNTER integer
AS
  declare @LAST_COUNTER integer;
BEGIN
  -- If there are no new values greater thant the counter to rollback (the document rolled back was the last one), then we recalculate the counter

  if not exists (select * from MYTABLE where FinancialYear = @YEAR and CustomKey > @COUNTER)
  begin   
    select @LAST_COUNTER = isnull(max(CustomKey),0) + 1 from MYTABLE where FinancialYear = @YEAR;

    exec COUNTER_SetValue @YEAR = @YEAR, @COUNTER = @LAST_COUNTER;
  end
  else 
  begin
    throw 99001, 'The sequence can''t be rolled back beause there are new values and you''ll need to fill the holes manually', 1;
  end 
END


4 commentaires

Merci pour la réponse, je connaissais la séquence, mais la logique n'est pas venue dans mon esprit. Cependant, je vais essayer cela et vous le faire savoir.


Je ne peux pas faire la séquence de restauration comme ne prend pas en charge les transactions. Je peux modifier la séquence dans un bloc d'exception si une erreur se produit, mais ce n'est pas une bonne idée, car à ce moment-là, autre connexion génère une valeur suivante. S'il vous plaît partager une suggestion si vous avez.


@Agh Rolling Back Actions n'a pas de solution facile, car, comme vous le dites, d'autres utilisateurs ont peut-être déjà généré leurs propres valeurs, de sorte que vous obtenez un trou dans votre numéro et vous ne pouvez pas simplement diminuer votre compteur. Personnellement, je vérifie si ma valeur est la dernière valeur et que dans ce cas, je diminue la séquence, mais s'il y avait déjà une autre valeur, vous devez remplir le trou manuellement. Je mettrai à jour la réponse montrant toutes mes procédures.


@Agh j'ai mis à jour la réponse.



0
votes

Que diriez-vous de la solution ci-dessous? XXX

Je ne suis pas sûr que vous allez insérer des données en vrac ou à une ligne unique à la fois. En cas d'enregistrement unique ci-dessus, le code devrait être bien. En cas de charge en vrac, nous devons convertir le paramètre de procédure pour être Varcharne et les valeurs doivent être transmises en tant que CSV. Après cela, convertissez CSV en tableau et apportez des modifications appropriées à la logique réelle.


4 commentaires

Merci mais cela augmentera de nombreuses impasse et baissera le système.


@Agh Pour gérer la concurrence Vous pouvez ajouter une colonne de plus avec Rowversion DataType.


Rharnderon peut ne pas m'aider à générer un numéro de séquence.


J'ai déjà mentionné que vous pouvez utiliser Rowversion pour gérer la concurrence pour ne pas générer de numéro de séquence.