Remplissez une chaîne avec des zéros de début pour qu'elle comporte 3 caractères dans SQL Server 2008

398

J'ai une chaîne de 3 caractères maximum lorsqu'elle est créée pour la première fois dans SQL Server 2008 R2.

Je voudrais le remplir avec des zéros en tête, donc si sa valeur d'origine était '1' alors la nouvelle valeur serait '001'. Ou si sa valeur d'origine était '23', la nouvelle valeur est '023'. Ou si sa valeur d'origine est «124», la nouvelle valeur est identique à la valeur d'origine.

J'utilise SQL Server 2008 R2. Comment pourrais-je faire cela en utilisant T-SQL?

Sunil
la source

Réponses:

681

Si le champ est déjà une chaîne, cela fonctionnera

 SELECT RIGHT('000'+ISNULL(field,''),3)

Si vous souhaitez que les valeurs nulles s'affichent en tant que '000'

Ce pourrait être un entier - alors vous voudriez

 SELECT RIGHT('000'+CAST(field AS VARCHAR(3)),3)

Comme requis par la question, cette réponse ne fonctionne que si la longueur <= 3, si vous voulez quelque chose de plus grand, vous devez changer la constante de chaîne et les deux constantes entières à la largeur nécessaire. par exemple'0000' and VARCHAR(4)),4

Hogan
la source
8
J'avais un champ Char (6) qui avait une poignée de valeurs qui ne faisaient que 2-3 caractères et ce qui précède ne fonctionnait pas pour moi. J'ai dû ajouter un RTRIM autour du '000000' + ISNULL (FIELD, '') pour que cela fonctionne.
DWiener
3
Hogan ouais j'ai compris, mais peu importe combien de temps la chaîne n'a pas fonctionné, je suis un peu trop occupé pour comprendre pourquoi, mais l'essentiel est qu'avec mon champ CHAR (6) juste à droite ('000000 '+ ISNULL (champ,' '), 6) n'a pas fonctionné mais RIGHT (RTRIM (' 000000 '+ ISNULL (champ,' ')), 6) a fonctionné.
DWiener
2
oh je comprends, vous aviez des espaces à droite d'un nombre codé en chaîne.
Hogan
3
@dwiener vous avez obtenu ce comportement car un char est un type de données de longueur fixe, donc dans votre cas char (6) signifie 6 caractères de long. Si votre valeur réelle est inférieure à 6, elle est complétée par des blancs à droite, de sorte que la réponse proposée produirait un résultat incorect pour un caractère (6).
Giannis Paraskevopoulos
2
@Hogan, oui, mais cette question est le résultat top1 de google pour "sql ajouter des zéros de tête", donc je pense que ce serait utile pour beaucoup de gens (qui n'utilisent pas sqlserver, mais google cette question) de savoir que dans d'autres bases de données peuvent existe une fonction plus pratique lpad. Merci quand même.
diralik
142

Bien que la question soit pour SQL Server 2008 R2, au cas où quelqu'un lirait ceci avec la version 2012 et supérieure, depuis, cela est devenu beaucoup plus facile grâce à l'utilisation de FORMAT .

Vous pouvez soit passer une chaîne de format numérique standard ou une chaîne de format numérique personnalisée comme argument de format (merci Vadim Ovchinnikov pour cet indice).

Pour cette question par exemple un code comme

DECLARE @myInt INT = 1;
-- One way using a standard numeric format string
PRINT FORMAT(@myInt,'D3');
-- Other way using a custom numeric format string
PRINT FORMAT(@myInt,'00#');

les sorties

001
001
Géza
la source
2
Que se passe-t-il si le numéro d'entrée est 111 ou 11?
Hogan
6
Pour 1 c'est 001, pour 11 c'est 011 et pour 111 c'est 111
Géza
2
Vous pouvez utiliser 'D3' au lieu de '00 # '.
Vadim Ovchinnikov
1
cela semble être beaucoup plus lent que la réponse acceptée mais tellement plus facile si vous ne travaillez pas avec de grandes quantités de données
root
2
Bien que cela semble illogique, il convient de noter que FORMAT ne fonctionne qu'avec des types numériques et de date, pas varchar.
strattonn
120

La méthode sûre:

SELECT REPLACE(STR(n,3),' ','0')

Cela a l'avantage de renvoyer la chaîne '***'pour n <0 ou n> 999, ce qui est un indicateur agréable et évident d'une entrée hors limites. Les autres méthodes répertoriées ici échoueront en silence en tronquant l'entrée à une sous-chaîne à 3 caractères.

Anon
la source
10
Merde, celui qui atterrit sur cette page devrait aider ce flotteur vers le haut!
MarioDS
1
Soyez prudent avec cette méthode. Lorsque l'expression dépasse la longueur spécifiée, la chaîne renvoie ** pour la longueur spécifiée. par exemple str (n, 10), lorsque n = 1000000000, alors vous aurez des étoiles (*) apparaissant.
Non consolidé,
Je ne sais pas comment cela fonctionne, mais c'est incroyable et simple.
RaRdEvA
1
Attention à celui-ci, les cordes le cassent (et l'OP a demandé de "remplir une chaîne"). Travaux: SELECT REPLACE(STR('1',3),' ','0')Pauses: SELECT REPLACE(STR('1A',3),' ','0'). Cela m'a brûlé aujourd'hui lorsqu'un utilisateur a entré une lettre dans la chaîne d'entrée et que je n'ai pas testé ce cas.
Jeff Mergler
@Unbound C'est ainsi que cela doit fonctionner, l'affiche le dit déjà. Mieux vaut renvoyer *** qu'une valeur tronquée comme toutes les autres propositions, cela montre que les paramètres étaient incorrects.
Marc Guillot
32

Voici une technique plus générale pour le rembourrage gauche à n'importe quelle largeur souhaitée:

declare @x     int     = 123 -- value to be padded
declare @width int     = 25  -- desired width
declare @pad   char(1) = '0' -- pad character

select right_justified = replicate(
                           @pad ,
                           @width-len(convert(varchar(100),@x))
                           )
                       + convert(varchar(100),@x)

Cependant, si vous avez affaire à des valeurs négatives et à un remplissage avec des zéros non significatifs, ni cela, ni aucune autre technique suggérée ne fonctionnera. Vous obtiendrez quelque chose qui ressemble à ceci:

00-123

[Probablement pas ce que vous vouliez]

Donc ... vous devrez sauter à travers quelques cerceaux supplémentaires Voici une approche qui formatera correctement les nombres négatifs:

declare @x     float   = -1.234
declare @width int     = 20
declare @pad   char(1) = '0'

select right_justified = stuff(
         convert(varchar(99),@x) ,                            -- source string (converted from numeric value)
         case when @x < 0 then 2 else 1 end ,                 -- insert position
         0 ,                                                  -- count of characters to remove from source string
         replicate(@pad,@width-len(convert(varchar(99),@x)) ) -- text to be inserted
         )

Il convient de noter que les convert()appels doivent spécifier une [n]varcharlongueur suffisante pour contenir le résultat converti avec troncature.

Nicholas Carey
la source
2
@StenPetrov, merci. Tout dépend de ce que vous essayez d'accomplir. La seule chose dont j'ai appris à dépendre dans de grandes bases de données de production réelles est la présence de mauvaises données d'une sorte ou d'une autre. Et je préfère éviter les appels téléphoniques de 3 heures du matin si je le peux; ^)
Nicholas Carey
:) quand cet appel à 3 heures du matin arrive, je préfère de loin lire 1 ligne simple que 10 lignes complexes. L'ajout de variables aggrave encore les choses, surtout si un autre membre de l'équipe a décidé de les calculer à la volée et n'a pas vérifié la @width non négative ...
Sten Petrov
Ces variables ajoutées sont juste pour la généralisation - vous pouvez coder en dur les valeurs. Pour la doublure unique, vous pouvez créer une fonction scalaire - puis vous avez votre doublure unique.
Gerard ONeill
30

Voici une variante de la réponse de Hogan que j'utilise dans SQL Server Express 2012:

SELECT RIGHT(CONCAT('000', field), 3)

Au lieu de vous inquiéter si le champ est une chaîne ou non, je viens de le CONCATfaire, car il produira de toute façon une chaîne. De plus, si le champ peut être un NULL, l'utilisation ISNULLpeut être nécessaire pour éviter que la fonction n'obtienne des NULLrésultats.

SELECT RIGHT(CONCAT('000', ISNULL(field,'')), 3)
jahu
la source
1
Autant que je me souvienne, CONCAT ignore simplement la valeur si elle est nulle, donc la première fonctionne correctement.
Marie
Cette solution fonctionnerait quel que soit le len de Field
Unbound
23

J'ai toujours trouvé la méthode suivante très utile.

REPLICATE('0', 5 - LEN(Job.Number)) + CAST(Job.Number AS varchar) as 'NumberFull'
Facture
la source
15

Utilisez cette fonction qui convient à toutes les situations.

CREATE FUNCTION dbo.fnNumPadLeft (@input INT, @pad tinyint)
RETURNS VARCHAR(250)
AS BEGIN
    DECLARE @NumStr VARCHAR(250)

    SET @NumStr = LTRIM(@input)

    IF(@pad > LEN(@NumStr))
        SET @NumStr = REPLICATE('0', @Pad - LEN(@NumStr)) + @NumStr;

    RETURN @NumStr;
END

Exemple de sortie

SELECT [dbo].[fnNumPadLeft] (2016,10) -- returns 0000002016
SELECT [dbo].[fnNumPadLeft] (2016,5) -- returns 02016
SELECT [dbo].[fnNumPadLeft] (2016,2) -- returns 2016
SELECT [dbo].[fnNumPadLeft] (2016,0) -- returns 2016 
Salar
la source
Cela devrait être la réponse acceptée car elle fonctionne sur les nombres et les chaînes . Et si vous ne voulez pas utiliser une fonction (mais pourquoi pas) quelque chose comme ça fonctionne aussi: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;qui retourne le premier exemple de Salar ci-dessus. Merci Salar.
Jeff Mergler
Mon commentaire ci-dessus contenait une faute de frappe, il devrait se lire: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;qui renvoie 0000002016dans le premier exemple ci-dessus.
Jeff Mergler
@JeffMergler - comment cela fonctionne-t-il sur les nombres et les chaînes? C'est une fonction qui prend un paramètre entier. La question portait sur les cordes.
Hogan
5

Pour ceux qui souhaitent mettre à jour leurs données existantes, voici la requête:

update SomeEventTable set eventTime=RIGHT('00000'+ISNULL(eventTime, ''),5)
Alan B. Dee
la source
3

Pour les entiers, vous pouvez utiliser la conversion implicite de int en varchar:

SELECT RIGHT(1000 + field, 3)
Konstantin
la source
4
Cependant, cela échouera étant donné une valeur suffisamment grande, de plus, pour les valeurs négatives, vous obtiendrez ... des résultats intéressants.
Nicholas Carey
3

Je connais son ancien ticket je pensais juste le partager.

J'ai trouvé ce code à la recherche d'une solution. Je ne sais pas si cela fonctionne sur toutes les versions de MSSQL, j'ai MSSQL 2016.

declare @value as nvarchar(50) = 23
select REPLACE(STR(CAST(@value AS INT) + 1,4), SPACE(1), '0') as Leadingzero

renvoie "0023" Le 4 dans la fonction STR est la longueur totale, y compris la valeur. Les exemples 4, 23 et 123 auront tous 4 en STR et la quantité correcte de zéros sera ajoutée. Vous pouvez l'augmenter ou le diminuer. Pas besoin d'avoir la longueur du 23.

Edit: je vois que c'est la même chose que @Anon post.

Niel achète
la source
3

Essayez ceci avec une longueur fixe.

select right('000000'+'123',5)

select REPLICATE('0', 5 - LEN(123)) + '123'
Dr.Stark
la source
2

J'ai eu un problème similaire avec la colonne entière en entrée lorsque j'avais besoin d'une sortie varchar (ou chaîne) de taille fixe. Par exemple, 1 à «01», 12 à «12». Ce code fonctionne:

SELECT RIGHT(CONCAT('00',field::text),2)

Si l'entrée est également une colonne de varchar, vous pouvez éviter la partie de coulée.

user3183867
la source
2

Pour une approche plus dynamique, essayez ceci.

declare @val varchar(5)
declare @maxSpaces int
set @maxSpaces = 3
set @val = '3'
select concat(REPLICATE('0',@maxSpaces-len(@val)),@val)
ncastillo
la source
1

A écrit cela parce que j'avais des exigences pour une longueur spécifique (9). Remplit la gauche avec @pattern UNIQUEMENT lorsque l'entrée doit être complétée. Doit toujours renvoyer la longueur définie dans @pattern.

declare @charInput as char(50) = 'input'

--always handle NULL :)
set @charInput = isnull(@charInput,'')

declare @actualLength as int = len(@charInput)

declare @pattern as char(50) = '123456789'
declare @prefLength as int = len(@pattern)

if @prefLength > @actualLength
    select Left(Left(@pattern, @prefLength-@actualLength) + @charInput, @prefLength)
else
    select @charInput

Renvoie 1234input

nicky
la source
1

C'est simple

Comme:

DECLARE @DUENO BIGINT
SET @DUENO=5

SELECT 'ND'+STUFF('000000',6-LEN(RTRIM(@DueNo))+1,LEN(RTRIM(@DueNo)),RTRIM(@DueNo)) DUENO
DEBASIS PAUL
la source
0

Je suis venu ici spécifiquement pour trouver comment convertir mon décalage horaire en une chaîne de fuseau horaire pour convertir les dates en DATETIMEOFFSET dans SQL Server 2008. Brut, mais nécessaire.

J'ai donc besoin d'une méthode capable de gérer les nombres négatifs et positifs, en les formatant en deux caractères avec un zéro en tête si nécessaire. La réponse Anons m'a rapproché, mais les valeurs de fuseau horaire négatives sortiraient 0-5plutôt que celles requises-05

Donc, avec un petit ajustement sur sa réponse, cela fonctionne pour toutes les conversions d'heure de fuseau horaire

DECLARE @n INT = 13 -- Works with -13, -5, 0, 5, etc
SELECT CASE 
    WHEN @n < 0 THEN '-' + REPLACE(STR(@n * -1 ,2),' ','0') 
    ELSE '+' + REPLACE(STR(@n,2),' ','0') END + ':00'
rouge
la source
-1

J'ai créé cette fonction qui s'adresse à bigint et un zéro à gauche ou un autre caractère unique (max 20 caractères retournés) et permet une longueur des résultats inférieure à la longueur du numéro d'entrée:

create FUNCTION fnPadNum (
  @Num BIGINT --Number to be padded, @sLen BIGINT --Total length of results , @PadChar varchar(1))
  RETURNS VARCHAR(20)
  AS
  --Pads bigint with leading 0's
            --Sample:  "select dbo.fnPadNum(201,5,'0')" returns "00201"
            --Sample:  "select dbo.fnPadNum(201,5,'*')" returns "**201"
            --Sample:  "select dbo.fnPadNum(201,5,' ')" returns "  201"
   BEGIN
     DECLARE @Results VARCHAR(20)
     SELECT @Results = CASE 
     WHEN @sLen >= len(ISNULL(@Num, 0))
     THEN replicate(@PadChar, @sLen - len(@Num)) + CAST(ISNULL(@Num, 0) AS VARCHAR)
     ELSE CAST(ISNULL(@Num, 0) AS VARCHAR)
     END

     RETURN @Results
     END
     GO

     --Usage:
      SELECT dbo.fnPadNum(201, 5,'0')
      SELECT dbo.fnPadNum(201, 5,'*')
      SELECT dbo.fnPadNum(201, 5,' ')
Shane
la source