Comment concaténer des nombres et des chaînes pour formater des nombres dans T-SQL?

105

J'ai la fonction suivante

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

mais quand j'ai essayé de l'utiliser, j'ai eu l'erreur suivante "La conversion a échoué lors de la conversion de la valeur varchar 'x' en type de données int." quand j'utilise l'instruction select suivante

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

Ce que je veux faire, c'est si le ActualWeight n'est pas nul, puis renvoyer le ActualWeight pour le "Actual Weight / DIMS" ou bien utiliser Actual_Dims_Lenght, Width et Height.

Si c'est DIMS, je veux formater la sortie pour qu'elle soit LenghtxWidhtxHeight (15x10x4). ActualWeight, Adcutal_Dims_Lenght, Width et Height sont tous des int (integer) mais la sortie pour "Actual Weight / DIMS" doit être varchar (50).

Où est-ce que je me trompe?

remercier

modifier: L'utilisateur ne peut choisir que Poids ou DIMS sur la page ASP.net et si l'utilisateur a sélectionné DIMS, il doit alors fournir Longueur, Largeur et Hauteur. Sinon, cela générera une erreur sur la page ASP.net. Dois-je m'en soucier du côté SQL?

Jack
la source

Réponses:

211

Quelques notes rapides:

  • C'est "longueur" pas "longueur"
  • Les alias de table dans votre requête la rendraient probablement beaucoup plus lisible

Passons maintenant au problème ...

Vous devez convertir explicitement vos paramètres en VARCHAR avant d'essayer de les concaténer. Lorsque SQL Server voit @my_int + 'X', il pense que vous essayez d'ajouter le nombre «X» à @my_int et il ne peut pas le faire. Essayez plutôt:

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
la source
6
Vous devez toujours spécifier la longueur d'un varchar: sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…
Eugene Ryabtsev
Merci. Un peu tard, mais j'ai ajouté les paramètres de longueur.
Tom H
53

Si vous utilisez SQL Server 2012+, vous pouvez utiliser la fonction CONCAT dans laquelle nous n'avons pas à effectuer de conversion explicite

SET @ActualWeightDIMS = Concat(@Actual_Dims_Lenght, 'x', @Actual_Dims_Width, 'x' 
                        , @Actual_Dims_Height) 
P ரதீப்
la source
J'ai rencontré des réclamations qui CONCAT()fonctionnent plus rapidement que CAST(). Des sources fiables d'études de performance seraient utiles.
Codes avec Hammer
Je ne serais pas surpris si cela était mesurable dans un benchmark, mais je serais très surpris si cela avait un impact sur les requêtes normales. Il faudrait avoir un nombre énorme de moulages pour noyer le temps de fonctionnement normal.
SilverbackNet
8

Change ça:

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

Pour ça:

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

Change ça:

SET @ActualWeightDIMS = @ActualWeight;

Pour ça:

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

Vous devez utiliser CAST. Apprenez tout sur CAST et CONVERT ici , car les types de données sont importants!

Eric
la source
6
select 'abcd' + ltrim(str(1)) + ltrim(str(2))
Sachin T Sawant
la source
7
Je ne comprends pas comment cela répond à la question.
Codes avec Hammer
4

Vous devez convertir vos entiers sous forme de chaîne lorsque vous essayez de les concaténer dans un varchar.

c'est à dire

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

Dans SQL Server 2008, vous pouvez utiliser la STRfonction:

   SELECT  @ActualWeightDIMS = STR(@Actual_Dims_Lenght) 
                              + 'x' + STR(@Actual_Dims_Width) 
                              + 'x' + STR(@Actual_Dims_Height);
p.campbell
la source
2
La fonction STR par défaut remplit le nombre à 10 caractères, ce qui ajoute beaucoup d'espaces. par exemple STR(1)me donne 9 espaces suivis de 1. CASTfonctionne mieux.
Tahir Hassan
2

Convertissez d'abord les nombres entiers en varchar!

John Saunders
la source
Exactement. La chaîne 'x' martèle complètement les décls int inutiles; il n'y a pas d'arithmétique dans l'UDF.
bvj
2

Vous devez CAST vos données numériques en chaînes avant de faire la concaténation de chaînes, par exemple utilisez CAST(@Actual_Dims_Lenght AS VARCHAR)plutôt que juste @Actual_Dims_Lenght, etc.

Alex Martelli
la source
2

J'ai essayé la requête ci-dessous, cela fonctionne exactement pour moi

 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
la source
1

Essayez de convertir les entiers en varchar, avant de les ajouter à une chaîne:

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
la source
1

Il y a des chances que vous vous retrouviez avec un numéro scientifique lorsque vous convertissez Integer en Str ... une manière plus sûre est

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

singhswat
la source