sql >> Databasteknik >  >> RDS >> Sqlserver

Skicka en liststruktur som ett argument till en lagrad procedur

Du behöver ett sätt att dela och bearbeta strängen i TSQL, det finns många sätt att göra detta. Den här artikeln täcker fördelarna och nackdelarna med nästan alla metoder:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Klipp den" av Erland Sommarskog

Du måste skapa en delad funktion. Så här kan en delad funktion användas:

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

Jag föredrar taltabellmetoden för att dela en sträng i TSQL men det finns många sätt att dela strängar i SQL Server, se föregående länk, som förklarar fördelarna och nackdelarna med var och en.

För att Numbers Table-metoden ska fungera måste du göra denna engångstabellinställning, vilket skapar en tabell Numbers som innehåller rader från 1 till 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)

När tabellen Numbers har ställts in skapar du den här delade funktionen:

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 

Du kan nu enkelt dela upp en CSV-sträng i en tabell och gå med på den. För att utföra din uppgift, om du kan skicka in två parametrar, en av nycklar en av värden, skapa sedan din procedur så här:

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

testa det:

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

UTGÅNG:

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

(4 row(s) affected)

eller om du vill skicka in ett enstaka parameternyckelvärdespar använd något i stil med detta:

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

kör det:

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

UTGÅNG:

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

(3 row(s) affected)



  1. mysql_connect() misslyckas med tom varning

  2. index i sql server, internt arbete och struktur av index

  3. Beräknar avståndet mellan en gps-plats och postgis geografivärde med hjälp av en funktion?

  4. mysql för många index?