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
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!