web-dev-qa-db-fra.com

Comment puis-je fournir une liste <int> à un paramètre SQL?

J'ai une instruction SQL comme celle-ci:

...
const string sql = @"UPDATE PLATYPUS
SET DUCKBILLID = :NEWDUCKBILLID
WHERE PLATYPUSID IN (:ListOfInts)";
...
ocmd.Parameters.Add("ListOfInts", ??WhatNow??);

Comment puis-je fournir la liste d'ints séparée par des virgules, qui peut contenir n'importe quel nombre (raisonnable *) de valeurs

  • Par "raisonnable" dans ce cas, j'entends entre une et deux douzaines.
17
B. Clay Shannon

UPDATE: Comme le souligne Lasse, vous ne pouvez pas réaliser ce que Clay essaie de faire avec la méthode ci-dessous. Bien que cela passe dans une liste de nombres séparés par des virgules, il ne sera pas exécuté comme prévu. Malheureusement, je ne peux pas supprimer cela car c'est la réponse acceptée.


Essayez quelque chose comme ça:

ocmd.Parameters.Add("ListOfInts", String.Join(",",myList.ToArray());

La méthode String.Join prend tous les éléments d'un tableau et place le caractère spécifié entre eux.

0
Abe Miessler

Vous ne pouvez pas, vous devez créer une fonction d'assistance qui remplace :ListOfInts par (par exemple) :I0,:I1,:I2... et transmettez le paramètre en ajoutant un par un dans le code. La fonction que vous voulez est émulée gracieusement par Dapper.Net in sa liste supporte .

11
Felice Pollano

Je pense que la seule solution possible est de passer des valeurs séparées par des virgules, que vous pouvez convertir en une table en SQL en utilisant une fonction. Voici la fonction que j'utilise

CREATE FUNCTION dbo.CSVToList (@CSV varchar(3000)) 
    RETURNS @Result TABLE (Value varchar(30))
AS   
BEGIN
    DECLARE @List TABLE
    (
        Value varchar(30)
    )

    DECLARE
        @Value varchar(30),
        @Pos int

    SET @CSV = LTRIM(RTRIM(@CSV))+ ','
    SET @Pos = CHARINDEX(',', @CSV, 1)

    IF REPLACE(@CSV, ',', '') <> ''
    BEGIN
        WHILE @Pos > 0
        BEGIN
            SET @Value = LTRIM(RTRIM(LEFT(@CSV, @Pos - 1)))

            IF @Value <> ''
                INSERT INTO @List (Value) VALUES (@Value) 

            SET @CSV = RIGHT(@CSV, LEN(@CSV) - @Pos)
            SET @Pos = CHARINDEX(',', @CSV, 1)
        END
    END     

    INSERT @Result
    SELECT
        Value
    FROM
        @List

    RETURN
END

et vous pouvez utiliser le code suivant (par exemple) pour effectuer des opérations:

DECLARE @CSV varchar(100)
SET @CSV = '30,32,34,36,40'

SELECT 
    ProductID, 
    ProductName, 
    UnitPrice
FROM 
    Products
WHERE
    ProductID IN (SELECT * FROM dbo.CSVToLIst(@CSV))

J'ai pris le code à partir d'ici: http://www.geekzilla.co.uk/view5C09B52C-4600-4B66-9DD7-DCE840D64CBD.htm

J'espère que ça aide.

5
Umar Jamil

Vous n'indiquez pas quelle base de données vous utilisez, mais s'il s'agit de SQL Server 2008+, vous pouvez également envisager les paramètres Paramètres de table .

Pour votre exemple, la complexité ajoutée ne vaut peut-être pas la peine, mais peut s'avérer utile dans d'autres scénarios.

4
James Simpson

Utilisez la méthode Join de string sur le tableau de Ints. Vous pouvez mentionner comma comme séparateur

List<int> ints = new List<int>();
ints.Add(4);
ints.Add(6);
ints.Add(2);

string concatenatedIds= string.Join(",", ints.ToArray());

La sortie (valeur dans concatenatedIds) sera 4,6,2. Vous pouvez utiliser cette chaîne comme valeur de paramètre pour votre clause IN

ocmd.Parameters.Add("ListOfInts",concatenatedIds);
1
Shyju

La meilleure façon de gérer cela est de conserver la liste dans la base de données, de sorte que vous puissiez écrire une requête select pour renvoyer les valeurs de votre liste. La question est, comment pouvez-vous faire cela lorsque les données proviennent du client? La plupart du temps, ces données sont sélectionnées à la main par l'utilisateur, enregistrement par enregistrement. Dans ce cas, vous pouvez utiliser une table (pensez: "panier") qui ajoute les enregistrements pour les valeurs une par une, au fur et à mesure que l'utilisateur les sélectionne. S'il s'agit davantage d'un travail par lots, vous pouvez utiliser un processus BulkInsert pour créer les enregistrements.

1
Joel Coehoorn