Funzione PadLeft in T-SQL


113

Ho la seguente tabella A:

id
----
1
2
12
123
1234

Ho bisogno di inserire a sinistra i idvalori con zero:

id
----
0001
0002
0012
0123
1234

Come posso raggiungere questo obiettivo?

Risposte:


197

Credo che questo possa essere quello che stai cercando:

SELECT padded_id = REPLACE(STR(id, 4), SPACE(1), '0') 

FROM tableA

o

SELECT REPLACE(STR(id, 4), SPACE(1), '0') AS [padded_id]

FROM tableA

Non ho testato la sintassi nel 2 ° esempio. Non sono sicuro che funzioni al 100% - potrebbe richiedere qualche ritocco - ma trasmette l'idea generale di come ottenere l'output desiderato.

MODIFICARE

Per affrontare le preoccupazioni elencate nei commenti ...

@ pkr298 - Sì STR funziona solo sui numeri ... Il campo dell'OP è un ID ... quindi solo un numero.

@Desolator - Ovviamente non funzionerà ... il primo parametro è lungo 6 caratteri. Puoi fare qualcosa come:

SELECT REPLACE(STR(id,
(SELECT LEN(MAX(id)) + 4 FROM tableA)), SPACE(1), '0') AS [padded_id] FROM tableA

questo dovrebbe teoricamente spostare i pali della porta ... man mano che il numero aumenta, dovrebbe SEMPRE funzionare ... indipendentemente se è 1 o 123456789 ...

Quindi se il tuo valore massimo è 123456 ... vedresti 0000123456 e se il tuo valore minimo è 1 vedresti 0000000001


4
STR () funziona solo sui numeri (o sui numeri nei campi stringa). Questo codice si interrompe se lo si utilizza su un campo varchar che si presume abbia un numero ma uno dei record contiene dati non validi (non numerici). La funzione RIGHT () non si interromperà in questo caso.
pkr298

1
La funzione STR () non funzionerà se il numero è maggiore (es. STR(123456, 4)Restituirà****

2
@Desolator ho aggiunto una risposta e una correzione per facilitare lo scenario che hai aggiunto.
Patrick

66

SQL Server ora supporta la funzione FORMAT a partire dalla versione 2012, quindi:

SELECT FORMAT(id, '0000') FROM TableA

farà il trucco.

Se il tuo ID o colonna è in a varchare rappresenta un numero che converti per primo:

SELECT FORMAT(CONVERT(INT,id), '0000') FROM TableA

Elegante e semplice, grazie! Data la data della domanda originale, questa dovrebbe ora essere la risposta ufficiale;)
David Gunderson

1
Se id è una stringa, puoi prima convertirla in numero intero: seleziona il formato (convert (int, id), '0000')
CrimsonKing

Scusa ma ho un voto negativo perché in questo modo è DAVVERO lento. Ci sono voluti quattro secondi interi per eseguire oltre 90 righe, mentre la risposta accettata è stata istantanea. Questo è uno svantaggio molto importante e FORMAT dovrebbe essere utilizzato solo su uno o due record, max. Altrimenti è inutile a causa delle sue scarse prestazioni.
Shadow Wizard is Ear For You

@ShadowWizard Vedo prestazioni istantanee utilizzando FORMAT con migliaia di righe.
JohnnyHK

@JohnnyHK beh forse qualcosa con il design del tavolo o altre stranezze del db, ma comunque ... il fatto è che per me era molto lento mentre l'altro modo era veloce.
Shadow Wizard è Ear For You


43

Vecchio post, ma forse questo aiuta qualcuno:

Per completare fino a quando non finisce con 4 caratteri non vuoti:

SELECT RIGHT ('0000'+COLUMNNAME, 4) FROM TABLENAME;

Per completare fino alle 10:

SELECT RIGHT ('0000000000'+COLUMNNAME, 10) FROM TABLENAME;

Nel caso in cui la colonna sia numerica , convertila prima in varchar con tale codice:

Select RIGHT('0000'+Convert(nvarchar(20), COLUMNNAME), 4)
From TABLENAME

E per completare fino a 10 con un campo numerico:

SELECT RIGHT ('0000000000'+Convert(nvarchar(20), COLUMNNAME), 10) FROM TABLENAME;

1
@ SilverM-A, non esiste alcuna utilità per aggiungere 0 prima di un numero, poiché verranno comunque ignorati (0003 è 3 dopo tutto). Probabilmente quello che vuoi ottenere è eseguire il cast di quel numero su una stringa (varchar) e quindi utilizzare l'istruzione precedente.
Marcelo Myara

1
@ SilverM-A, se questo è il caso, lancialo usando il comando "CAST" come: SELECT RIGHT ('0000000000' + CAST (COLUMNNAME AS VARCHAR), 10) FROM TABLENAME; È così?
Marcelo Myara

@MarceloMyara questo dovrebbe essere parte della risposta, non solo un commento. Aggiunto ora me stesso.
Shadow Wizard is Ear For You

Nota: questa è la risposta più efficiente, senza funzioni fantasiose che potrebbero diventare molto lente. Quindi gli ho dato una taglia extra.
Shadow Wizard è Ear For You

12

Prova questo:

SELECT RIGHT(REPLICATE('0',4)+CAST(Id AS VARCHAR(4)),4) FROM [Table A]


5

Funziona per stringhe, numeri interi e numerici:

SELECT CONCAT(REPLICATE('0', 4 - LEN(id)), id)

Dove 4si desidera la lunghezza. Funziona con numeri con più di 4 cifre, restituisce una stringa vuota su NULLvalore.


3

Se qualcuno è ancora interessato, ho trovato questo articolo su DATABASE.GUIDE:
Left Padding in SQL Server - 3 LPAD () equivalenti

In breve, ci sono 3 metodi menzionati in quell'articolo.
Supponiamo che il tuo id = 12 e che sia necessario che venga visualizzato come 0012.

Metodo 1: utilizzare la funzione RIGHT ()
Il primo metodo utilizza la funzione RIGHT () per restituire solo la parte più a destra della stringa, dopo aver aggiunto alcuni zeri iniziali.

SELECT RIGHT('00' + '12', 4);

Risultato:
0012

Metodo 2 - Usa una combinazione di RIGHT () e REPLICATE ()
Questo metodo è quasi lo stesso del metodo precedente, con l'unica differenza che sostituisco semplicemente i tre zeri con la funzione REPLICATE ():

SELECT RIGHT(REPLICATE('0', 2) + '12', 4);

Risultato:
0012

Metodo 3: utilizzare una combinazione di REPLACE () e STR ()
Questo metodo proviene da un'angolazione completamente diversa rispetto ai metodi precedenti:

SELECT REPLACE(STR('12', 4),' ','0');

Risultato:
0012

Dai un'occhiata all'articolo, c'è un'analisi più approfondita con esempi.


2

Questo è ciò che normalmente uso quando ho bisogno di riempire un valore.

SET @PaddedValue = REPLICATE('0', @Length - LEN(@OrigValue)) + CAST(@OrigValue as VARCHAR)

1

Ne avevo bisogno in una funzione sul server SQL e ho aggiustato un po 'la risposta di Patrick.

declare @dossierId int = 123
declare @padded_id varchar(7)


set @padded_id = REPLACE(
              SPACE(7 - LEN(@dossierId)) + convert(varchar(7), @dossierId), 
              SPACE(1),  
              '0') 

SELECT @dossierId as '@dossierId'
      ,SPACE(LEN(@dossierId)) + convert(varchar(7)
      ,@dossierId) as withSpaces
      ,@padded_id as '@padded_id'

1

Crea funzione:

    Create FUNCTION [dbo].[PadLeft]
      (
        @Text NVARCHAR(MAX) ,
        @Replace NVARCHAR(MAX) ,
        @Len INT
      )
RETURNS NVARCHAR(MAX)
AS
    BEGIN 


        DECLARE @var NVARCHAR(MAX) 

        SELECT @var = ISNULL(LTRIM(RTRIM(@Text)) , '')


        RETURN   RIGHT(REPLICATE(@Replace,@Len)+ @var, @Len)


    END

Esempio:

Select dbo.PadLeft('123456','0',8)

Solo un punto sugli standard, non mi preoccuperei del controllo IsNull, se il valore è null, la funzione dovrebbe comunque restituire null per quel valore poiché questo è il comportamento standard per le funzioni incorporate. Se convertiamo tutto in un valore non nullo, il chiamante non sarà più in grado di utilizzare operazioni logiche nulle che altrimenti potrebbero aspettarsi. (Null in molte delle mie tabelle significa "non specificato" e dovrebbe essere utilizzato un valore predefinito.SELECT @var = LTRIM(RTRIM(@Text))
Chris Schaller

1

Ho creato una funzione:

CREATE FUNCTION [dbo].[fnPadLeft](@int int, @Length tinyint)
RETURNS varchar(255) 
AS 
BEGIN
    DECLARE @strInt varchar(255)

    SET @strInt = CAST(@int as varchar(255))
    RETURN (REPLICATE('0', (@Length - LEN(@strInt))) + @strInt);
END;

Usa: seleziona dbo.fnPadLeft (123, 10)

Restituisce: 0000000123


0

Qualcosa di abbastanza conforme a ODBC, se necessario, potrebbe essere il seguente:

select ifnull(repeat('0', 5 - (floor(log10(FIELD_NAME)) + 1)), '')
        + cast (FIELD as varchar(10))
  from TABLE_NAME

Ciò si basa sul fatto che la quantità di cifre per un numero in base 10 può essere trovata dalla componente integrale del suo logaritmo. Da questo possiamo sottrarlo dalla larghezza di imbottitura desiderata. La ripetizione restituirà nullper valori inferiori a 1 quindi abbiamo bisogno ifnull.


0

La mia soluzione non è efficiente ma mi ha aiutato nella situazione in cui i valori (numeri di assegno bancario e numero di riferimento del bonifico) sono stati memorizzati come varchar in cui alcune voci avevano valori alfanumerici con loro e ho dovuto riempire se la lunghezza è inferiore a 6 caratteri.

Pensato per condividere se qualcuno si imbatte nella stessa situazione

declare @minlen int = 6
declare @str varchar(20)

set @str = '123'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 000123

set @str = '1234'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 001234

set @str = '123456'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456

set @str = '123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456789

set @str = '123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456789


set @str = 'NEFT 123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: NEFT 123456789

0

Un semplice esempio potrebbe essere

    DECLARE @number INTEGER
    DECLARE @length INTEGER
    DECLARE @char   NVARCHAR(10)
    SET @number = 1
    SET @length = 5
    SET @char = '0'

    SELECT FORMAT(@number, replicate(@char, @length))

0

Ho creato una funzione per fare questo, dove puoi specificare la lunghezza del carattere di output desiderata:

CREATE FUNCTION [dbo].[udfLeadingZero]
(
        @String VARCHAR(MAX)
,       @Len INT
)
RETURNS VARCHAR(MAX)
BEGIN
    SET @String = RIGHT(REPLICATE('0',@Len)+@String,@Len)
RETURN @String
END
GO

Risultati di esempio


-5

Il modo più efficiente è:

Select id, LEN(id)
From TableA
Order by 2,1 

The result :
id
----
1
2
12
123
1234

6
Come risponde questo alla domanda degli OP sul riempimento con zeri?
Filburt
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.