Как объединить числа и строки для форматирования чисел в T-SQL?

105

У меня есть следующая функция

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

но когда я попытался использовать его, я получил следующую ошибку: «Ошибка преобразования при преобразовании значения varchar 'x' в тип данных int». когда я использую следующий оператор выбора

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

Что я хочу сделать, так это то, что если ActualWeight не равен нулю, вернуть ActualWeight для «Фактического веса / DIMS» или использовать Actual_Dims_Lenght, Width и Height.

Если это DIMS, то я хочу отформатировать вывод как LenghtxWidhtxHeight (15x10x4). ActualWeight, Adcutal_Dims_Lenght, Width и Height - это целые (целые) значения, но вывод для «Фактический вес / DIMS» должен быть varchar (50).

Где я ошибаюсь?

благодарить

изменить: пользователь может выбрать только вес или DIMS на странице ASP.net, и если пользователь выбрал DIMS, они должны указать длину, ширину и высоту. В противном случае это вызовет ошибку на странице ASP.net. Стоит ли беспокоиться об этом на стороне sql?

разъем
источник

Ответы:

211

Пара небольших заметок:

  • Это «длина», а не «длина»
  • Псевдонимы таблиц в вашем запросе, вероятно, сделают его более читаемым

Теперь к проблеме ...

Вам необходимо явно преобразовать ваши параметры в VARCHAR, прежде чем пытаться объединить их. Когда SQL Server видит @my_int + 'X', он думает, что вы пытаетесь добавить число «X» к @my_int, а он не может этого сделать. Вместо этого попробуйте:

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))
Том Х
источник
6
Вы всегда должны указывать длину varchar: sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…
Eugene
Спасибо. Немного поздно, но я добавил параметры длины.
Tom H
53

Если вы используете SQL Server 2012+, вы можете использовать функцию CONCAT, в которой нам не нужно выполнять явное преобразование

SET @ActualWeightDIMS = Concat(@Actual_Dims_Lenght, 'x', @Actual_Dims_Width, 'x' 
                        , @Actual_Dims_Height) 
P ரதீப்
источник
Я встречал некоторые утверждения, которые работают CONCAT()быстрее, чем CAST(). Были бы полезны надежные источники исследований производительности.
Codes with Hammer
Я бы не удивился, если бы это можно было измерить в тесте, но я был бы очень удивлен, если бы это повлияло на обычные запросы. Чтобы заглушить нормальное время работы, потребуется огромное количество повязок.
SilverbackNet
8

Измените это:

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

К этому:

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

Измените это:

SET @ActualWeightDIMS = @ActualWeight;

К этому:

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

Вам нужно использовать CAST. Узнайте все о CAST и CONVERT здесь , потому что типы данных важны!

Эрик
источник
6
select 'abcd' + ltrim(str(1)) + ltrim(str(2))
Сачин Т. Савант
источник
7
Я не понимаю, как это решает вопрос.
Codes with Hammer
4

Вы должны преобразовать свои целые числа как строку при попытке объединить их в varchar.

т.е.

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

В SQL Server 2008 вы можете использовать STRфункцию:

   SELECT  @ActualWeightDIMS = STR(@Actual_Dims_Lenght) 
                              + 'x' + STR(@Actual_Dims_Width) 
                              + 'x' + STR(@Actual_Dims_Height);
П. Кэмпбелл
источник
2
Функция STR по умолчанию дополняет число до 10 символов, поэтому добавляет множество пробелов. например STR(1)дает мне 9 пробелов, за которыми следует 1. CASTна самом деле работает лучше.
Tahir Hassan
2

Сначала преобразуйте целые числа в varchar!

Джон Сондерс
источник
Именно. Строка 'x' полностью забивает бессмысленные int decls; в UDF нет арифметики.
bvj
2

Вам нужно преобразовать числовые данные в строки, прежде чем выполнять конкатенацию строк, поэтому, например, используйте CAST(@Actual_Dims_Lenght AS VARCHAR)вместо просто @Actual_Dims_Lenght& c.

Алекс Мартелли
источник
2

Я попробовал следующий запрос, он работает для меня точно

 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
Рики Рэм
источник
1

Попробуйте преобразовать целые числа в varchar, прежде чем добавлять их в строку:

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))
Андомар
источник
1

Есть вероятность, что вы получите научное число при преобразовании целого числа в Str ... более безопасный способ -

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

Singhswat
источник