2010-12-17 12 views
9

Mijam listę int (oddzielonych przecinkiem)t-sql Konwertuj oddzielone przecinkami ciąg na int, bez użycia funkcji utworzonej przez użytkownika

tj. 1, 2, 3, 4

do mojego sp. Ale dostaję błąd, ponieważ lista jest ciągiem znaków i porównuję do pola int. Czy istnieje sposób przekonwertowania listy na int, bez korzystania z funkcji utworzonej przez użytkownika?

Uwaga: EmployeeID jest INT

declare @intArray varchar(200) 

SELECT * 
FROM tbl_Employee 
WHERE employeeID IN (@intArray) 

Błąd "nie można przekonwertować typu varchar do int"

+0

Jaką wersję programu SQL Server? Czy jesteś w stanie zmienić kod, który wywołuje twój sp? –

+0

@Damien SQL Server 2005. Tak, jestem w stanie zmienić kod wywołujący moje sp. – Kukoy

+1

szczurów. W 2008 r. Sugerowałbym zmianę na używanie parametrów wycenianych w tabeli. –

Odpowiedz

8

Nie chcesz rzucić tej listy na int, ale na listę int.

Nie ma operatora ani funkcji przesyłania, ale można użyć dynamicznego SQL, aby ominąć to.

zasadzie piszesz

EXECUTE('SELECT * FROM tbl_Employee WHERE employeeID IN ('[email protected]+')') 

Bądź świadomy ataków SQL injection chociaż!

+3

To dobry sposób na robienie tego, co chce OP. Należy pamiętać, że wraz ze wzrostem listy pracowników i "ID" fraza "IN" staje się coraz bardziej nieefektywna. W 2005/2008 preferowane jest 'EXISTS'. Dynamiczny SQL nie może być buforowany, więc wykonanie nigdy nie staje się szybsze, niż w przypadku innych instrukcji. – Brad

+0

@Brad: Instrukcje dynamiczne są buforowane tak samo dobrze, jak każde inne. Dopóki nie zmienisz tekstu zapytania, buforowany plan jest pobierany. Oczywiście, różne listy ID byłyby tutaj problemem, gdyby zapytanie było wykonywane bardzo często. EXISTS wymaga pewnej (tymczasowej) tabeli do przechowywania wyszukanych identyfikatorów. Jeśli masz tylko listę (i.mi. z aplikacji internetowej, w której użytkownik może wybrać określonych pracowników za pomocą pól wyboru), IN jest nadal najlepszą opcją. – TToni

+0

Zgadzam się, że 'EXISTS' nie jest tutaj praktycznie praktyczny, chciałem tylko wskazać, że jest * preferowane * jeśli tabela lub lista' IN' jest duża. Dobrze jest się nauczyć, że SQL wykonuje plany pamięci podręcznej dla dynamicznego SQL (dla każdej zmiany). Ale myślę, że to buforowanie jest w dużej mierze możliwe do zniesienia, ponieważ zapytanie często się zmienia. Jeśli nie, dlaczego zdecydujesz się użyć dynamicznego SQL? – Brad

4

próbujesz konwertować nie tylko string do int, ale kilkaint ów w jeden. Czy spodziewasz się, że Twój SELECT zwróci wszystkich pracowników i ID wymienionych w tablicy?

Zdaję sobie sprawę, że chciałeś to zrobić, bez funkcji. Jednak tak właśnie teraz to robię i działa świetnie. Weź to, co chcesz, z mojej odpowiedzi.

Ten kod używa pętli while, która prawdopodobnie zostanie poprawiona na rekurencyjne CTE, jeśli używasz SQL 2005/2008. Możesz użyć wyjścia funkcji jako tabeli, którą możesz INNER JOIN, co pozwoli ci bardzo szybko filtrować.

/* 
************************************************************************************************************************ 
    Name:   ConvertDelimitedListIntoTable 
    Description: Converts a list of delimited values into a table for use like a dynamic IN statment 

    Modification History 
    Date  Author   Description 
    ========== ============ ==================================== 
    2009-01-31 B. Williams  Initial Creation 

************************************************************************************************************************ 
*/ 
ALTER FUNCTION [dbo].[ConvertDelimitedListIntoTable] (
    @list NVARCHAR(MAX) ,@delimiter CHAR(1)) 
RETURNS @table TABLE ( 
    item VARCHAR(255) NOT NULL) 
AS 
    BEGIN 
     DECLARE @pos INT ,@nextpos INT ,@valuelen INT 

     SELECT @pos = 0 ,@nextpos = 1 

     WHILE @nextpos > 0 
      BEGIN 
       SELECT @nextpos = CHARINDEX(@delimiter,@list,@pos + 1) 
       SELECT @valuelen = CASE WHEN @nextpos > 0 THEN @nextpos 
             ELSE LEN(@list) + 1 
            END - @pos - 1 
       INSERT @table (item) 
       VALUES (CONVERT(INT,SUBSTRING(@list,@pos + 1,@valuelen))) 
       SELECT @pos = @nextpos 

      END 

     DELETE FROM @table 
     WHERE item = '' 

     RETURN 
    END 

Zastosowanie:

DECLARE @intArray varchar(200) 

SELECT * 
FROM tbl_Employee e 
     INNER JOIN dbo.ConvertDelimitedListIntoTable(@intArray,',') arr 
       ON e.EmployeeID = arr.Item 

Nie mogą być również szybki sposób zrobić to z tally tabeli.

+0

To świetnie, dziękuję! –

+0

Nie udało się wykonać pierwszego działania rozwiązania w procedurze przechowywanej. Dzięki za to! –

Powiązane problemy