Riempi una stringa con zeri iniziali in modo che sia lunga 3 caratteri in SQL Server 2008


398

Ho una stringa lunga fino a 3 caratteri quando viene creata per la prima volta in SQL Server 2008 R2.

Vorrei riempirlo con zeri iniziali, quindi se il suo valore originale fosse "1", il nuovo valore sarebbe "001". O se il suo valore originale era "23", il nuovo valore è "023". O se il suo valore originale è "124", il nuovo valore è uguale al valore originale.

Sto usando SQL Server 2008 R2. Come lo farei usando T-SQL?



Possibile duplicato di numeri
iniziali

Risposte:


681

Se il campo è già una stringa, funzionerà

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

Se si desidera che i null vengano visualizzati come '000'

Potrebbe essere un numero intero, quindi vorresti

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

Come richiesto dalla domanda, questa risposta funziona solo se la lunghezza <= 3, se si desidera qualcosa di più grande, è necessario modificare la costante di stringa e le due costanti di intero alla larghezza necessaria. per esempio'0000' and VARCHAR(4)),4


8
Avevo un campo Char (6) che aveva una manciata di valori che erano lunghi solo 2-3 caratteri e quanto sopra non funzionava per me. Ho dovuto aggiungere un RTRIM intorno a '000000' + ISNULL (FIELD, '') per farlo funzionare.
DWiener,

3
Hogan sì, l'ho capito, ma non importa per quanto tempo la stringa non ha funzionato, sono un po 'troppo impegnata per capire perché, ma l'essenza è che con il mio campo CHAR (6) sto solo facendo DESTRA (' 000000 '+ ISNULL (field,' '), 6) non ha funzionato ma RIGHT (RTRIM (' 000000 '+ ISNULL (field,' ')), 6) ha funzionato.
DWiener,

2
oh ho capito, avevi spazi a destra di un numero codificato come una stringa.
Hogan,

3
@dwiener hai questo comportamento perché un char è un tipo di dati a lunghezza fissa, quindi nel tuo caso char (6) significa 6 caratteri lunghi. Se il valore effettivo è inferiore a 6, viene riempito con spazi vuoti a destra, quindi la risposta proposta produrrebbe un risultato errato per un carattere (6).
Giannis Paraskevopoulos,

2
@Hogan, sì, ma questa domanda è il primo risultato google per "sql aggiungi zero iniziali", quindi penso che sarebbe utile per molte persone (che non usano sqlserver, ma google questa domanda) sapere che in altri database potrebbero esiste una funzione più comoda lpad. Grazie lo stesso.
Diralik,

142

Sebbene la domanda fosse per SQL Server 2008 R2, nel caso qualcuno lo stia leggendo con la versione 2012 e successive, da allora è diventato molto più facile con l'uso di FORMAT .

Puoi passare una stringa di formato numerico standard o una stringa di formato numerico personalizzata come argomento del formato (grazie a Vadim Ovchinnikov per questo suggerimento).

Per questa domanda, ad esempio, un codice come

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#');

uscite

001
001

2
Cosa succede se il numero di input è 111 o 11?
Hogan,

6
Per 1 è 001, per 11 è 011 e per 111 è 111
Géza il

2
Puoi usare 'D3' invece di '00 # '.
Vadim Ovchinnikov,

1
sembra essere molto più lento della risposta accettata ma molto più semplice se non si lavora con grandi quantità di dati
root

2
Sebbene sembri illogico, vale la pena notare che FORMAT funziona solo con tipi numerici e di data, non varchar.
Strattonn,

120

Il metodo sicuro:

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

Ciò ha il vantaggio di restituire la stringa '***'per n <0 o n> 999, che è un indicatore piacevole ed evidente dell'input fuori dai limiti. Gli altri metodi elencati qui falliranno silenziosamente troncando l'input su una sottostringa di 3 caratteri.


10
Accidenti, chiunque atterra su questa pagina dovrebbe aiutare questo float verso l'alto!
MarioDS,

1
Diventato con questo metodo. Quando l'espressione supera la lunghezza specificata, la stringa restituisce ** per la lunghezza specificata. per es. str (n, 10), quando n = 1000000000, appariranno le stelle (*).
Nessun impegno specifico

Non so come funzioni ma è sorprendente e semplice.
RaRdEvA,

1
Attento a questo, le stringhe lo rompono (e l'OP ha chiesto "riempire una stringa"). Opere: SELECT REPLACE(STR('1',3),' ','0')Breaks: SELECT REPLACE(STR('1A',3),' ','0'). Questo mi ha bruciato oggi quando un utente ha inserito una lettera nella stringa di input e non sono riuscito a provare quel caso.
Jeff Mergler,

@Unbound Ecco come dovrebbe funzionare, lo dice già il poster. Meglio restituire *** che un valore troncato come fanno tutte le altre proposte, mostra che i parametri erano sbagliati.
Marc Guillot,

32

Ecco una tecnica più generale per l'imbottitura a sinistra di qualsiasi larghezza desiderata:

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)

Tuttavia, se hai a che fare con valori negativi e il riempimento con zero iniziali, né questo, né altre tecniche suggerite funzioneranno. Otterrai qualcosa che assomiglia a questo:

00-123

[Probabilmente non quello che volevi]

Quindi ... dovrai saltare alcuni cerchi aggiuntivi Ecco un approccio che formatterà correttamente i numeri negativi:

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
         )

Si noti che le convert()chiamate devono specificare una [n]varcharlunghezza sufficiente per contenere il risultato convertito con troncamento.


2
@StenPetrov, grazie. Tutto dipende da ciò che stai cercando di realizzare. L'unica cosa su cui ho imparato a dipendere da grandi database di produzione nel mondo reale è la presenza di dati errati di un tipo o di un altro. E preferisco evitare le telefonate alle 3 del mattino, se possibile; ^)
Nicholas Carey,

:) ancora quando arriva la chiamata alle 3AM, preferirei leggere 1 riga semplice anziché 10 linee complesse. L'aggiunta di variabili peggiora ulteriormente le cose, soprattutto se un altro membro del team ha deciso di calcolarle al volo e non ha verificato la presenza di @width non negativa ...
Sten Petrov

Queste variabili aggiunte sono solo per la generalizzazione: puoi codificare i valori. Per un liner, puoi creare una funzione scalare, quindi hai il tuo liner unico.
Gerard ONeill,

30

Ecco una variante della risposta di Hogan che utilizzo in SQL Server Express 2012:

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

Invece di preoccuparmi se il campo è una stringa o no, lo accetto CONCATe basta , poiché emetterà comunque una stringa. Inoltre, se il campo può essere un NULL, ISNULLpotrebbe essere necessario utilizzare per evitare che la funzione ottenga NULLrisultati.

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

1
Per quanto mi ricordo CONCAT ignora il valore se è nullo, quindi il primo funziona bene.
Marie,

Questa soluzione avrebbe funzionato indipendentemente dal campo di Field
Unbound il

23

Ho sempre trovato molto utile il seguente metodo.

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

15

Utilizzare questa funzione adatta a ogni situazione.

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

Uscita campione

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 

Questa dovrebbe essere la risposta accettata perché funziona su numeri e stringhe . E se non vuoi usare una funzione (ma perché no) funziona anche qualcosa del genere: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;che restituisce il primo esempio di Salar sopra. Grazie Salar.
Jeff Mergler,

Il mio commento sopra conteneva un refuso, dovrebbe essere letto: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;che ritorna 0000002016nel primo esempio sopra.
Jeff Mergler,

@JeffMergler - come funziona su numeri e stringhe? È una funzione che accetta un parametro intero. La domanda riguardava le stringhe.
Hogan,

5

Per coloro che desiderano aggiornare i loro dati esistenti ecco la query:

update SomeEventTable set eventTime=RIGHT('00000'+ISNULL(eventTime, ''),5)

3

Per i numeri interi è possibile utilizzare la conversione implicita da int a varchar:

SELECT RIGHT(1000 + field, 3)

4
Tuttavia, ciò fallirà dato un valore sufficientemente grande, inoltre, per valori negativi, otterrai ... risultati interessanti.
Nicholas Carey,

3

Conosco il suo vecchio biglietto, ho solo pensato di condividerlo.

Ho trovato questo codice alla ricerca di una soluzione. Non sono sicuro che funzioni su tutte le versioni di MSSQL. Ho MSSQL 2016.

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

restituisce "0023" Il 4 nella funzione STR è la lunghezza totale compreso il valore. Gli esempi 4, 23 e 123 avranno tutti 4 in STR e verrà aggiunta la quantità corretta di zeri. Puoi aumentarlo o diminuirlo. Non c'è bisogno di ottenere la lunghezza sul 23.

Modifica: vedo che è uguale al post @Anon.


3

Prova questo con lunghezza fissa.

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

select REPLICATE('0', 5 - LEN(123)) + '123'

2

Ho avuto un problema simile con la colonna intera come input quando avevo bisogno di output varchar (o stringa) di dimensioni fisse. Ad esempio, da 1 a '01', da 12 a '12'. Questo codice funziona:

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

Se l'input è anche una colonna di varchar, puoi evitare la parte di casting.


2

Per un approccio più dinamico prova questo.

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

1

Ho scritto questo perché avevo i requisiti per una lunghezza specifica (9). Riempie la sinistra con @pattern SOLO quando l'ingresso necessita di riempimento. Dovrebbe sempre restituire la lunghezza definita in @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

Restituisce 1234 input


1

È semplice

Piace:

DECLARE @DUENO BIGINT
SET @DUENO=5

SELECT 'ND'+STUFF('000000',6-LEN(RTRIM(@DueNo))+1,LEN(RTRIM(@DueNo)),RTRIM(@DueNo)) DUENO

0

Sono venuto qui specificamente per capire come convertire il mio fuso orario in una stringa di fuso orario per convertire le date in DATETIMEOFFSET in SQL Server 2008. Lordo, ma necessario.

Quindi ho bisogno di 1 metodo per far fronte a numeri negativi e positivi, formattandoli su due caratteri con uno zero iniziale, se necessario. La risposta di Anons mi ha avvicinato, ma i valori di fuso orario negativi sarebbero emersi come0-5 piuttosto che quelli richiesti-05

Quindi, con un po 'di ottimizzazione sulla sua risposta, questo funziona per tutte le conversioni dell'ora del fuso orario

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'

-1

Ho creato questa funzione che si rivolge a bigint e uno zero iniziale o altro carattere singolo (restituiti max 20 caratteri) e consente una lunghezza dei risultati inferiore alla lunghezza del numero di input:

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,' ')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.