¿Cómo concatenar números y cadenas para formatear números en T-SQL?

105

Tengo la siguiente función

ALTER FUNCTION [dbo].[ActualWeightDIMS]
(
    -- Add the parameters for the function here
    @ActualWeight int,
    @Actual_Dims_Lenght int,
    @Actual_Dims_Width int,
    @Actual_Dims_Height int
)
RETURNS varchar(50)
AS
BEGIN

DECLARE @ActualWeightDIMS varchar(50);
--Actual Weight
     IF (@ActualWeight is not null) 
          SET @ActualWeightDIMS = @ActualWeight;
--Actual DIMS
     IF (@Actual_Dims_Lenght is not null) AND 
          (@Actual_Dims_Width is not null) AND (@Actual_Dims_Height is not null)
          SET @ActualWeightDIMS= @Actual_Dims_Lenght + 'x' + @Actual_Dims_Width + 'x' + @Actual_Dims_Height;


     RETURN(@ActualWeightDIMS);

END

pero cuando intenté usarlo, recibí el siguiente error "La conversión falló al convertir el valor varchar 'x' al tipo de datos int". cuando uso la siguiente declaración de selección

select 
 BA_Adjustment_Detail.ID_Number [ID_Number],
 BA_Adjustment_Detail.Submit_Date [Submit_Date],
 BA_Category.Category [category],
 BA_Type_Of_Request.Request [Type_Of_Request],
 dbo.ActualWeightDIMS(BA_Adjustment_Detail.ActualWeight,BA_Adjustment_Detail.Actual_Dims_Lenght,BA_Adjustment_Detail.Actual_Dims_Width,BA_Adjustment_Detail.Actual_Dims_Height) [Actual Weight/DIMS],
 BA_Adjustment_Detail.Notes [Notes],
 BA_Adjustment_Detail.UPSCustomerNo [UPSNo],
 BA_Adjustment_Detail.TrackingNo [AirbillNo],
 BA_Adjustment_Detail.StoreNo [StoreNo],
 BA_Adjustment_Detail.Download_Date [Download_Date],
 BA_Adjustment_Detail.Shipment_Date[ShipmentDate],
 BA_Adjustment_Detail.FranchiseNo [FranchiseNo],
 BA_Adjustment_Detail.CustomerNo [CustomerNo],
 BA_Adjustment_Detail.BillTo [BillTo],
 BA_Adjustment_Detail.Adjustment_Amount_Requested [Adjustment_Amount_Requested]
from BA_Adjustment_Detail
inner join BA_Category 
on BA_Category.ID = BA_Adjustment_Detail.CategoryID
inner join BA_Type_Of_Request
on BA_Type_Of_Request.ID = BA_Adjustment_Detail.TypeOfRequestID

Lo que quiero hacer es si ActualWeight no es nulo, entonces devuelva el ActualWeight para el "Actual Weight / DIMS" o de lo contrario utilice Actual_Dims_Lenght, Width y Height.

Si es DIMS, entonces quiero formatear la salida para que sea LenghtxWidhtxHeight (15x10x4). ActualWeight, Adcutal_Dims_Lenght, Width y Height son todos valores int (enteros) pero la salida para "Actual Weight / DIMS" debe ser varchar (50).

¿Dónde me equivoco?

gracias

editar: El usuario solo puede elegir Peso o DIMS en la página ASP.net y si el usuario seleccionó DIMS, entonces debe proporcionar Largo, Ancho y Alto. De lo contrario, arrojará un error en la página ASP.net. ¿Debo preocuparme por eso en el lado de SQL?

Jack
fuente

Respuestas:

211

Un par de notas rápidas:

  • Es "largo", no "largo"
  • Los alias de tabla en su consulta probablemente lo harían mucho más legible

Ahora sobre el problema ...

Necesita convertir explícitamente sus parámetros a VARCHAR antes de intentar concatenarlos. Cuando SQL Server ve @my_int + 'X', cree que está intentando agregar el número "X" a @my_int y no puede hacerlo. En su lugar, intente:

SET @ActualWeightDIMS =
     CAST(@Actual_Dims_Lenght AS VARCHAR(16)) + 'x' +
     CAST(@Actual_Dims_Width  AS VARCHAR(16)) + 'x' +
     CAST(@Actual_Dims_Height  AS VARCHAR(16))
Tom H
fuente
6
Siempre debe especificar la longitud de un varchar: sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…
Eugene Ryabtsev
Gracias. Un poco tarde, pero agregué los parámetros de longitud.
Tom H
53

Si está utilizando SQL Server 2012+ , puede usar la función CONCAT en la que no tenemos que hacer ninguna conversión explícita

SET @ActualWeightDIMS = Concat(@Actual_Dims_Lenght, 'x', @Actual_Dims_Width, 'x' 
                        , @Actual_Dims_Height) 
P ரதீப்
fuente
Me he encontrado con algunas afirmaciones que CONCAT()funcionan más rápido que CAST(). Sería útil contar con fuentes confiables de estudios de desempeño.
Códigos con Hammer
No me sorprendería que fuera medible en un punto de referencia, pero me sorprendería mucho que tuviera algún impacto en las consultas normales. Tendría que tener una enorme cantidad de yesos para ahogar el tiempo de operación normal.
SilverbackNet
8

Cambia esto:

SET @ActualWeightDIMS= @Actual_Dims_Lenght + 'x' + 
    @Actual_Dims_Width + 'x' + @Actual_Dims_Height;

A esto:

SET @ActualWeightDIMS= CAST(@Actual_Dims_Lenght as varchar(3)) + 'x' + 
    CAST(@Actual_Dims_Width as varchar(3)) + 'x' + 
    CAST(@Actual_Dims_Height as varchar(3));

Cambia esto:

SET @ActualWeightDIMS = @ActualWeight;

A esto:

SET @ActualWeightDIMS = CAST(@ActualWeight as varchar(50));

Necesita usar CAST. Aprenda todo sobre CAST y CONVERT aquí , ¡porque los tipos de datos son importantes!

Eric
fuente
6
select 'abcd' + ltrim(str(1)) + ltrim(str(2))
Sachin T Sawant
fuente
7
No entiendo cómo esto aborda la pregunta.
Códigos con Hammer
4

Debes convertir tus enteros como una cadena cuando intentes concatenarlos en un varchar.

es decir

 SELECT  @ActualWeightDIMS = CAST(@Actual_Dims_Lenght AS varchar(10)) 
                              + 'x' + 
                             CAST(@Actual_Dims_Width as varchar(10)) 
                             + 'x' + CAST(@Actual_Dims_Height as varchar(10));

En SQL Server 2008, puede utilizar la STRfunción:

   SELECT  @ActualWeightDIMS = STR(@Actual_Dims_Lenght) 
                              + 'x' + STR(@Actual_Dims_Width) 
                              + 'x' + STR(@Actual_Dims_Height);
p.campbell
fuente
2
La función STR por defecto rellena el número a 10 caracteres, por lo que agrega muchos espacios. por ejemplo, STR(1)me da 9 espacios seguidos de 1. CASTen realidad funciona mejor.
Tahir Hassan
2

¡Lanza los enteros a varchar primero!

John Saunders
fuente
Exactamente. La cadena 'x' martilla completamente las inútiles declives int; no hay aritmética en la UDF.
bvj
2

Necesita CAST sus datos numéricos a cadenas antes de hacer la concatenación de cadenas, por ejemplo, use en CAST(@Actual_Dims_Lenght AS VARCHAR)lugar de solo @Actual_Dims_Lenght, & c.

Alex Martelli
fuente
2

Probé la siguiente consulta, funciona exactamente para mí

 with cte as(

   select ROW_NUMBER() over (order by repairid) as'RN', [RepairProductId] from [Ws_RepairList]
  )
  update CTE set [RepairProductId]= ISNULL([RepairProductId]+convert(nvarchar(10),RN),0) from cte
RickyRam
fuente
1

Intente convertir los ints en varchar, antes de agregarlos a una cadena:

SET @ActualWeightDIMS = cast(@Actual_Dims_Lenght as varchar(8)) + 
   'x' + cast(@Actual_Dims_Width as varchar(8)) + 
   'x' + cast(@Actual_Dims_Height as varhcar(8))
Andomar
fuente
1

Hay posibilidades de que termines con un Número científico cuando conviertas Integer en Str ... una forma más segura es

SET @ActualWeightDIMS = STR(@Actual_Dims_Width); OR Select STR(@Actual_Dims_Width) + str(@Actual_Dims_Width)

singhswat
fuente