Rellene una cadena con ceros a la izquierda para que tenga 3 caracteres en SQL Server 2008

398

Tengo una cadena de hasta 3 caracteres cuando se creó por primera vez en SQL Server 2008 R2.

Me gustaría rellenarlo con ceros a la izquierda, por lo que si su valor original era '1', el nuevo valor sería '001'. O si su valor original era '23', el nuevo valor es '023'. O si su valor original es '124', entonces el nuevo valor es el mismo que el valor original.

Estoy usando SQL Server 2008 R2. ¿Cómo haría esto usando T-SQL?

Sunil
fuente

Respuestas:

681

Si el campo ya es una cadena, esto funcionará

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

Si desea que los valores nulos se muestren como '000'

Puede ser un número entero, entonces usted querría

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

Como lo requiere la pregunta, esta respuesta solo funciona si la longitud <= 3, si desea algo más grande, necesita cambiar la constante de cadena y las dos constantes enteras al ancho necesario. p.ej'0000' and VARCHAR(4)),4

Hogan
fuente
8
Tenía un campo Char (6) que tenía un puñado de valores que tenían solo 2-3 caracteres de largo y lo anterior no me funcionó. Tuve que agregar un RTRIM alrededor del '000000' + ISNULL (FIELD, '') para que funcione.
DWiener
3
Hogan, sí, lo entendí, pero no importa cuánto tiempo no funcionó la cuerda, estoy un poco demasiado ocupado para entender por qué, pero lo esencial es que con mi campo CHAR (6) justo a la DERECHA ('000000 '+ ISNULL (campo,' '), 6) no funcionó pero RIGHT (RTRIM (' 000000 '+ ISNULL (campo,' ')), 6) sí.
DWiener
2
oh, entiendo, tenías espacios a la derecha de un número codificado como una cadena.
Hogan
3
@dwiener, obtuvo este comportamiento porque un carácter es un tipo de datos de longitud fija, por lo que en su caso char (6) significa 6 caracteres de longitud. Si su valor real es inferior a 6, se rellena con espacios en blanco a la derecha, por lo que la respuesta propuesta produciría un resultado exacto para un carácter (6).
Giannis Paraskevopoulos
2
@Hogan, sí, pero esta pregunta es el primer resultado de Google para "sql add primeros ceros", por lo que creo que sería útil para muchas personas (que no usan sqlserver, pero google esta pregunta) saber que en otras bases de datos puede Existe una función más conveniente lpad. Gracias de todos modos.
diralik
142

Aunque la pregunta era para SQL Server 2008 R2, en caso de que alguien esté leyendo esto con la versión 2012 y superior, desde entonces se hizo mucho más fácil con el uso de FORMAT .

Puede pasar una cadena de formato numérico estándar o una cadena de formato numérico personalizado como argumento de formato (gracias a Vadim Ovchinnikov por esta pista).

Para esta pregunta, por ejemplo, un código como

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

salidas

001
001
Géza
fuente
2
¿Qué sucede si el número de entrada es 111 u 11?
Hogan
66
Para 1 es 001, para 11 es 011 y para 111 es 111
Géza
2
Puede usar 'D3' en lugar de '00 # '.
Vadim Ovchinnikov
1
parece ser considerablemente más lento que la respuesta aceptada, pero es mucho más fácil si no funciona con grandes cantidades de datos
root
2
Aunque parezca ilógico, vale la pena señalar que FORMAT solo funciona con tipos numéricos y de fecha, no varchar.
strattonn
120

El método seguro:

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

Esto tiene la ventaja de devolver la cadena '***'para n <0 or n> 999, que es un indicador agradable y obvio de entrada fuera de los límites. Los otros métodos enumerados aquí fallarán en silencio al truncar la entrada a una subcadena de 3 caracteres.

Luego
fuente
10
¡Maldición, quien aterrice en esta página debería ayudar a que este flote a la cima!
MarioDS
1
Con éxito con este método. Cuando la expresión excede la longitud especificada, la cadena devuelve ** para la longitud especificada. para, por ejemplo, str (n, 10), cuando n = 1000000000, aparecerán estrellas (*).
Sin consolidar el
No sé cómo funciona esto, pero es increíble y simple.
RaRdEvA
1
Cuidado con este, las cadenas lo rompen (y el OP pidió "rellenar una cadena"). Obras: SELECT REPLACE(STR('1',3),' ','0')Saltos: SELECT REPLACE(STR('1A',3),' ','0'). Esto me quemó hoy cuando un usuario ingresó una letra en la cadena de entrada y no pude probar ese caso.
Jeff Mergler
@Unbound Así es como debe funcionar, el póster ya lo dice. Es mejor devolver *** que un valor truncado como lo hacen todas las otras propuestas, muestra que los parámetros estaban equivocados.
Marc Guillot
32

Aquí hay una técnica más general para el relleno izquierdo a cualquier ancho deseado:

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)

Sin embargo, si se trata de valores negativos y rellena con ceros a la izquierda, ni esta ni ninguna otra técnica sugerida funcionarán. Obtendrás algo parecido a esto:

00-123

[Probablemente no lo que querías]

Entonces ... tendrás que saltar algunos aros adicionales. Aquí hay un enfoque que formateará correctamente los números negativos:

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
         )

Se debe tener en cuenta que las convert()llamadas deben especificar una [n]varcharde longitud suficiente para contener el resultado convertido con truncamiento.

Nicholas Carey
fuente
2
@StenPetrov, gracias. Todo depende de lo que intentes lograr. De lo único que he aprendido a depender en las grandes bases de datos de producción del mundo real es la presencia de datos incorrectos de un tipo u otro. Y prefiero evitar las llamadas telefónicas a las 3 AM si es posible; ^)
Nicholas Carey
:) aún así, cuando entra esa llamada de 3AM, prefiero leer 1 línea simple que 10 complejas. Agregar variables empeora aún más las cosas, especialmente si otro miembro del equipo decidió calcularlas sobre la marcha y no verificó el @width no negativo ...
Sten Petrov
Esas variables agregadas son solo para generalización: puede codificar los valores. Para el forro único, puede crear una función escalar, luego tiene su forro único.
Gerard ONeill
30

Aquí hay una variante de la respuesta de Hogan que uso en SQL Server Express 2012:

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

En lugar de preocuparme si el campo es una cadena o no, lo hago CONCAT, ya que de todos modos generará una cadena. Además, si el campo puede ser un NULL, ISNULLpuede ser necesario usar para evitar que la función obtenga NULLresultados.

SELECT RIGHT(CONCAT('000', ISNULL(field,'')), 3)
jahu
fuente
1
Por lo que recuerdo, CONCAT simplemente ignora el valor si es nulo, por lo que el primero funciona bien.
Marie
Esta solución funcionaría independientemente de la len de Field
Sin consolidar el
23

Siempre he encontrado que el siguiente método es muy útil.

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

Use esta función que se adapta a cada situación.

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

Salida de muestra

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
fuente
Esta debería ser la respuesta aceptada porque funciona en números y cadenas . Y si no desea utilizar una función (pero por qué no), algo como esto también funciona: lo DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;que devuelve el primer ejemplo de Salar anterior. Gracias Salar
Jeff Mergler
Mi comentario anterior contenía un error tipográfico, debería leer: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;que regresa 0000002016en el primer ejemplo anterior.
Jeff Mergler
@JeffMergler: ¿cómo funciona esto en números y cadenas? Es una función que toma un parámetro entero. La pregunta era sobre cuerdas.
Hogan
5

Para aquellos que desean actualizar sus datos existentes aquí está la consulta:

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

Para enteros, puede usar la conversión implícita de int a varchar:

SELECT RIGHT(1000 + field, 3)
Konstantin
fuente
44
Sin embargo, eso fallará dado un valor suficientemente grande, además, para valores negativos, obtendrá ... resultados interesantes.
Nicholas Carey
3

Sé que es un boleto viejo, solo pensé en compartirlo.

Encontré este código buscando una solución. No estoy seguro si funciona en todas las versiones de MSSQL Tengo MSSQL 2016.

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

devuelve "0023" El 4 en la función STR es la longitud total, incluido el valor. Los ejemplos 4, 23 y 123 tendrán 4 en STR y se agregará la cantidad correcta de ceros. Puedes aumentarlo o disminuirlo. No es necesario obtener la longitud en el 23.

Editar: veo que es lo mismo que @Anon post.

Niel compra
fuente
3

Prueba esto con una longitud fija.

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

select REPLICATE('0', 5 - LEN(123)) + '123'
Dr.Stark
fuente
2

Tuve un problema similar con la columna entera como entrada cuando necesitaba una salida varchar (o cadena) de tamaño fijo. Por ejemplo, 1 a '01', 12 a '12'. Este código funciona:

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

Si la entrada también es una columna de varchar, puede evitar la parte de fundición.

usuario3183867
fuente
2

Para un enfoque más dinámico intente esto.

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

Escribí esto porque tenía requisitos para una longitud específica (9). Rellena la izquierda con @pattern SOLO cuando la entrada necesita relleno. Siempre debe devolver la longitud definida en @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

Devuelve 1234input

nicky
fuente
1

Simple es que

Me gusta:

DECLARE @DUENO BIGINT
SET @DUENO=5

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

Vine aquí específicamente para averiguar cómo podría convertir mi timezoneoffset en una cadena de zona horaria para convertir fechas a DATETIMEOFFSET en SQL Server 2008. Bruto, pero necesario.

Por lo tanto, necesito 1 método que haga frente a los números negativos y positivos, formateándolos a dos caracteres con un cero a la izquierda si es necesario. La respuesta de Anons me acercó, pero los valores negativos de zona horaria saldrían como0-5 lugar de los requeridos-05

Entonces, con un pequeño ajuste en su respuesta, esto funciona para todas las conversiones de hora de zona horaria

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'
rojo
fuente
-1

Creé esta función que atiende a bigint y un cero inicial u otro carácter único (máximo 20 caracteres devueltos) y permite una longitud de resultados menor que la longitud del número de entrada:

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
fuente