2010-10-29 2 views
1

comment puis-je boucle à travers une variable séparées par des virgules à l'aide tsql dans une procédure stockéeboucle T-SQL dans une procédure stockée

Ainsi par exemple ma liste ressemblerait à ceci

"1,2,3,4,5,6,7,8,9,10" 

et je boucle pensé cette liste et fait une certaine table nécessaire insérer sur la base de cette liste

+1

Si vous utilisez SQL Server 2008 et au-dessus, vous devriez regarder dans l'utilisation des paramètres de valeur de table au lieu de tricherie de valeur séparée par des virgules. – Oded

+0

Est-ce que l'une des réponses données vous a donné une solution? –

Répondre

2

Vous pourriez le faire de deux façons, mais si ce serait une liste d'ID, il pourrait être fait comme ça aussi. Cela changerait un peu le format de votre liste.

UPDATE table 
SET column = value 
WHERE ID in ('1','2','3','4','5','6','7','8','9','10') 

Vous pouvez faire une boucle et

DECLARE @List CHAR(100) 
DECLARE @ListItem int 
DECLARE @Pos int 
SET @List = '1,2,3,4,5,6,7,8,9,10' 
WHILE LEN(@List) > 0 
BEGIN 
    --Pull Item Frim List 
    SET @Pos = CHARINDEX(',', @List) 
    IF @Pos = 0 
     BEGIN 
      SET @ListItem = @List 
     END 
    ELSE 
     BEGIN 
      SET @ListItem = SUBSTRING(@List, 1, @Pos - 1) 
     END 

    UPDATE table 
    SET column = value 
    WHERE ID = @ListItem 

    --Remove Item Frim List 
    IF @Pos = 0 
     BEGIN 
       SET @List = '' 
     END 
    ELSE 
     BEGIN 
       SET @List = SUBSTRING(@List, @Pos + 1, LEN(@List) - @Pos) 
     END 
END 
+0

Dieu je déteste TSQL .. mais merci ça a fait l'affaire –

1

Je vais essayer d'éviter les boucles et insérer les lignes directement à partir de votre liste par des virgules.

Utilisez un paramètre de valeurs de table (nouveau dans SQl Server 2008). Mis en place en créant le type de paramètre réel de la table:

CREATE TYPE IntTableType AS TABLE (ID INTEGER PRIMARY KEY) 

Votre procédure serait alors:

Create Procedure up_TEST 
    @Ids IntTableType READONLY 
AS 

SELECT * 
    FROM ATable a 
    WHERE a.Id IN (SELECT ID FROM @Ids) 

RETURN 0 
GO 

si vous ne pouvez pas utiliser les paramètres de valeur de table, voir: "Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog, alors il y a plusieurs façons de diviser une chaîne dans SQL Server. Cet article couvre les PROs et CONs de presque toutes les méthodes. en général, vous devez créer une fonction de séparation. Voici comment une fonction split peut être utilisé pour insérer des lignes:

INSERT INTO YourTableA (colA) 
    SELECT 
     b.col1 
     FROM dbo.yourSplitFunction(@Parameter) b 

I prefer the number table approach to split a string in TSQL mais il existe de nombreuses façons de diviser les chaînes dans SQL Server, voir le lien précédent, ce qui explique les avantages et les inconvénients de chacun.

Pour la méthode de table de nombres au travail, vous devez faire une configuration de table de temps, ce qui va créer une table Numbers qui contient des lignes de 1 à 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) 

Une fois la table des numéros est mis en place , créez cette fonction split:

CREATE FUNCTION [dbo].[FN_ListToTable] 
(
    @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 not return empty rows 
    ---------------- 
    SELECT 
     ListValue 
     FROM (SELECT 
        LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue 
        FROM (
          SELECT @SplitOn + @List + @SplitOn AS List2 
         ) AS dt 
         INNER JOIN Numbers n ON n.Number < LEN(dt.List2) 
        WHERE SUBSTRING(List2, number, 1) = @SplitOn 
      ) dt2 
     WHERE ListValue IS NOT NULL AND ListValue!='' 

); 
GO 

Vous pouvez maintenant facilement découper une chaîne CSV dans une table et se joindre à elle:

Create Procedure up_TEST 
@Ids VARCHAR(MAX) 
AS 
SELECT * FROM ATable a 
WHERE a.Id IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids)) 
GO 

ou insérer des lignes de ce:

Create Procedure up_TEST 
@Ids VARCHAR(MAX) 
,@OtherValue varchar(5) 
AS 
INSERT INTO YourTableA 
     (colA, colB, colC) 
    SELECT 
     ListValue, @OtherValue, GETDATE() 
     FROM dbo.FN_ListToTable(',',@Ids) 
GO