Formattazione di numeri riempiendo con zeri iniziali in SQL Server


119

Abbiamo una vecchia tabella SQL che è stata utilizzata da SQL Server 2000 per quasi 10 anni.

In esso, i nostri numeri di badge dei dipendenti sono memorizzati char(6)da 000001a 999999.

Sto scrivendo un'applicazione web in questo momento e ho bisogno di memorizzare i numeri dei badge dei dipendenti.

Nella mia nuova tabella, potrei prendere la scorciatoia e copiare la vecchia tabella, ma spero in un migliore trasferimento dei dati, dimensioni più piccole, ecc. Semplicemente memorizzando i intvalori da 1a 999999.

In C #, posso formattare rapidamente un intvalore per il numero di badge utilizzando

public static string GetBadgeString(int badgeNum) {
  return string.Format("{0:000000}", badgeNum);
  // alternate
  // return string.Format("{0:d6}", badgeNum);
}

Come modifico questa semplice query SQL per formattare anche il valore restituito?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Se EmployeeIDè 7135, questa query dovrebbe restituire 007135.


Poiché le 0s iniziali sono significative in questo campo, perché cambiarle in un INT?
Oded

2
SQL Server 2012 avrà finalmente una FORMATfunzione come C # :-)
marc_s

1
@Oden: i intvalori occupano molto meno spazio char(6)e ci saranno più di queste voci per parte prodotta. Efficienza.
jp2code

Stai ottimizzando prima di riscontrare un problema?
Oded

4
Vediamo, hai fino a un milione di numeri di badge e pensi di poter salvare (in base a DATALENGTH()) due byte ciascuno. Poiché la colonna potrebbe essere in un indice, potresti risparmiare più di 2 MB. E con altre colonne sommate, quei 2 byte potrebbero essere appena sufficienti per ridurre la lunghezza di una riga abbastanza da salvare una pagina 4KB per riga. Sarà ospitato su una piattaforma mobile o potresti concentrare la tua attenzione in un'area improduttiva?
HABO

Risposte:


172

Cambia il numero 6 in qualunque sia la tua lunghezza totale:

SELECT REPLICATE('0',6-LEN(EmployeeId)) + EmployeeId

Se la colonna è un INT, è possibile utilizzare RTRIM per convertirlo implicitamente in un VARCHAR

SELECT REPLICATE('0',6-LEN(RTRIM(EmployeeId))) + RTRIM(EmployeeId)

E il codice per rimuovere questi 0 e recuperare il numero "reale":

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)

1
+1 Mi hai persino mostrato come rimuovere gli 0! Fammi provare questo e lo contrassegnerò come una risposta.
jp2code

non è necessario il codice per rimuovere gli zeri, basta assegnare o convertire in un int e verranno rimossi automaticamente.
Jimbo

2
Funziona solo se il valore passato è una stringa, se passi un numero intero ottieni lo stesso valore che hai passato.
Mordy

2
Anche se il suo vecchio ... usare "+ convert (varchar, EmployeeID)" invece di "+ EmployeeID" dovrebbe risolvere il problema int
Krishna Sarma

3
è un buon modo a meno che il EmployeeId non sia maggiore di 6 cifre che causa il risultato NULL. La funzione di contatto è la risposta: SELECT CONCAT (REPLICATE ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Mahmoud Moravej

125

Basta usare la funzione FORMAT (funziona su SQL Server 2012 o più recente):

SELECT FORMAT(EmployeeID, '000000')
FROM dbo.RequestItems
WHERE ID=0 

Riferimento: http://msdn.microsoft.com/en-us/library/hh213505.aspx


1
Questa è una vecchia domanda, prima che SQL Server 2012 uscisse.
jp2code

19
Tuttavia, mi piacerebbe vedere questa bolla un po 'più vicino alla cima ora.
Dave Haynes

4
Nel caso qualcuno se lo stesse chiedendo. Formatnon conserva il tipo di dati ma converte implicitamente in nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph

2
In questo modo è la soluzione più semplice e IMHO la migliore.
Robert Lujo

Prestare attenzione a questa funzione se la si utilizza per set di dati di grandi dimensioni
amd

33

Puoi cambiare la tua procedura in questo modo

SELECT Right('000000' + CONVERT(NVARCHAR, EmployeeID), 6) AS EmpIDText, 
       EmployeeID
FROM dbo.RequestItems 
WHERE ID=0 

Tuttavia questo presuppone che il tuo EmployeeIDsia un valore numerico e questo codice cambia il risultato in una stringa, suggerisco di aggiungere nuovamente il valore numerico originale

EDIT Ovviamente non ho letto attentamente la domanda sopra. Dice che il campo è un char(6)quindi EmployeeID non è un valore numerico. Sebbene questa risposta abbia ancora un valore di per sé, non è la risposta corretta alla domanda precedente.


Questo è il modo più pulito per farlo, credo. Grazie
iheartcsharp

È '000000'davvero necessario ..? '0'funziona anche bene. È sicuro usare solo uno 0 ..?
shashwat

1
L'OP ha richiesto una stringa di 6 caratteri come risultato. In particolare, se EmployeeID è 7135, questa query dovrebbe restituire 007135 . L'uso di un solo '0' restituisce 07135no 007135. L'idea è di concatenare a una stringa di 6 caratteri composta da tutta 0la stringa EmployeedID convertita, quindi INIZIARE dal bordo destro prendere 6 caratteri. Qualunque sia la lunghezza dell'ID, il metodo sopra restituisce sempre una stringa con solo il numero di caratteri zero necessari per raggiungere la lunghezza di 6 caratteri
Steve

Potrebbero essere 5 zeri '00000'poiché EmployeeIDconterrà almeno una cifra. Ma la REPLICATE()funzione sembra più adatta, come nelle altre risposte
nosklo

26

Odiavo dover CONVERTIRE l'int, e questo sembra molto più semplice. Potrebbe anche funzionare meglio poiché c'è solo una conversione di stringa e una semplice aggiunta.

Selezionare RIGHT (1000000 + EmployeeId, 6) ...

Assicurati solo che "1000000" abbia almeno tanti zeri quante sono le dimensioni necessarie.


11

Sto postando tutto in un posto, tutto funziona per me per riempire con 4 zero iniziali :)

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

Questo copre tutte le opzioni necessarie. Grazie.
kyurthich

6

Un altro modo, solo per completezza.

DECLARE @empNumber INT = 7123
SELECT STUFF('000000', 6-LEN(@empNumber)+1, LEN(@empNumber), @empNumber)

Oppure, secondo la tua richiesta

SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
         AS EmployeeCode
FROM dbo.RequestItems
WHERE ID=0

@ jp2code - devi leggere cos'è StackOverflow - è modificato in modo collaborativo come un wiki - non è la tua domanda non appena l'hai pubblicato! Le cose che vengono comunemente eliminate sono eccessive "sciocchezze" come ringraziare in anticipo e scarsa grammatica / uso delle maiuscole.
Jamiec

5

Dalla versione 2012 in poi puoi usare

SELECT FORMAT(EmployeeID,'000000')
FROM dbo.RequestItems
WHERE ID=0

4

Il più pulito possibile e dare la possibilità di sostituire con variabili:

Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
WHERE ID=0

Se la EmployeeIDcolonna è definita come, intl'operatore + verrà considerato come un'addizione anziché come una concatenazione e quindi gli zeri andranno persi. L'utilizzo converteviterà questo problema.

Chiamare REPLICATE ('0', 6) per evitare di digitare '000000' è solo uno spreco ;-)
Mladen Mihajlovic

3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0

2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0

Ops. In realtà, questo mi ha dato 7135.0quando l'ho dato 7135.
jp2code

1

La soluzione funziona per i numeri con segno / negativo con zeri iniziali, per tutte le versioni di SQL:

DECLARE
    @n money = -3,
    @length tinyint = 15,
    @decimals tinyint = 0

SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')

1

Il più semplice è sempre il migliore:

Select EmployeeID*1 as EmployeeID 

-1

Nella mia versione di SQL non posso usare REPLICATE. Quindi ho fatto questo:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
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.