sql >> Databáze >  >> RDS >> PostgreSQL

Hromadná vložka/aktualizace Postgres, která je bezpečná pro vstřikování. Možná funkce, která bere pole?

Tady na Dálném jižním pobřeží NSW je ráno a napadlo mě, že bych se do toho dal ještě jednou. Předtím jsem měl zmínit, že naše prostředí pro nasazení je RDS, díky čemuž je COPY méně atraktivní. Ale myšlenka předání pole, kde každý prvek obsahuje data řádku, je velmi přitažlivý. Je to hodně jako vícehodnotový INSERT, ale s jiným syntaktickým cukrem. Trochu jsem šťouchl do polí v Postgresu a vždy jsem přišel zmatený syntaxí. Našel jsem několik opravdu vynikajících vláken se spoustou podrobností z některých nejlepších plakátů k prostudování:

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/

Odtud mám funkční testovací funkci:

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;

Chcete-li kruh uzavřít, zde je příklad nějakého vstupu:

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

Když se vrátím k výsledkům mých testů, funguje to zhruba stejně dobře jako moje původní vícehodnotová vložka. Další dvě metody, které jsem původně zveřejnil, jsou řekněme 4x pomalejší. (Výsledky jsou dost nevyzpytatelné, ale vždy jsou mnohem pomalejší.) Ale stále mi zbývá moje původní otázka:

Je tato injekce bezpečná?

Pokud ne, myslím, že to budu muset přepsat do PL/pgSQL pomocí smyčky FOREACH a EXECUTE...USING nebo FORMAT, abych tam dostal funkce pro zpracování textu/interpolkaci vstřikování. Ví někdo?

Mám spoustu dalších otázek ohledně této funkce (Měl by to být postup, abych mohl řídit transakci? Jak udělám vstup anyarray? Jaký by byl rozumný výsledek vrátit?) Ale myslím, že budu muset sledovat je jako své vlastní otázky.

Děkujeme za jakoukoli pomoc!




  1. Funkce data a času SQLite

  2. Rails-MySQL Error - neinicializovaná konstanta MysqlCompat::MysqlRes

  3. Oracle SQL automaticky vytvoří inkrementovaný PK VARCHAR

  4. Jednoduchá mysql otázka týkající se primárních klíčů a vložky