sql >> Database teknologi >  >> RDS >> PostgreSQL

Postgres bulk indsats/opdatering, der er injektionssikker. Måske en funktion, der tager et array?

Det er morgen her på den fjerne sydlige kyst af NSW, og jeg tænkte, at jeg ville tage en ny snak om dette. Jeg burde have nævnt før, at vores implementeringsmiljø er RDS, hvilket gør COPY mindre tiltalende. Men ideen med at sende et array ind, hvor hvert element inkluderer rækkedata, er meget tiltrækkende. Det er meget som en INSERT med flere værdier, men med forskelligt syntaktisk sukker. Jeg har stukket lidt i arrays i Postgres, og jeg er altid blevet forvirret over syntaksen. Jeg fandt et par virkelig fremragende tråde med masser af detaljer fra nogle topplakater at studere:

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-parameter-and-access-it

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

Derfra har jeg en fungerende testfunktion:

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;

For at lukke cirklen er her et eksempel på input:

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[]
    );

Går vi tilbage til mine testresultater, fungerer dette nogenlunde lige så godt som min originale multi-værdi indsats. De to andre metoder, jeg oprindeligt postede, er, lad os sige, 4x langsommere. (Resultaterne er ret uberegnelige, men de er altid meget langsommere.) Men jeg sidder stadig tilbage med mit oprindelige spørgsmål:

Er denne injektion sikker?

Hvis ikke, gætter jeg på, at jeg skal omskrive det i PL/pgSQL med en FOREACH-løkke og UDFØRE...USING eller FORMAT for at få de indsprøjtningsrensende tekstbehandlings-/interpolkationsfunktioner der. Er der nogen, der ved det?

Jeg har en masse andre spørgsmål om denne funktion (Skal det være en procedure, så jeg kan administrere transaktionen? Hvordan laver jeg input anyarray? Hvad ville være et fornuftigt resultat at returnere?) Men jeg tror, ​​jeg bliver nødt til at forfølge dem som deres egne spørgsmål.

Tak for enhver hjælp!




  1. 4 tips til opsætning af dine SQL Server-advarsler

  2. Håndtering af fejlhåndtering, mens du kører sqlplus fra shell-scripts

  3. Oracle dato til streng konvertering

  4. Hvordan virker underforespørgsel i select statement i oracle