web-dev-qa-db-fra.com

Tableaux entiers Postgres comme paramètres?

Je comprends que dans Postgres pure, vous pouvez passer un tableau d'entiers dans une fonction mais que cela n'est pas pris en charge dans le fournisseur de données .NET Npgsql.

J'ai actuellement un DbCommand dans lequel je charge un appel à un proc stocké, ajoute un paramètre et exécute scalaire pour récupérer un identifiant pour remplir un objet.

Cela doit maintenant prendre n entiers comme arguments. Ils sont utilisés pour créer des enregistrements enfants reliant l'enregistrement nouvellement créé par son id aux arguments entiers.

Idéalement, je préfère ne pas avoir à effectuer plusieurs appels ExecuteNonQuery sur ma DbCommand pour chacun des entiers, donc je suis sur le point de créer une chaîne csv en tant que paramètre qui sera divisé du côté de la base de données.

Je vis normalement dans LINQ 2 SQL en savourant l'abstraction Db, en travaillant sur ce projet avec un accès manuel aux données, tout devient un peu sale, comment les gens passent-ils généralement ce type de paramètres dans postgres?

31
Tristan Warner-Smith

Voir: http://www.postgresql.org/docs/9.1/static/arrays.html

Si votre pilote non natif ne vous permet toujours pas de transmettre des tableaux, vous pouvez:

  • passez une représentation sous forme de chaîne d'un tableau (que votre procédure stockée peut ensuite analyser dans un tableau - voir string_to_array )

    CREATE FUNCTION my_method(TEXT) RETURNS VOID AS $$ 
    DECLARE
           ids INT[];
    BEGIN
           ids = string_to_array($1,',');
           ...
    END $$ LANGUAGE plpgsql;
    

    ensuite

    SELECT my_method(:1)
    

    avec: 1 = '1,2,3,4'

  • compter sur Postgres lui-même pour convertir une chaîne en tableau

    CREATE FUNCTION my_method(INT[]) RETURNS VOID AS $$ 
           ...
    END $$ LANGUAGE plpgsql;
    

    ensuite

    SELECT my_method('{1,2,3,4}')
    
  • choisissez de ne pas utiliser de variables de liaison et d'émettre une chaîne de commande explicite avec tous les paramètres énoncés à la place (assurez-vous de valider ou d'échapper tous les paramètres provenant de l'extérieur pour éviter les attaques par injection SQL.)

    CREATE FUNCTION my_method(INT[]) RETURNS VOID AS $$ 
           ...
    END $$ LANGUAGE plpgsql;
    

    ensuite

    SELECT my_method(ARRAY [1,2,3,4])
    
50
vladr

Je me rends compte que c'est une vieille question, mais il m'a fallu plusieurs heures pour trouver une bonne solution et j'ai pensé transmettre ce que j'avais appris ici et sauver quelqu'un d'autre. Essayez, par exemple,

SELECT * FROM some_table WHERE id_column = ANY(@id_list)

où @id_list est lié à un paramètre int [] au moyen de

command.Parameters.Add("@id_list", NpgsqlDbType.Array | NpgsqlDbType.Integer).Value = my_id_list;

où commande est un NpgsqlCommand (en utilisant C # et Npgsql dans Visual Studio).

47
brichins

Vous pouvez toujours utiliser une chaîne correctement formatée. L'astuce est le formatage.

command.Parameters.Add("@array_parameter", string.Format("{{{0}}}", string.Join(",", array));

Notez que si votre tableau est un tableau de chaînes, vous devrez utiliser array.Select (value => string.Format ("\" {0}\", value)) ou l'équivalent. J'utilise ce style pour un tableau d'un type énuméré dans PostgreSQL, car il n'y a pas de conversion automatique à partir du tableau.

Dans mon cas, mon type énuméré a des valeurs comme 'value1', 'value2', 'value3', et mon énumération C # a des valeurs correspondantes. Dans mon cas, la requête SQL finale finit par ressembler à quelque chose comme (E '{"value1", "value2"}'), et cela fonctionne.

1
user2738265