web-dev-qa-db-fra.com

Procédure SQL Server déclarer une liste

Mon code SQL est assez simple. J'essaie de sélectionner des données d'une base de données comme celle-ci:

SELECT * FROM DBTable
WHERE id IN (1,2,5,7,10)

Je veux savoir comment déclarer la liste avant la sélection (dans une variable, une liste, un tableau ou quelque chose) et dans la sélection uniquement utiliser le nom de la variable, quelque chose comme ceci: 

VAR myList = "(1,2,5,7,10)"
SELECT * FROM DBTable
WHERE id IN myList
28
Alex Doro

Vous pouvez déclarer une variable en tant que table temporaire comme ceci:

declare @myList table (Id int)

Cela signifie que vous pouvez utiliser l'instruction insert pour la renseigner avec des valeurs:

insert into @myList values (1), (2), (5), (7), (10)

Ensuite, votre instruction select peut utiliser l’instruction in:

select * from DBTable
where id in (select Id from @myList)

Ou vous pouvez rejoindre la table temporaire comme ceci:

select *
from DBTable d
join @myList t on t.Id = d.Id

Et si vous faites souvent quelque chose comme cela, vous pouvez envisager de définir un type de table défini par l'utilisateur afin de pouvoir déclarer votre variable comme suit:

declare @myList dbo.MyTableType
49
Peter Monks

Cela n'est pas possible avec une requête normale car la clause in nécessite des valeurs distinctes et non une valeur unique contenant une liste séparée par des virgules. Une solution serait une requête dynamique

declare @myList varchar(100)
set @myList = '(1,2,5,7,10)'
exec('select * from DBTable where id IN ' + @myList)
8
juergen d

Si vous voulez entrer et appliquer une chaîne séparée par des virgules dans la requête, vous pouvez alors créer Function comme: 

create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
    returns @temptable TABLE (items varchar(MAX))       
    as       
    begin      
        declare @idx int       
        declare @slice varchar(8000)       

        select @idx = 1       
            if len(@String)<1 or @String is null  return       

        while @idx!= 0       
        begin       
            set @idx = charindex(@Delimiter,@String)       
            if @idx!=0       
                set @slice = left(@String,@idx - 1)       
            else       
                set @slice = @String       

            if(len(@slice)>0)  
                insert into @temptable(Items) values(@slice)       

            set @String = right(@String,len(@String) - @idx)       
            if len(@String) = 0 break       
        end   
    return 
    end;

Vous pouvez l'utiliser comme:

Declare @Values VARCHAR(MAX);

set @Values ='1,2,5,7,10';
Select * from DBTable
    Where id  in (select items from [dbo].[Split] (@Values, ',') )

Sinon, si vous n'avez pas de chaîne séparée par des virgules en entrée, vous pouvez essayer Table variable OR TableType ou Temp table comme: INSERT en utilisant LIST dans la procédure stockée

1
Pranav Singh

J'ai toujours trouvé plus facile d'inverser le test par rapport à la liste dans des situations comme celle-ci. Par exemple...

SELECT 
    field0, field1, field2 
FROM 
    my_table 
WHERE 
    ',' + @mysearchlist + ',' LIKE '%,' + CAST(field3 AS VARCHAR) + ',%' 

Cela signifie qu'il n'y a pas de méli-mélo compliqué requis pour les valeurs que vous recherchez.

Par exemple, si notre liste était ('1,2,3'), nous ajoutons une virgule au début et à la fin de notre liste comme suit: ',' + @mysearchlist + ','.

Nous procédons également de la même manière pour la valeur de champ recherchée et ajoutons des caractères génériques: '%,' + CAST(field3 AS VARCHAR) + ',%' (notez les caractères % et ,).

Enfin, nous testons les deux en utilisant l'opérateur LIKE: ',' + @mysearchlist + ',' LIKE '%,' + CAST(field3 AS VARCHAR) + ',%'.

1
Paul

Alternative à Peter Monks.

Si le nombre dans l'instruction 'in' est petit et fixe.

DECLARE @var1 varchar(30), @var2 varchar(30), @var3  varchar(30);

SET @var1 = 'james';
SET @var2 = 'same';
SET @var3 = 'dogcat';

Select * FROM Database Where x in (@var1,@var2,@var3);
1
Aaron C

Vous pouvez convertir la liste des valeurs transmises en un paramètre de valeur de table, puis sélectionner cette liste. 

DECLARE @list NVARCHAR(MAX)
SET @list = '1,2,5,7,10';

DECLARE @pos INT
DECLARE @nextpos INT
DECLARE @valuelen INT
DECLARE @tbl TABLE (number int NOT NULL)

SELECT @pos = 0, @nextpos = 1;

WHILE @nextpos > 0
BEGIN
    SELECT @nextpos = charindex(',', @list, @pos + 1)
    SELECT @valuelen = CASE WHEN @nextpos > 0
                            THEN @nextpos
                            ELSE len(@list) + 1
                        END - @pos - 1
    INSERT @tbl (number)
        VALUES (convert(int, substring(@list, @pos + 1, @valuelen)))
    SELECT @pos = @nextpos;
END

SELECT * FROM DBTable WHERE id IN (SELECT number FROM @tbl);

Dans cet exemple, la chaîne passée dans '1,2,5,7,10' est divisée par des virgules et chaque valeur est ajoutée en tant que nouvelle ligne dans la variable de table @tbl. Ceci peut ensuite être sélectionné en utilisant le SQL standard.

Si vous envisagez de réutiliser cette fonctionnalité, vous pouvez aller plus loin et la convertir en une fonction.

0
Jonathan