Füllen Sie eine Zeichenfolge mit führenden Nullen auf, damit sie in SQL Server 2008 3 Zeichen lang ist

398

Ich habe eine Zeichenfolge, die bis zu 3 Zeichen lang ist, wenn sie zum ersten Mal in SQL Server 2008 R2 erstellt wird.

Ich möchte es mit führenden Nullen auffüllen. Wenn also sein ursprünglicher Wert '1' wäre, wäre der neue Wert '001'. Oder wenn der ursprüngliche Wert '23' war, ist der neue Wert '023'. Oder wenn der ursprüngliche Wert '124' ist, entspricht der neue Wert dem ursprünglichen Wert.

Ich verwende SQL Server 2008 R2. Wie würde ich das mit T-SQL machen?

Sunil
quelle

Antworten:

681

Wenn das Feld bereits eine Zeichenfolge ist, funktioniert dies

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

Wenn Sie möchten, dass Nullen als '000' angezeigt werden

Es könnte eine ganze Zahl sein - dann würden Sie wollen

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

Wie in der Frage gefordert, funktioniert diese Antwort nur, wenn die Länge <= 3 ist. Wenn Sie etwas Größeres wünschen, müssen Sie die Zeichenfolgenkonstante und die beiden Ganzzahlkonstanten auf die erforderliche Breite ändern. z.B'0000' and VARCHAR(4)),4

Hogan
quelle
8
Ich hatte ein Char (6) -Feld, das eine Handvoll Werte hatte, die nur 2-3 Zeichen lang waren, und die oben genannten haben bei mir nicht funktioniert. Ich musste ein RTRIM um '000000' + ISNULL (FIELD, '') hinzufügen, damit es funktioniert.
DWiener
3
Hogan, ja, das habe ich verstanden, aber egal wie lange die Saite nicht funktioniert hat, ich bin etwas zu beschäftigt, um herauszufinden, warum, aber das Wesentliche ist, dass mein CHAR (6) -Feld gerade RIGHT ('000000) macht '+ ISNULL (Feld,' '), 6) hat nicht funktioniert, aber RIGHT (RTRIM (' 000000 '+ ISNULL (Feld,' ')), 6) hat funktioniert.
DWiener
2
Oh, ich verstehe, Sie hatten rechts von einer Zahl, die als Zeichenfolge codiert ist, Leerzeichen.
Hogan
3
@wwiener Sie haben dieses Verhalten erhalten, weil ein Zeichen ein Datentyp fester Länge ist. In Ihrem Fall bedeutet char (6) also 6 Zeichen lang. Wenn Ihr tatsächlicher Wert kleiner als 6 ist, wird er rechts mit Leerzeichen aufgefüllt, sodass die vorgeschlagene Antwort ein falsches Ergebnis für ein Zeichen (6) ergibt.
Giannis Paraskevopoulos
2
@Hogan, ja, aber diese Frage ist das Top-1-Google-Ergebnis für "SQL Add Leading Zero". Daher denke ich, dass es für viele Leute (die keinen SQL Server verwenden, aber diese Frage googeln) nützlich wäre, dies in anderen Datenbanken zu wissen existiert mehr bequeme Funktion lpad. Trotzdem danke.
Diralik
142

Obwohl die Frage für SQL Server 2008 R2 war, wurde sie durch die Verwendung von FORMAT viel einfacher, falls jemand dies mit Version 2012 und höher liest .

Sie können entweder eine Standardzeichenfolge im numerischen Format oder eine benutzerdefinierte Zeichenfolge im numerischen Format als Formatargument übergeben (danke Vadim Ovchinnikov für diesen Hinweis).

Für diese Frage zum Beispiel ein Code wie

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

Ausgänge

001
001
Géza
quelle
2
Was passiert, wenn die Eingangsnummer 111 oder 11 ist?
Hogan
6
Für 1 ist es 001, für 11 ist es 011 und für 111 ist es 111
Géza
2
Sie können 'D3' anstelle von '00 # 'verwenden.
Vadim Ovchinnikov
1
es scheint erheblich langsamer zu sein als die akzeptierte Antwort, aber sooo viel einfacher, wenn man nicht mit großen Datenmengen arbeitet
root
2
Obwohl es unlogisch erscheint, ist es erwähnenswert, dass FORMAT nur mit numerischen und Datumstypen funktioniert, nicht mit varchar.
Strattonn
120

Die sichere Methode:

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

Dies hat den Vorteil, dass die Zeichenfolge '***'für n <0 oder n> 999 zurückgegeben wird, was ein netter und offensichtlicher Indikator für die Eingabe außerhalb der Grenzen ist. Die anderen hier aufgeführten Methoden schlagen stillschweigend fehl, indem die Eingabe in eine dreistellige Teilzeichenfolge abgeschnitten wird.

Anon
quelle
10
Verdammt, wer auch immer auf dieser Seite landet, sollte diesem helfen, nach oben zu schweben!
MarioDS
1
Seien Sie vorsichtig mit dieser Methode. Wenn der Ausdruck die angegebene Länge überschreitet, gibt die Zeichenfolge ** für die angegebene Länge zurück. Wenn z. B. str (n, 10), wenn n = 1000000000 ist, werden Sterne (*) angezeigt.
Ungebunden am
Ich weiß nicht, wie das funktioniert, aber es ist erstaunlich und einfach.
RaRdEvA
1
Vorsichtig mit diesem, brechen Strings es (und das OP bat um "Auffüllen eines Strings"). Werke: SELECT REPLACE(STR('1',3),' ','0')Pausen : SELECT REPLACE(STR('1A',3),' ','0'). Dies hat mich heute verbrannt, als ein Benutzer einen Buchstaben in die Eingabezeichenfolge eingegeben hat und ich diesen Fall nicht testen konnte.
Jeff Mergler
@Unbound So soll es funktionieren, das Poster sagt es schon. Es ist besser, *** als einen abgeschnittenen Wert zurückzugeben, wie dies bei allen anderen Vorschlägen der Fall ist. Dies zeigt, dass die Parameter falsch waren.
Marc Guillot
32

Hier ist eine allgemeinere Technik zum Auffüllen der linken Seite auf eine beliebige gewünschte Breite:

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)

Wenn Sie jedoch mit negativen Werten arbeiten und mit führenden Nullen auffüllen, funktionieren weder diese noch andere vorgeschlagene Techniken. Sie erhalten etwas, das so aussieht:

00-123

[Wahrscheinlich nicht das, was du wolltest]

Also ... Sie müssen durch einige zusätzliche Rahmen springen. Hier ist ein Ansatz, mit dem negative Zahlen richtig formatiert werden:

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
         )

Man sollte beachten, dass die convert()Aufrufe eine [n]varcharausreichende Länge angeben sollten, um das konvertierte Ergebnis mit Kürzung zu halten.

Nicholas Carey
quelle
2
@StenPetrov, danke. Es hängt alles davon ab, was Sie erreichen wollen. Das einzige, worauf ich in großen, realen Produktionsdatenbanken angewiesen bin, ist das Vorhandensein von schlechten Daten der einen oder anderen Art. Und ich ziehe es vor, die 3-Uhr-Anrufe zu vermeiden, wenn ich kann; ^)
Nicholas Carey
:) Immer noch, wenn dieser 3-Uhr-Anruf eingeht, müsste ich lieber 1 einfache Zeile als 10 komplexe lesen. Das Hinzufügen von Variablen macht die Sache noch schlimmer, besonders wenn ein anderes Teammitglied beschlossen hat, sie im laufenden Betrieb zu berechnen und nicht nach nicht negativer @ Breite gesucht hat ...
Sten Petrov
Diese hinzugefügten Variablen dienen nur der Verallgemeinerung - Sie können die Werte hart codieren. Für den Einzeiler können Sie eine Skalarfunktion erstellen - dann haben Sie Ihren Einzeiler.
Gerard ONeill
30

Hier ist eine Variante von Hogans Antwort, die ich in SQL Server Express 2012 verwende:

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

Anstatt mir Sorgen zu machen, ob das Feld eine Zeichenfolge ist oder nicht, CONCATmache ich es einfach , da es sowieso eine Zeichenfolge ausgibt. Wenn das Feld ein Feld sein kann, ist möglicherweise eine NULLVerwendung ISNULLerforderlich, um zu vermeiden, dass die Funktion NULLErgebnisse erzielt.

SELECT RIGHT(CONCAT('000', ISNULL(field,'')), 3)
jahu
quelle
1
Soweit ich mich erinnere, ignoriert CONCAT den Wert nur, wenn er null ist, sodass der erste einwandfrei funktioniert.
Marie
Diese Lösung würde unabhängig von der Länge von Field
Unbound
23

Ich habe die folgende Methode immer als sehr hilfreich empfunden.

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

Verwenden Sie diese Funktion, die für jede Situation geeignet ist.

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

Beispielausgabe

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
quelle
Dies sollte die akzeptierte Antwort sein, da sie mit Zahlen und Zeichenfolgen funktioniert . Und wenn Sie eine Funktion nicht verwenden möchten (aber warum nicht), funktioniert so etwas auch: Dies DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;gibt Salars erstes Beispiel oben zurück. Danke Salar.
Jeff Mergler
Mein Kommentar oben enthielt einen Tippfehler, der lauten sollte: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;der 0000002016im ersten Beispiel oben zurückkehrt.
Jeff Mergler
@ JeffMergler - wie funktioniert das bei Zahlen und Strings? Es ist eine Funktion, die einen ganzzahligen Parameter akzeptiert. Die Frage betraf Saiten.
Hogan
5

Für diejenigen, die ihre vorhandenen Daten aktualisieren möchten, ist hier die Abfrage:

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

Für Ganzzahlen können Sie die implizite Konvertierung von int nach varchar verwenden:

SELECT RIGHT(1000 + field, 3)
Konstantin
quelle
4
Bei einem ausreichend großen Wert schlägt dies jedoch fehl. Bei negativen Werten erhalten Sie ... interessante Ergebnisse.
Nicholas Carey
3

Ich kenne das alte Ticket, von dem ich nur dachte, dass ich es teilen möchte.

Ich habe diesen Code gefunden und nach einer Lösung gesucht. Ich bin mir nicht sicher, ob es auf allen Versionen von MSSQL funktioniert. Ich habe MSSQL 2016.

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

gibt "0023" zurück. Die 4 in der STR-Funktion ist die Gesamtlänge einschließlich des Werts. Beispiel 4, 23 und 123 haben alle 4 in STR und die richtige Anzahl von Nullen wird hinzugefügt. Sie können es erhöhen oder verringern. Keine Notwendigkeit, die Länge auf dem 23 zu bekommen.

Bearbeiten: Ich sehe es das gleiche wie @Anon Post.

Niel kauft
quelle
2

Ich hatte ein ähnliches Problem mit der Ganzzahlspalte als Eingabe, als ich eine Varchar- (oder String-) Ausgabe mit fester Größe benötigte. Zum Beispiel 1 bis '01', 12 bis '12'. Dieser Code funktioniert:

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

Wenn die Eingabe auch eine Spalte von Varchar ist, können Sie das Gussteil vermeiden.

user3183867
quelle
2

Versuchen Sie dies für einen dynamischeren Ansatz.

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

Versuchen Sie dies mit fester Länge.

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

select REPLICATE('0', 5 - LEN(123)) + '123'
Dr.Stark
quelle
1

Schrieb dies, weil ich Anforderungen für bis zu einer bestimmten Länge hatte (9). Füllt die linke Seite NUR mit dem @ Muster auf, wenn die Eingabe aufgefüllt werden muss. Sollte immer die in @pattern definierte Länge zurückgeben.

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

Gibt 1234input zurück

Nicky
quelle
1

Einfach ist das

Mögen:

DECLARE @DUENO BIGINT
SET @DUENO=5

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

Ich bin speziell hierher gekommen, um herauszufinden, wie ich meinen Zeitzonenversatz in eine Zeitzonenzeichenfolge konvertieren kann, um Datumsangaben in SQL Server 2008 in DATETIMEOFFSET zu konvertieren. Brutto, aber notwendig.

Ich brauche also eine Methode, die negative und positive Zahlen verarbeitet und sie bei Bedarf auf zwei Zeichen mit einer führenden Null formatiert. Anons Antwort brachte mich in die Nähe, aber negative Zeitzonenwerte würden 0-5eher als die erforderlichen herauskommen-05

Mit ein wenig Optimierung seiner Antwort funktioniert dies für alle Zeitzonen-Stunden-Konvertierungen

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'
rot
quelle
-1

Ich habe diese Funktion erstellt, die Bigint und eine führende Null oder ein anderes einzelnes Zeichen (maximal 20 zurückgegebene Zeichen) berücksichtigt und eine Länge von Ergebnissen zulässt, die kleiner als die Länge der eingegebenen Nummer ist:

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
quelle