2009-02-20 12 views
20

Entiendo que en Postgres puro, puede pasar una matriz de enteros a una función, pero que esto no es compatible con el proveedor de datos .NET Npgsql.Arrays enteros de Postgres como parámetros?

Actualmente tengo un DbCommand en el que cargo una llamada a un proceso almacenado, agrego un parámetro y ejecuto escalar para recuperar un Id con el que rellenar un objeto.

Esto ahora necesita tomar n enteros como argumentos. Estos se utilizan para crear registros secundarios que vinculen el nuevo registro creado por su id a los argumentos enteros.

Idealmente prefiero no tener que hacer múltiples llamadas a ExecuteNonQuery en mi DbCommand para cada uno de los enteros, por lo que estoy a punto de construir una cadena csv como un parámetro que se dividirá en el lado de la base de datos.

Normalmente vivo en LINQ 2 SQL saboreando la abstracción Db, trabajar en este proyecto con acceso manual a datos todo se está ensuciando un poco, ¿cómo la gente suele pasar estos tipos de parámetros en postgres?

+3

Para aquellos w No lea más allá de las respuestas seleccionadas: los parámetros de la matriz * son * compatibles con el proveedor .NET Npgsql (aunque no puedo decir si esto fue cierto cuando se hizo la pregunta). Ver mi [respuesta a continuación] (http://stackoverflow.com/a/7733714/957950). – brichins

Respuesta

36

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

Si el controlador no nativo todavía no le permite pasar matrices, a continuación, se puede:

  • pasar una representación de cadena de una matriz (que el procedimiento almacenado puede a continuación, analizar en una matriz - ver string_to_array)

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

    entonces

    SELECT my_method(:1) 
    

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

  • se basan en Postgres sí mismo para emitir a partir de una cadena en una matriz

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

    continuación

    SELECT my_method('{1,2,3,4}') 
    
  • decide no utilizar variables de enlace y emita una cadena de comando explícita con todos los parámetros detallados en su lugar (asegúrese de validar o escapar todos los parámetros que vienen) desde el exterior para evitar ataques de inyección SQL.)

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

    continuación

    SELECT my_method(ARRAY [1,2,3,4]) 
    
+0

Gracias! No, no, confiaba en lo que mis colegas me dijeron. Lo intentaré. –

+1

¿Tiene alguna prueba con respecto a la falta de apoyo nativo de las declaraciones preparadas en PG? No pude encontrar ninguna mención de ese hecho en el [manual] (http://www.postgresql.org/docs/9.2/static/sql-prepare.html). En cuanto al registro, creo que el servidor registra las consultas, ya que no se ejecutan, ya que se transmiten desde el cliente, por lo tanto, no hay declaraciones "EJECUTAR" en el registro. –

+1

@IhorKaharlichenko la redacción era pobre, y estaba fuera de tema. Editado la respuesta. Re. el reclamo original, los conductores no usarán 'PREPARE' a menos que las declaraciones preparadas del lado del servidor estén habilitadas (a veces explícitamente) y, en algunos casos, a menos que se haya excedido un cierto umbral de número de ejecuciones para un comando. Si el registro de comandos está habilitado en 'postgresql.conf', entonces verá el' SELECT'/'INSERT'/etc real. comandos cuando las declaraciones preparadas del lado del servidor NO se utilizan. – vladr

35

Comprendo que esto es una vieja pregunta, pero me tomó varias horas para encontrar una buena solución y pensé' d transmitir lo que aprendí here y salvar a alguien más el problema. Pruebe, por ejemplo,

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

donde @id_list se une a un parámetro int [] a modo de

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

donde comando es un NpgsqlCommand (usando C# y Npgsql en Visual Studio).

+0

Información útil, gracias. –

+1

Podría haber buscado una eternidad si no hubiera tenido esta respuesta ... – Hambone

2

Puede siempre usar una cadena con el formato correcto. El truco es el formateo.

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

Tenga en cuenta que si la matriz es una matriz de cadenas, entonces usted tendrá que utilizar array.Select (valor => string.Format ("\" {0} \", valor)) o el equivalente. Yo uso este estilo para una matriz de un tipo enumerado en PostgreSQL, porque no hay conversión automática de la matriz.

En mi caso, mi tipo enumerado tiene algunos valores como 'value1', 'value2', 'value3', y mi enumeración C# tiene valores coincidentes. En mi caso, la consulta SQL final termina pareciéndose a (E '{"value1", "value2"}'), y esto funciona.

+1

Por supuesto, todas las advertencias estándar sobre la inyección de SQL se aplican – brichins

Cuestiones relacionadas