Mise en forme des nombres par remplissage avec des zéros non significatifs dans SQL Server


119

Nous avons une ancienne table SQL qui a été utilisée par SQL Server 2000 pendant près de 10 ans.

Dans celui-ci, les numéros de badge de nos employés sont stockés char(6)du 000001au 999999.

J'écris actuellement une application Web et j'ai besoin de stocker les numéros de badge des employés.

Dans ma nouvelle table, je pourrais prendre le raccourci et copier l'ancienne table, mais j'espère un meilleur transfert de données, une taille plus petite, etc., en stockant simplement les intvaleurs de 1à 999999.

En C #, je peux rapidement mettre en forme une intvaleur pour le numéro de badge en utilisant

public static string GetBadgeString(int badgeNum) {
  return string.Format("{0:000000}", badgeNum);
  // alternate
  // return string.Format("{0:d6}", badgeNum);
}

Comment modifier cette simple requête SQL pour formater également la valeur renvoyée?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Si EmployeeIDest 7135, cette requête doit renvoyer 007135.


Puisque les leaders 0sont importants dans ce domaine, pourquoi le changer en un INT?
Oded

2
SQL Server 2012 aura enfin une FORMATfonction comme C # :-)
marc_s

1
@Oden: Les intvaleurs occupent beaucoup moins d'espace que char(6), et il y aura plusieurs de ces entrées par pièce fabriquée. Efficacité.
jp2code

Optimisez-vous avant de rencontrer un problème?
Oded

4
Voyons voir, vous avez jusqu'à un million de numéros de badge et vous pensez que vous pouvez enregistrer (selon DATALENGTH()) deux octets chacun. Étant donné que la colonne peut être dans un index, vous pourriez économiser plus de 2 Mo. Et avec les autres colonnes ajoutées, ces 2 octets pourraient suffire à réduire suffisamment la longueur d'une ligne pour enregistrer une page de 4 Ko par ligne. Est-ce que cela va être hébergé sur une plate-forme mobile, ou pourriez-vous concentrer votre attention sur une zone improductive?
HABO

Réponses:


172

Changez le nombre 6 en ce que votre longueur totale doit être:

SELECT REPLICATE('0',6-LEN(EmployeeId)) + EmployeeId

Si la colonne est un INT, vous pouvez utiliser RTRIM pour la convertir implicitement en VARCHAR

SELECT REPLICATE('0',6-LEN(RTRIM(EmployeeId))) + RTRIM(EmployeeId)

Et le code pour supprimer ces 0 et récupérer le `` vrai '' nombre:

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)

1
+1 Vous m'avez même montré comment supprimer les 0! Laissez-moi tester ceci, et je le marquerai comme une réponse.
jp2code

vous n'avez pas besoin de code pour supprimer les zéros, attribuez simplement ou convertissez-les en int et ils seront supprimés automatiquement.
Jimbo

2
Cela ne fonctionne que si la valeur transmise est une chaîne, si vous passez un entier, vous obtenez la même valeur que vous avez transmise.
Mordy

2
Bien que son ancien ... l'utilisation de "+ convert (varchar, EmployeeID)" au lieu de "+ EmployeeID" devrait résoudre le problème int
Krishna Sarma

3
c'est un bon moyen à moins que EmployeeId ne soit supérieur à 6 chiffres, ce qui entraîne un résultat NULL. La fonction de contact est la réponse: SELECT CONCAT (REPLICATE ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Mahmoud Moravej

125

Utilisez simplement la fonction FORMAT (fonctionne sur SQL Server 2012 ou plus récent):

SELECT FORMAT(EmployeeID, '000000')
FROM dbo.RequestItems
WHERE ID=0 

Référence: http://msdn.microsoft.com/en-us/library/hh213505.aspx


1
C'est une vieille question - avant la sortie de SQL Server 2012.
jp2code

19
Pourtant, j'aimerais voir cette bulle un peu plus près du sommet maintenant.
Dave Haynes

4
Juste au cas où quelqu'un se demanderait. Formatne conserve pas le type de données mais se convertit implicitement en nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph

2
Cette façon est la plus simple et à mon humble avis la meilleure solution.
Robert Lujo

Soyez conscient de cette fonction si vous l'utilisez pour un grand ensemble de données
amd le

33

Vous pouvez modifier votre procédure de cette manière

SELECT Right('000000' + CONVERT(NVARCHAR, EmployeeID), 6) AS EmpIDText, 
       EmployeeID
FROM dbo.RequestItems 
WHERE ID=0 

Cependant, cela suppose que vous EmployeeIDêtes une valeur numérique et que ce code change le résultat en une chaîne, je suggère d'ajouter à nouveau la valeur numérique d'origine

EDIT Bien sûr, je n'ai pas lu attentivement la question ci-dessus. Il indique que le champ est un char(6)donc EmployeeID n'est pas une valeur numérique. Bien que cette réponse ait toujours une valeur en soi, ce n'est pas la bonne réponse à la question ci-dessus.


C'est la manière la plus propre de le faire, je pense. Merci
iheartcsharp

Est-ce '000000'vraiment nécessaire ..? '0'fonctionne également très bien. Est-il sécuritaire d'utiliser un seul 0 ..?
shashwat

1
L'OP a demandé une chaîne de 6 caractères en conséquence. Plus précisément, si EmployeeID est 7135, cette requête doit renvoyer 007135 . L'utilisation d'un seul «0» 07135ne renvoie pas 007135. L'idée générale est de concaténer en une chaîne de 6 caractères composée de toute 0la chaîne EmployeedID convertie, puis de STARTING à partir du bord droit prendre 6 caractères. Quelle que soit la longueur de l'ID, la méthode ci-dessus renvoie toujours une chaîne avec juste le nombre de caractères zéro requis pour atteindre la longueur de 6 caractères
Steve

Il peut s'agir de 5 zéros '00000'puisque le EmployeeIDcontiendra au moins un chiffre. Mais la REPLICATE()fonction semble plus adaptée, comme dans les autres réponses
nosklo

26

J'ai détesté avoir à CONVERTIR l'int, et cela semble beaucoup plus simple. Peut-être même plus performant puisqu'il n'y a qu'une seule conversion de chaîne et un simple ajout.

sélectionnez DROITE (1000000 + EmployeeId, 6) ...

Assurez-vous simplement que le "1000000" a au moins autant de zéros que la taille nécessaire.


11

Je poste tout au même endroit, tout fonctionne pour moi pour compléter avec 4 zéro en tête :)

declare @number int =  1;
print right('0000' + cast(@number as varchar(4)) , 4)
print right('0000' + convert(varchar(4), @number) , 4)
print right(replicate('0',4) + convert(varchar(4), @number) , 4)
print  cast(replace(str(@number,4),' ','0')as char(4))
print format(@number,'0000')

Cela couvre toutes les options nécessaires. Je vous remercie.
kyurthich

6

Une autre façon, juste pour l'exhaustivité.

DECLARE @empNumber INT = 7123
SELECT STUFF('000000', 6-LEN(@empNumber)+1, LEN(@empNumber), @empNumber)

Ou, selon votre requête

SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
         AS EmployeeCode
FROM dbo.RequestItems
WHERE ID=0

@ jp2code - vous devez lire ce qu'est StackOverflow - il est édité en collaboration comme un wiki - ce n'est pas votre question dès que vous l'avez posté! Les choses qui sont généralement supprimées sont des «peluches» excessives comme les remerciements à l'avance et une mauvaise grammaire / capitalisation.
Jamiec

5

À partir de la version 2012, vous pouvez utiliser

SELECT FORMAT(EmployeeID,'000000')
FROM dbo.RequestItems
WHERE ID=0

4

Aussi propre que possible et donne la possibilité de remplacer par des variables:

Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
WHERE ID=0

Si la EmployeeIDcolonne est définie comme intalors l'opérateur + sera traité comme une addition plutôt que comme une concaténation et ainsi les zéros seront perdus. L'utilisation convertévitera ce problème.

Appeler REPLICATE ('0', 6) pour éviter de taper '000000' est juste un gaspillage ;-)
Mladen Mihajlovic

3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0

2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0

Oups. En fait, cela m'a donné 7135.0quand je l'ai donné 7135.
jp2code

1

La solution fonctionne pour les nombres signés / négatifs avec des zéros non significatifs, pour toutes les versions de SQL:

DECLARE
    @n money = -3,
    @length tinyint = 15,
    @decimals tinyint = 0

SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')

1

Le plus simple est toujours le meilleur:

Select EmployeeID*1 as EmployeeID 

-1

Dans ma version de SQL, je ne peux pas utiliser REPLICATE. Alors j'ai fait ceci:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.