PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wstawianie/aktualizacja zbiorcza Postgres, która jest bezpieczna dla wstrzyknięć. Może funkcja, która pobiera tablicę?

Tu, na Dalekim Południowym Wybrzeżu Nowej Południowej Walii, jest ranek i pomyślałem, że jeszcze raz spróbuję. Powinienem był wcześniej wspomnieć, że nasze środowisko wdrożeniowe to RDS, co sprawia, że ​​COPY jest mniej atrakcyjne. Ale pomysł przekazywania w tablicy, w której każdy element zawiera dane wiersza, jest bardzo pociągający. Przypomina to wielowartościową INSERT, ale z innym cukrem składniowym. Trochę grzebałem w tablicach w Postgresie i zawsze wychodzę zdezorientowany składnią. Znalazłem kilka naprawdę doskonałych wątków z wieloma szczegółami z kilku najlepszych plakatów do przestudiowania:

https://dba.stackexchange .com/questions/224785/pass-array-of-mixed-type-into-stored-function

https ://dba.stackexchange.com/questions/131505/use-array-of-composite-type-as-function-and-access-it

https://dba.stackexchange.com/questions/225176/how-to-pass-an-array-to-a-plpgsql-function-with-variadic-parameter/

Stamtąd mam działającą funkcję testową:

DROP FUNCTION IF EXISTS data.item_insert_array (item[]);

CREATE OR REPLACE FUNCTION data.item_insert_array (data_in item[]) 
  RETURNS int
AS $$
INSERT INTO item (
    id, 
    marked_for_deletion, 
    name_)

SELECT
    d.id, 
    d.marked_for_deletion,
    d.name_

FROM unnest(data_in) d

ON CONFLICT(id) DO UPDATE SET 
    marked_for_deletion = EXCLUDED.marked_for_deletion,
    name_ = EXCLUDED.name_;

SELECT cardinality(data_in); -- array_length() doesn't work. ¯\_(ツ)_/¯

$$ LANGUAGE sql;

ALTER FUNCTION data.item_insert_array(item[]) OWNER TO user_bender;

Aby zamknąć krąg, oto przykład niektórych danych wejściowych:

select * from item_insert_array(

    array[
        ('2f888809-2777-524b-abb7-13df413440f5',true,'Salad fork'),
        ('f2924dda-8e63-264b-be55-2f366d9c3caa',false,'Melon baller'),
        ('d9ecd18d-34fd-5548-90ea-0183a72de849',true,'Fondue fork')
        ]::item[]
    );

Wracając do wyników moich testów, działa to z grubsza tak samo, jak moja oryginalna wielowartościowa wkładka. Pozostałe dwie metody, które pierwotnie opublikowałem, są, powiedzmy, 4x wolniejsze. (Wyniki są dość niekonsekwentne, ale zawsze są dużo wolniejsze.) Ale nadal mam moje pierwotne pytanie:

Czy ten zastrzyk jest bezpieczny?

Jeśli nie, myślę, że muszę przepisać go w PL/pgSQL z pętlą FOREACH i EXECUTE...USING lub FORMAT, aby uzyskać tam funkcje przetwarzania/interpolacji tekstu do czyszczenia wtrysku. Czy ktoś wie?

Mam wiele innych pytań dotyczących tej funkcji (czy powinna to być procedura, dzięki której będę mógł zarządzać transakcją? Jak wprowadzić dowolną tablicę wejściową? Jaki byłby sensowny wynik do zwrócenia?) Ale myślę, że będę musiał traktuj je jako własne pytania.

Dziękujemy za pomoc!




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres tablica json ostatnia data

  2. Sparametryzowana klauzula IN przy użyciu wielu kolumn

  3. Zdefiniować nazwy tabel i kolumn jako argumenty w funkcji plpgsql?

  4. PostgreSQL — odwołania do kluczy obcych wzajemnie wykluczające się tabele

  5. org.hibernate.type.TextType i Oracle