sql >> Database >  >> RDS >> Sqlserver

Geef een lijststructuur door als argument aan een opgeslagen procedure

Je hebt een manier nodig om de string in TSQL te splitsen en te verwerken, er zijn veel manieren om dit te doen. Dit artikel behandelt de voor- en nadelen van zowat elke methode:

"Arrays en lijsten in SQL Server 2005 en daarna, wanneer tabelwaardeparameters dat niet doen Cut it" door Erland Sommarskog

U moet een splitfunctie maken. Zo kan een splitsingsfunctie worden gebruikt:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

Ik geef de voorkeur aan de getallentabelbenadering om een ​​string in TSQL te splitsen maar er zijn talloze manieren om strings in SQL Server te splitsen, zie de vorige link, waarin de voor- en nadelen van elk worden uitgelegd.

Om de Numbers Table-methode te laten werken, moet u deze eenmalige tijdtabelconfiguratie uitvoeren, waardoor een tabel Numbers wordt gemaakt die rijen van 1 tot 10.000 bevat:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

Zodra de Numbers-tabel is ingesteld, maakt u deze splitsfunctie:

CREATE FUNCTION [dbo].[FN_ListToTableRows]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(
    ----------------
    --SINGLE QUERY-- --this will return empty rows, and row numbers
    ----------------
    SELECT
        ROW_NUMBER() OVER(ORDER BY number) AS RowNumber
            ,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue
        FROM (
                 SELECT @SplitOn + @List + @SplitOn AS ListValue
             ) AS InnerQuery
            INNER JOIN Numbers n ON n.Number < LEN(InnerQuery.ListValue)
        WHERE SUBSTRING(ListValue, number, 1) = @SplitOn
);
GO 

U kunt nu eenvoudig een CSV-tekenreeks in een tabel splitsen en eraan deelnemen. Om uw taak te volbrengen, moet u twee parameters invoeren, een van de sleutels een van de waarden, en vervolgens uw procedure als volgt maken:

CREATE PROCEDURE StoredProcedureName
(
     @Params1  int
    ,@Array1   varchar(8000)
    ,@Params2  int
    ,@Array2   varchar(8000)
)
AS 

DECLARE @YourTable table (col1 int, col2 int)

INSERT INTO @YourTable
        (col1, col2)
    SELECT
        a1.ListValue, a2.ListValue
        FROM dbo.FN_ListToTableRows(',',@Array1)            a1
            INNER JOIN dbo.FN_ListToTableRows(',',@Array2)  a2 ON a1.RowNumber=a2.RowNumber

select * from @YourTable

GO

test het uit:

exec StoredProcedureName 17,'127,204,110,198',7,'162,170,163,170'

UITGANG:

(4 row(s) affected)
col1        col2
----------- -----------
127         162
204         170
110         163
198         170

(4 row(s) affected)

of als u een sleutelwaardepaar met één parameter wilt doorgeven, gebruik dan zoiets als dit:

CREATE PROCEDURE StoredProcedureName
(
     @KeyValueList  varchar(8000)
)
AS 

DECLARE @YourTable table (RowKey varchar(500), RowValue varchar(500))

INSERT INTO @YourTable
        (RowKey, RowValue)
    SELECT
        LEFT(y.ListValue,CHARINDEX(',',y.ListValue)-1),RIGHT(y.ListValue,LEN(y.ListValue)-CHARINDEX(',',y.ListValue))
        FROM dbo.FN_ListToTableRows(';',@KeyValueList) y

SELECT * FROM @YourTable

GO

voer het uit:

exec StoredProcedureName 'a,5;b,BBB;abc,xyz'

UITGANG:

RowKey  RowValue
------- -----------
a       5
b       BBB
abc     xyz

(3 row(s) affected)



  1. CSV versus MySQL-prestaties

  2. SQL commando niet juist afgesloten?

  3. Hoe de tafel in orakel te laten vallen

  4. Verbinding maken met 4D vanuit Java