Como concatenar números e strings para formatar números em T-SQL?

105

Eu tenho a seguinte função

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

mas quando tentei usá-lo, recebi o seguinte erro "A conversão falhou ao converter o valor varchar 'x' para o tipo de dados int." quando eu uso a seguinte declaração select

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

O que eu quero fazer é se o ActualWeight não for nulo, retornar o ActualWeight para o "Peso real / DIMS" ou usar o Actual_Dims_Lenght, Width e Height.

Se for DIMS, quero formatar a saída como LenghtxWidhtxHeight (15x10x4). O ActualWeight, Adcutal_Dims_Lenght, Width e Height são todos valores int (integer), mas a saída para "Actual Weight / DIMS" deve ser varchar (50).

Onde eu estou entendendo errado?

obrigado

editar: O usuário só pode escolher Peso ou DIMS na página ASP.net e se o usuário selecionou DIMS, ele deve fornecer Comprimento, Largura e Altura. Caso contrário, ele lançará um erro na página ASP.net. Devo me preocupar com isso no lado do sql?

Jack
fonte

Respostas:

211

Algumas notas rápidas:

  • É "comprimento" e não "comprimento"
  • Os aliases de tabela em sua consulta provavelmente a tornariam muito mais legível

Agora no problema ...

Você precisa converter explicitamente seus parâmetros para VARCHAR antes de tentar concatená-los. Quando o SQL Server vê @my_int + 'X', ele pensa que você está tentando adicionar o número "X" a @my_int e não pode fazer isso. Em vez disso, tente:

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
fonte
6
Você deve sempre especificar o comprimento de um varchar: sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…
Eugene Ryabtsev
Obrigado. Um pouco tarde, mas adicionei os parâmetros de comprimento.
Tom H
53

Se você estiver usando o SQL Server 2012+, você pode usar a função CONCAT , na qual não temos que fazer nenhuma conversão explícita

SET @ActualWeightDIMS = Concat(@Actual_Dims_Lenght, 'x', @Actual_Dims_Width, 'x' 
                        , @Actual_Dims_Height) 
P ரதீப்
fonte
Eu encontrei algumas reivindicações com CONCAT()desempenho mais rápido do que CAST(). Fontes confiáveis ​​de estudos de desempenho seriam úteis.
Códigos com Martelo de
Eu não ficaria surpreso se fosse mensurável em um benchmark, mas ficaria muito surpreso se tivesse algum impacto em consultas normais. Você teria que ter um número enorme de moldes para abafar o tempo normal de operação.
SilverbackNet
8

Mude isso:

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

Para isso:

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

Mude isso:

SET @ActualWeightDIMS = @ActualWeight;

Para isso:

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

Você precisa usar CAST. Aprenda tudo sobre CAST e CONVERT aqui , porque os tipos de dados são importantes!

Eric
fonte
6
select 'abcd' + ltrim(str(1)) + ltrim(str(2))
Sachin T Sawant
fonte
7
Não entendo como isso aborda a questão.
Códigos com Martelo de
4

Você deve converter seus inteiros como string ao tentar concatená-los em um varchar.

ie

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

No SQL Server 2008, você pode usar a STRfunção:

   SELECT  @ActualWeightDIMS = STR(@Actual_Dims_Lenght) 
                              + 'x' + STR(@Actual_Dims_Width) 
                              + 'x' + STR(@Actual_Dims_Height);
p.campbell
fonte
2
A função STR, por padrão, preenche o número com 10 caracteres, adicionando muitos espaços. por exemplo, STR(1)dá-me 9 espaços seguidos de 1. CASTrealmente funciona melhor.
Tahir Hassan
2

Converta os inteiros para varchar primeiro!

John Saunders
fonte
Exatamente. A string 'x' martela completamente os decls internos inúteis; não há aritmética no UDF.
bvj
2

Você precisa CAST seus dados numéricos para strings antes de fazer a concatenação de strings, então, por exemplo, use em CAST(@Actual_Dims_Lenght AS VARCHAR)vez de apenas @Actual_Dims_Lenght, & c.

Alex Martelli
fonte
2

Eu tentei a consulta abaixo e funciona exatamente para mim

 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
fonte
1

Tente converter os ints em varchar, antes de adicioná-los a uma string:

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
fonte
1

Há chances de que você possa acabar com o número científico ao converter Inteiro em Str ... a maneira mais segura é

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

singhswat
fonte