Jak połączyć liczby i ciągi, aby sformatować liczby w T-SQL?

105

Mam następującą funkcję

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

ale kiedy próbowałem go użyć, pojawił się następujący błąd: „Konwersja nie powiodła się podczas konwersji wartości varchar 'x' na typ danych int.” kiedy używam poniższej instrukcji 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

Chcę zrobić, jeśli ActualWeight nie jest zerowa, a następnie zwróć ActualWeight dla „Actual Weight / DIMS” lub użyj Actual_Dims_Lenght, Width i Height.

Jeśli jest to DIMS, chcę sformatować dane wyjściowe na LenghtxWidhtxHeight (15x10x4). ActualWeight, Adcutal_Dims_Lenght, Width i Height są wartościami int (integer), ale dane wyjściowe dla „Actual Weight / DIMS” powinny mieć wartość varchar (50).

Gdzie się mylę?

podziękować

edycja: użytkownik może wybrać tylko wagę lub wymiary na stronie ASP.net, a jeśli użytkownik wybrał DIMS, musi podać długość, szerokość i wysokość. W przeciwnym razie zgłosi błąd na stronie ASP.net. Czy powinienem się tym martwić po stronie sql?

Jacek
źródło

Odpowiedzi:

211

Kilka szybkich uwag:

  • To „długość”, a nie „długość”
  • Aliasy tabel w zapytaniu prawdopodobnie uczyniłyby je bardziej czytelnymi

Teraz przejdźmy do problemu ...

Musisz jawnie przekonwertować parametry na VARCHAR, zanim spróbujesz je połączyć. Kiedy SQL Server widzi @my_int + 'X', myśli, że próbujesz dodać liczbę „X” do @my_int i nie może tego zrobić. Zamiast tego spróbuj:

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.
źródło
6
Zawsze powinieneś określać długość varchar: sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…
Eugene Ryabtsev
Dzięki. Trochę późno, ale dodałem parametry długości.
Tom H
53

Jeśli używasz SQL Server 2012+ , możesz użyć funkcji CONCAT, w której nie musimy wykonywać żadnej jawnej konwersji

SET @ActualWeightDIMS = Concat(@Actual_Dims_Lenght, 'x', @Actual_Dims_Width, 'x' 
                        , @Actual_Dims_Height) 
P ரதீப்
źródło
Spotkałem się z pewnymi twierdzeniami, które działają CONCAT()szybciej niż CAST(). Przydatne byłyby wiarygodne źródła badań wydajności.
Kody z Hammerem
Nie zdziwiłbym się, gdyby było to mierzalne w benchmarku, ale byłbym bardzo zdziwiony, gdyby miał jakikolwiek wpływ na normalne zapytania. Musiałbyś mieć ogromną liczbę odlewów, aby zagłuszyć normalny czas pracy.
SilverbackNet
8

Zmień to:

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

Do tego:

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

Zmień to:

SET @ActualWeightDIMS = @ActualWeight;

Do tego:

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

Musisz użyć CAST. Dowiedz się wszystkiego o CAST i konwertować tutaj , ponieważ typy danych są ważne!

Eric
źródło
6
select 'abcd' + ltrim(str(1)) + ltrim(str(2))
Sachin T Sawant
źródło
7
Nie rozumiem, jak to odpowiada na pytanie.
Kody z Hammerem
4

Musisz rzutować swoje liczby całkowite jako łańcuchy, gdy próbujesz połączyć je w varchar.

to znaczy

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

W SQL Server 2008 możesz użyć STRfunkcji:

   SELECT  @ActualWeightDIMS = STR(@Actual_Dims_Lenght) 
                              + 'x' + STR(@Actual_Dims_Width) 
                              + 'x' + STR(@Actual_Dims_Height);
p.campbell
źródło
2
Funkcja STR domyślnie dopełnia liczbę do 10 znaków, więc dodaje mnóstwo spacji. np. STR(1)daje mi 9 spacji, po których następuje 1. CASTfaktycznie działa lepiej.
Tahir Hassan
2

Najpierw przerzuć liczby całkowite na varchar!

John Saunders
źródło
Dokładnie. Ciąg „x” całkowicie hamuje bezsensowne int decl; nie ma arytmetyki w UDF.
bvj
2

Musisz przerzucić dane liczbowe na ciągi, zanim wykonasz konkatenację ciągów, więc na przykład użyj CAST(@Actual_Dims_Lenght AS VARCHAR)zamiast po prostu @Actual_Dims_Lenght& c.

Alex Martelli
źródło
2

Wypróbowałem poniższe zapytanie, które działa dokładnie dla mnie

 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
źródło
1

Spróbuj rzutować ints na varchar, zanim dodasz je do łańcucha:

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
źródło
1

Są szanse, że możesz skończyć z liczbą naukową po przekonwertowaniu liczby całkowitej na str ... bezpieczniejszy sposób jest

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

singhswat
źródło