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.

jp2code
la source
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)
Vince Pergolizzi
la source
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

EdMorte
la source
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.

Steve
la source
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.

JeffSahol
la source
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')
Raj Kumar
la source
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
Jamiec
la source
@ 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
Hagop Simonien
la source
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
Divanshu
la source
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
Jimbo
la source
2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0
user1227804
la source
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')
Zsolt v
la source
1

Le plus simple est toujours le meilleur:

Select EmployeeID*1 as EmployeeID 
Michal
la source
-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`
Zlato010
la source