Formatando números preenchendo com zeros à esquerda no SQL Server

119

Temos uma tabela SQL antiga que foi usada pelo SQL Server 2000 por quase 10 anos.

Nele, nossos números de crachá de funcionário são armazenados char(6)de 000001a 999999.

Estou escrevendo um aplicativo da web agora e preciso armazenar os números dos crachás dos funcionários.

Na minha nova tabela, eu poderia pegar o atalho e copiar a tabela antiga, mas estou esperando por uma transferência de dados melhor, tamanho menor, etc, simplesmente armazenando os intvalores de 1a 999999.

Em C #, posso formatar rapidamente um intvalor para o número do emblema usando

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

Como eu modificaria essa consulta SQL simples para formatar o valor retornado também?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Se EmployeeIDfor 7135, esta consulta deve retornar 007135.

jp2code
fonte
Visto que os 0s iniciais são significativos para este campo, por que alterá-lo para um INT?
Oded
2
O SQL Server 2012 finalmente terá uma FORMATfunção como C # :-)
marc_s
1
@Oden: Os intvalores ocupam muito menos espaço do que isso char(6), e haverá várias dessas entradas por peça fabricada. Eficiência.
jp2code
Você está otimizando antes de ter um problema?
Oded
4
Vamos ver, você tem até um milhão de números de crachá e calcula que pode salvar (de acordo com DATALENGTH()) dois bytes cada. Como a coluna pode estar em um índice, você pode economizar mais de 2 MB. E com outras colunas somadas, esses 2 bytes podem ser apenas o suficiente para reduzir o comprimento de uma linha o suficiente para salvar uma página de 4 KB por linha. Será hospedado em uma plataforma móvel ou você pode estar focando sua atenção em uma área improdutiva?
HABO

Respostas:

172

Altere o número 6 para qualquer que seja o seu comprimento total:

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

Se a coluna for um INT, você pode usar RTRIM para convertê-la implicitamente em um VARCHAR

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

E o código para remover esses 0s e recuperar o número 'real':

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)
Vince Pergolizzi
fonte
1
+1 Você até me mostrou como remover os 0s! Deixe-me testar isso e marcarei como uma resposta.
jp2code
você não precisa de código para remover os zeros, apenas atribua ou converta para um int e eles serão removidos automaticamente.
Jimbo
2
Isso só funciona se o valor passado for uma string, se você passar um número inteiro, obterá o mesmo valor que passou.
Mordy
2
Embora seja antigo ... usar "+ convert (varchar, EmployeeID)" em vez de "+ EmployeeID" deve resolver o problema
interno
3
é uma boa maneira, a menos que EmployeeId seja maior que 6 dígitos, o que causa um resultado NULL. A função de contato é a resposta: SELECT CONCAT (REPLICATE ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Mahmoud Moravej
125

Basta usar a função FORMAT (funciona no SQL Server 2012 ou mais recente):

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

Referência: http://msdn.microsoft.com/en-us/library/hh213505.aspx

EdMorte
fonte
1
Esta é uma questão antiga - antes do SQL Server 2012 ser lançado.
jp2code 01 de
19
Mesmo assim, gostaria de ver essa bolha um pouco mais perto do topo agora.
Dave Haynes
4
Apenas no caso de alguém estar se perguntando. Formatnão preserva o tipo de dados, mas converte implicitamente em nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph
2
Desta forma é a solução mais simples e IMHO a melhor.
Robert Lujo
Esteja ciente dessa função se você estiver usando-a para grandes conjuntos de dados
amd
33

Você pode alterar o seu procedimento desta forma

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

No entanto, isso assume que seu EmployeeIDé um valor numérico e este código altera o resultado para uma string, sugiro adicionar novamente o valor numérico original

EDITAR Claro que não li com atenção a pergunta acima. Diz que o campo é um char(6)EmployeeID não é um valor numérico. Embora essa resposta ainda tenha um valor per se, não é a resposta correta para a pergunta acima.

Steve
fonte
Esta é a maneira mais limpa de fazer isso, eu acho. Obrigado
iheartcsharp
Isso é '000000'realmente necessário ..? '0'também funcionando bem. É seguro usar apenas um 0 ..?
shashwat
1
O OP solicitou uma string de comprimento de 6 caracteres como resultado. Especificamente se EmployeeID for 7135, esta consulta deve retornar 007135 . Usar apenas um '0' retorna 07135não 007135. A ideia toda é concatenar em uma string de 6 caracteres composta de toda 0a string convertida EmployeedID e, em seguida, INICIAR da borda direita pegar 6 caracteres. Qualquer que seja o comprimento do ID, o método acima retorna sempre uma string com apenas o número zero de caracteres necessário para atingir o comprimento de 6 caracteres
Steve
Pode ser 5 zeros, '00000'pois o EmployeeIDconterá pelo menos um dígito. Mas a REPLICATE()função parece mais adequada, como nas outras respostas
nosklo
26

Odiava ter que CONVERTER o int, e isso parece muito mais simples. Pode até ter um desempenho melhor, pois há apenas uma conversão de string e adição simples.

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

Apenas certifique-se de que "1000000" tenha pelo menos tantos zeros quanto o tamanho necessário.

JeffSahol
fonte
11

Estou postando tudo em um só lugar, tudo funciona para mim preencher com 4 zero à esquerda :)

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')
Raj kumar
fonte
Isso cobre todas as opções necessárias. Obrigado.
Kyurthich
6

Outra forma, apenas para completar.

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

Ou, de acordo com sua consulta

SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
         AS EmployeeCode
FROM dbo.RequestItems
WHERE ID=0
Jamiec
fonte
@ jp2code - você precisa ler sobre o que é StackOverflow - é editado de forma colaborativa como um wiki - não é sua pergunta assim que você postar! Coisas que são comumente editadas são excessivas "bobagens", como agradecimento antecipado e gramática / capitalização inadequadas.
Jamiec
5

A partir da versão 2012, você pode usar

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

Tão limpo quanto possível e com escopo de substituição por variáveis:

Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
WHERE ID=0
Divanshu
fonte
Se a EmployeeIDcoluna for definida como int, o operador + será tratado como adição em vez de concatenação e, portanto, os zeros serão perdidos. O uso convertevitará esse problema.
Chamar REPLICATE ('0', 6) para evitar digitar '000000' é um desperdício ;-)
Mladen Mihajlovic
3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0
Jimbo
fonte
2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0
user1227804
fonte
Opa. Na verdade, isso me deu 7135.0quando eu dei 7135.
jp2code
1

A solução funciona para números assinados / negativos com zeros à esquerda, para todas as versões Sql:

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

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

O mais simples é sempre o melhor:

Select EmployeeID*1 as EmployeeID 
Michal
fonte
-1

Na minha versão do SQL, não consigo usar REPLICATE. ENTÃO eu fiz isso:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
Zlato010
fonte