2009-02-20 17 views
20

Rozumiem, że w Postgres czysty można przekazać tablicę liczb całkowitych do funkcji, ale to nie jest obsługiwane w dostawcy danych .NET Npgsql.Postgres tablice całkowite jako parametry?

Mam obecnie polecenie DbCommand, do którego ładuję wywołanie do zapisanego procesu, dodam parametr i wykonuję skalar, aby odzyskać identyfikator, aby wypełnić obiekt.

To teraz musi przyjmować liczby całkowite jako argumenty. Służą one do tworzenia rekordów potomnych łączących nowo utworzony rekord przez jego identyfikator z argumentami całkowitymi.

Idealnie raczej nie musiałbym wykonywać wielu wywołań ExecuteNonQuery na mojej komendzie DbCommand dla każdej z liczb całkowitych, więc zamierzam zbudować ciąg znaków csv jako parametr, który zostanie podzielony po stronie bazy danych.

Zwykle mieszkam w LINQ 2 SQL delektując się abstrakcją Db, pracując nad tym projektem z ręcznym dostępem do danych, wszystko jest po prostu trochę brudne, jak ludzie zwykle przechodzą do przekazywania tego rodzaju parametrów do postgreSzu?

+3

Dla tych w ho nie czyta obok wybranych odpowiedzi: parametry tablicy * są * obsługiwane przez dostawcę Npgsql .NET (chociaż nie mogę powiedzieć, czy było to prawdą, gdy zadano pytanie). Zobacz moją [odpowiedź poniżej] (http://stackoverflow.com/a/7733714/957950). – brichins

Odpowiedz

36

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

Jeśli nie rodzimy kierowca nadal nie pozwala przekazać tablice, a następnie można:

  • przekazać ciąg znaków reprezentujący tablicę (co procedura składowana może następnie zanalizować w tablicy - patrz string_to_array)

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

    następnie

    SELECT my_method(:1) 
    

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

  • polegać na siebie PostgreSQL rzucić z ciągiem do tablicy

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

    następnie

    SELECT my_method('{1,2,3,4}') 
    
  • wybrać, aby nie używać zmiennych powiązań i Wydaj jawny ciąg polecenia z wszystkimi parametrami zapisanymi zamiast niego (upewnij się, że sprawdzasz poprawność lub unikasz wszystkich nadchodzących parametrów z zewnątrz, aby uniknąć ataków SQL injection.)

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

    następnie

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

Dzięki! Nie, nie, polegałem na tym, co powiedzieli mi moi koledzy. Dam ci szansę. –

+1

Czy masz jakiś dowód na brak rodzimego wsparcia przygotowanych wyciągów w PG? Nie znalazłem żadnych wzmianek na ten temat w [podręczniku] (http://www.postgresql.org/docs/9.2/static/sql-prepare.html). Jeśli chodzi o rejestrowanie, domyślam się, że serwer loguje kwerendy, ponieważ są wykonywane nie tak, jak są przekazywane z klienta, a zatem nie zawierają instrukcji "EXECUTE" w dzienniku. –

+1

@IhorKaharlichenko sformułowanie było słabe i nie było tematu. Edytował odpowiedź. Re. oryginalnego roszczenia, sterowniki nie będą używać polecenia "PREPARE", chyba że instrukcje przygotowane po stronie serwera są włączone (czasami jawnie), aw niektórych przypadkach, jeśli dla polecenia nie zostanie przekroczony określony próg liczby wykonań. Jeśli rejestrowanie komend jest włączone w pliku 'postgresql.conf', zobaczysz aktualne' SELECT'/'INSERT'/etc. komendy, gdy instrukcje przygotowane po stronie serwera NIE są używane. – vladr

35

Zdaję sobie sprawę, że jest to stare pytanie, ale zajęło mi kilka godzin, aby znaleźć dobre rozwiązanie i myślałem” Przekaż to, czego nauczyłem się here i uratuj komuś innemu kłopot. Próby na przykład

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

gdzie @id_list jest związany z [] parametru int drodze

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

którym polecenie jest NpgsqlCommand (C# i Npgsql Visual Studio).

+0

Przydatne informacje, dziękuję. –

+1

Mogłem szukać wieczności, gdybyś nie miał tej odpowiedzi ... – Hambone

2

Możesz zawsze użyć poprawnie sformatowanego ciąg. Sztuką jest formatowanie.

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

Zauważ, że jeśli tablica jest tablicą stringów, następnie trzeba użyć array.Select (wartość => string.Format ("\" {0} \”, wartość)) lub jej odpowiednik.Zastosuj ten styl do tablicy typu wyliczeniowego w PostgreSQL, ponieważ nie ma automatycznej konwersji z tablicy.

W moim przypadku mój typ wyliczeniowy ma pewne wartości, takie jak "wartość1", "wartość2", "value3", a moje wyliczenie C# ma pasujące wartości. W moim przypadku ostateczne zapytanie SQL kończy się wyglądem podobnym (E '{"value1", "value2"}'), a to działa.

+1

Oczywiście, wszystkie standardowe ostrzeżenia o wstrzyknięciu SQL mają zastosowanie – brichins

Powiązane problemy