web-dev-qa-db-fra.com

Incrémentation automatique en lettres et chiffres MS SQL

J'ai une question, comment réaliser l'incrémentation automatique dans MS SQL. la seule façon que je connaisse jusqu'à présent est de perfixer le tableau par exemple

CREATE TABLE Customer (
    CUSId INT NOT NULL IDENTITY(1, 1) PRIMARY KEY
    ,CUSKey AS 'Cus' + RIGHT('000' + CONVERT(VARCHAR(5), CUSId), 6) PERSISTED
    ,CusName VARCHAR(50)
    ,mobileno INT
    ,Gender VARCHAR(10)
    )

je vais avoir quelque chose comme

Cus0001
Cus0002

quoi après Cus9999?

certains comment puis-je atteindre l'incrémentation automatique comme celui-ci

CUSAB000001
CUSAB000002
CUSAB000003
CUSAB000004
CUSAB000005
CUSAB000006
CUSAB000007
CUSAB000008
CUSAB999999
CUSCD000001
CUSYZ999999.
5
Anis Maredia

Pour incrémenter des groupes commençant à AA et se terminant à ZZ, vous devez convertir la partie gauche du nombre (quel que soit le nombre de chiffres que vous souhaitez conserver sous forme d'entiers) en Base 26. Vous commencez par tronquer la partie droite du nombre afin de n'avoir que la partie gauche, puis vous divisez par 10 ^ IntegerDigits (par exemple 3 chiffres entiers == 10 ^ 3 == 1000) pour obtenir le A_, puis utilisez modulo sur le même 10 ^ IntegerDigits pour obtenir le côté _A. Ces valeurs nous obtiendront le décalage par rapport à la valeur ASCII pour A. Par exemple:

SELECT (123142 / 1000) AS [Truncated],
       (123142 / 1000) / 26 AS [SetsOf26],
       (123142 / 1000) % 26 AS [Remaining],
       CHAR(65) AS [A];

-- Truncated = 123
-- SetsOf26  = 4
-- Remaining = 19
-- A         = A

Nous pouvons rassembler tout cela dans un TVF en ligne (à des fins de démonstration, pas pour une utilisation dans une colonne calculée dans un tableau) comme suit:

CREATE FUNCTION dbo.Base26 (@Base10 INT)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
  WITH truncated AS
  (
    SELECT (@Base10 / 1000) AS [Value]
  )
  SELECT @Base10 AS [Actual],
    tr.Value AS [Truncated],
    CHAR(65 + (tr.Value / 26)) AS [1stChar],
    CHAR(65 + (tr.Value % 26)) AS [2ndChar],
    CHAR(65 + (tr.Value / 26))
      + CHAR(65 + (tr.Value % 26))
      + RIGHT('00' + CONVERT(VARCHAR(20), @Base10 % 1000), 3) AS [EndResult]
  FROM truncated tr;
GO

Ensuite, nous pouvons tester avec:

SELECT * FROM dbo.Base26(142);
SELECT * FROM dbo.Base26(3142);
SELECT * FROM dbo.Base26(123142);
SELECT * FROM dbo.Base26(123999);

qui renvoie:

Actual   Truncated   1stChar   2ndChar   EndResult
142      0           A         A         AA142

3142     3           A         D         AD142

123142   123         E         T         ET142

123999   123         E         T         ET999

CEPENDANT, Je ne vois absolument aucune raison de mettre cela en œuvre dans votre situation. Il n'y a aucun avantage à avoir une chaîne "CusXXXXXX" où "XXXXXX" est vraiment juste la valeur IDENTITY. Si vous deviez obscurcir le "XXXXXX" via un hachage ou l'inverse multiplicatif modulaire, alors cela pourrait être correct, bien que je ne sois toujours pas sûr que vous souhaitiez stocker la partie de chaîne "Cus" de celui-ci. Mais sous sa forme actuelle, vous ne tirez aucun avantage de cette opération. Vous gaspillez simplement de l'espace dans la base de données.

Autres notes:

  • Vous feriez mieux de ne pas abréger "Client" pour être "CUS" comme préfixe pour les colonnes de ce tableau. Utilisez simplement le nom complet de la table, en particulier pour la colonne ID: CustomerID et CustomerName.
  • Vous ne devez pas utiliser un type numérique (c'est-à-dire INT) pour stocker les numéros de téléphone. Les nombres sur lesquels vous n'effectuez pas d'opérations mathématiques doivent être stockés sous forme de chaînes. Cela s'applique également aux codes postaux, aux numéros de sécurité sociale (SSN), etc. Dans le cas des numéros de téléphone, ils ont souvent des extensions ou d'autres options non numériques, telles que le préfixe avec + S'ils se trouvent en dehors du pays de base.
  • Vous ne devez pas utiliser un type de chaîne (c'est-à-dire VARCHAR(10)) pour stocker un code/une étiquette répété tel que "sexe" (en supposant que les mots complets "mâle" et "femelle" ou similaire sont stockés, et que un classement non binaire/_BIN2 est utilisé). Vous devriez avoir une table de recherche "Genre" avec une colonne GenderID TINYINT Comme clé primaire (mais pas un IDENTITY ). Ensuite, dans la table Customer, vous auriez également GenderID TINYINT Mais ce serait une clé étrangère référençant dbo.Gender (GenderID).

    OU:

    Vous pouvez utiliser une colonne CHAR(1) COLLATE Latin1_General_100_BIN2 NOT NULL avec une contrainte CHECK imposant que seuls M et F sont acceptables. Cela vous donne un "code" lisible par l'homme tout en étant aussi efficace avec le stockage, la mémoire et les comparaisons qu'un TINYINT.

8
Solomon Rutzky

Lisez cet excellent article s'il vous plaît.

http://www.sqlteam.com/article/custom-auto-generated-sequences-with-sql-server

Notez que la colonne dbID est une identité standard générée par la base de données qui sera notre clé primaire physique de la table. Cependant, nous ajouterons une colonne CustomerNumber qui sera ce que nous exposons au monde extérieur au format "C0000", comme décrit.

Créons une fonction qui accepte un entier et utilise cet entier pour renvoyer notre numéro de client:

create function CustomerNumber (@id int) 
returns char(5) 
as 
begin 
return 'C' + right('0000' + convert(varchar(10), @id), 4) 
end

En utilisant cette fonction, nous pouvons simplement ajouter une colonne calculée à notre table comme ceci:

alter table Customers add CustomerNumber as dbo.CustomerNumber(dbID)