Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Passa una struttura di elenco come argomento a una stored procedure

Hai bisogno di un modo per dividere ed elaborare la stringa in TSQL, ci sono molti modi per farlo. Questo articolo copre i PRO ei CONTRO di quasi tutti i metodi:

"Array ed elenchi in SQL Server 2005 e versioni successive, quando i parametri del valore della tabella non lo fanno Taglialo" di Erland Sommarskog

Devi creare una funzione di divisione. Ecco come è possibile utilizzare una funzione di divisione:

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

Preferisco l'approccio della tabella dei numeri per dividere una stringa in TSQL ma ci sono molti modi per dividere le stringhe in SQL Server, vedi il link precedente, che spiega i PRO ei CONTRO di ciascuno.

Affinché il metodo della tabella dei numeri funzioni, devi eseguire questa configurazione dell'orario una tantum, che creerà una tabella Numbers che contiene righe da 1 a 10.000:

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)

Una volta impostata la tabella dei numeri, crea questa funzione di divisione:

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 

Ora puoi facilmente dividere una stringa CSV in una tabella e unirti ad essa. Per portare a termine il tuo compito, se puoi passare due parametri, uno di chiavi uno di valori, quindi crea la tua procedura in questo modo:

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

provalo:

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

USCITA:

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

(4 row(s) affected)

o se vuoi passare una coppia di valori chiave di un singolo parametro, usa qualcosa del genere:

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

eseguilo:

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

USCITA:

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

(3 row(s) affected)