2009-02-20 20 views
20

Ich verstehe, dass in Postgres rein, Sie einen Integer-Array in eine Funktion übergeben können, aber dass dies nicht in den .NET-Datenprovider Npgsql unterstützt.Postgres Integer-Arrays als Parameter?

Moment hat ich eine DbCommand, in denen ich einen Anruf an eine gespeicherte Prozedur laden, in einem Parameter hinzufügen und Skalar ausführen, um eine ID, um wieder mit einem Objekt zu füllen.

Dies muss nun n ganze Zahlen als Argumente nehmen. Diese werden verwendet, um untergeordnete Datensätze zu erstellen, die den neu erstellten Datensatz mit seiner ID mit den ganzzahligen Argumenten verknüpfen.

Im Idealfall würde ich lieber nicht mehrere ExecuteNonQuery-Aufrufe auf meinem DbCommand für jede der ganzen Zahlen machen müssen, also bin ich dabei, eine CSV-Zeichenfolge als einen Parameter zu erstellen, der auf der Datenbankseite aufgeteilt wird.

Normalerweise lebe ich in LINQ 2 SQL die Db Abstraktion genießend, an diesem Projekt mit manuellem Datenzugriff arbeitend, es ist alles nur ein bisschen schmutzig, wie gehen Leute normalerweise diese Art von Parametern in Postgres weiter?

+3

Für die w ho nicht über die ausgewählten Antworten lesen: Array-Parameter * werden * mit dem .NET Npgsql-Provider unterstützt (obwohl ich nicht sagen kann, ob dies wahr war, als die Frage gestellt wurde). Siehe meine [Antwort unten] (http://stackoverflow.com/a/7733714/957950). – brichins

Antwort

36

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

Wenn Ihr nicht-nativer Treiber noch nicht zulässt Arrays zu übergeben, dann können Sie:

  • eine String-Darstellung eines Arrays übergeben (die gespeicherten Prozedur können parsen dann in ein Array - siehe string_to_array)

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

    dann

    SELECT my_method(:1) 
    

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

  • verlassen sich auf Postgres sich aus einer Zeichenkette auf ein Array werfen

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

    dann

    SELECT my_method('{1,2,3,4}') 
    
  • nicht wählen Bindevariablen zu verwenden und Geben Sie eine explizite Befehlszeichenfolge mit allen ausgeschriebenen Parametern ein (stellen Sie sicher, dass alle Parameter überprüft werden, die kommen von außen SQL-Injection-Angriffe zu vermeiden.)

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

    dann

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

Danke! Nein, hatte ich nicht, ich verließ mich darauf, was meine Kollegen mir gesagt hatten. Ich versuche es mal. –

+1

Haben Sie irgendwelche Beweise bezüglich fehlender nativer Unterstützung von vorbereiteten Aussagen in PG? Ich fand keine Erwähnung dieser Tatsache im [Handbuch] (http://www.postgresql.org/docs/9.2/static/sql-prepare.html). Wie für die Protokollierung, ich denke, dass Server die Abfragen protokolliert, wie sie ausgeführt werden, nicht wie sie vom Client übergeben werden, also keine "EXECUTE" -Anweisungen im Protokoll. –

+1

@IhorKaharlichenko der Wortlaut war schlecht und war off-topic. Bearbeitete die Antwort. Re. Im ursprünglichen Fall werden Treiber 'PREPARE' nicht verwenden, es sei denn serverseitige vorbereitete Anweisungen sind aktiviert (manchmal explizit) und in einigen Fällen, wenn ein bestimmter Anzahl von Ausführungsschwellenwerten für einen Befehl nicht überschritten wurde. Wenn die Befehlsprotokollierung in 'postgresql.conf' aktiviert ist, sehen Sie den eigentlichen' SELECT'/'INSERT'/etc. Befehle, wenn serverseitig vorbereitete Anweisungen NICHT verwendet werden. – vladr

35

Ich weiß, das eine alte Frage, aber es hat mich mehrere Stunden, um eine gute Lösung zu finden und dachte, dass ich d weitergeben, was ich gelernt here und speichern Sie jemand anderen das Problem. Versuchen Sie zum Beispiel

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

wo @id_list in einen int [] Parameter haft

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

wo Befehl ein NpgsqlCommand (unter Verwendung von C# und Npgsql in Visual Studio) ist.

+0

Nützliche Informationen, danke. –

+1

Ich hätte nach einer Ewigkeit suchen können, wenn Sie diese Antwort nicht gehabt hätten ... – Hambone

2

Sie können immer verwenden Sie eine ordnungsgemäß formatierte Zeichenfolge. Der Trick ist die Formatierung.

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

Beachten Sie, dass, wenn Ihr Array ein Array von Strings ist, dann müssen Sie array.Select (Wert => string.Format ("\" {0} \“, Wert)) verwenden, oder das Äquivalent. Ich verwende diesen Stil für ein Array eines Aufzählungstyps in PostgreSQL, da es keine automatische Konvertierung vom Array gibt.

In meinem Fall hat mein Aufzählungstyp einige Werte wie 'Wert1', 'Wert2', "value3", und meine C# -Enumeration hat übereinstimmende Werte. In meinem Fall sieht die abschließende SQL-Abfrage so aus (E '{"value1", "value2"}), und das funktioniert.

+1

Natürlich gelten alle Standardwarnungen über SQL-Injektion – brichins