Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Przekazywanie zmiennej do klauzuli IN w funkcji SQL?

Oto nieco wydajniejszy sposób dzielenia listy liczb całkowitych. Najpierw utwórz tabelę liczb, jeśli jeszcze jej nie masz. Spowoduje to utworzenie tabeli ze 100 000 unikalnych liczb całkowitych (możesz potrzebować mniej lub więcej):

;WITH x AS
(
   SELECT TOP (1000000) Number = ROW_NUMBER() OVER 
   (ORDER BY s1.[object_id])
   FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
   ORDER BY s1.[object_id]
)
SELECT Number INTO dbo.Numbers FROM x;

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(Number);

Następnie funkcja:

CREATE FUNCTION [dbo].[SplitInts_Numbers]
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN
   (
       SELECT Item = CONVERT(INT, SUBSTRING(@List, Number,
         CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number))
       FROM dbo.Numbers
       WHERE Number <= CONVERT(INT, LEN(@List))
         AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter
   );

Możesz porównać wydajność z podejściem iteracyjnym tutaj:

http://sqlfiddle.com/#!3/960d2/1

Aby uniknąć tabeli liczb, możesz również wypróbować wersję funkcji opartą na XML - jest bardziej kompaktowa, ale mniej wydajna:

CREATE FUNCTION [dbo].[SplitInts_XML]
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN ( SELECT Item = CONVERT(INT, Item) FROM ( 
     SELECT Item = x.i.value('(./text())[1]', 'int') FROM ( 
       SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') 
       + '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y
     WHERE Item IS NOT NULL
   );

W każdym razie, gdy masz już funkcję, możesz po prostu powiedzieć:

WHERE ID IN (SELECT Item FROM dbo.SplitInts_Numbers(@MyList, ','));


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 8078 bajtów na stronie danych 8060 B (SQL Server)?

  2. Różnica dwóch dat w serwerze sql

  3. Jak mogę pobrać listę identyfikatorów z tabeli SQL jako ciąg wartości oddzielonych przecinkami?

  4. Tworzenie kolumny wyliczanej w SQL Server 2008

  5. Suma uruchomiona SQL pogrupowana według daty