Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Übergeben Sie eine Listenstruktur als Argument an eine gespeicherte Prozedur

Sie brauchen eine Möglichkeit, die Zeichenfolge in TSQL aufzuteilen und zu verarbeiten, es gibt viele Möglichkeiten, dies zu tun. Dieser Artikel behandelt die Vor- und Nachteile von fast jeder Methode:

"Arrays und Listen in SQL Server 2005 und höher, wenn Tabellenwertparameter dies nicht tun Cut it" von Erland Sommarskog

Sie müssen eine Split-Funktion erstellen. So kann eine Split-Funktion verwendet werden:

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

Ich bevorzuge den Zahlentabellen-Ansatz, um einen String in TSQL aufzuteilen aber es gibt zahlreiche Möglichkeiten, Zeichenfolgen in SQL Server aufzuteilen, siehe den vorherigen Link, der die Vor- und Nachteile der einzelnen erklärt.

Damit die Zahlentabellenmethode funktioniert, müssen Sie diese einmalige Zeittabelleneinrichtung durchführen, die eine Tabelle Numbers erstellt die Zeilen von 1 bis 10.000 enthält:

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)

Sobald die Numbers-Tabelle eingerichtet ist, erstellen Sie diese Split-Funktion:

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 

Sie können jetzt ganz einfach eine CSV-Zeichenfolge in eine Tabelle aufteilen und ihr beitreten. Um Ihre Aufgabe zu erfüllen, wenn Sie zwei Parameter übergeben können, einen von Schlüsseln und einen von Werten, dann erstellen Sie Ihre Prozedur wie folgt:

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

Probieren Sie es aus:

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

AUSGABE:

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

(4 row(s) affected)

oder wenn Sie ein Schlüsselwertpaar mit einem einzelnen Parameter übergeben möchten, verwenden Sie Folgendes:

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

Führen Sie es aus:

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

AUSGABE:

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

(3 row(s) affected)