PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Групово вмъкване/актуализация на Postgres, която е безопасна за инжектиране. Може би функция, която приема масив?

Сутрин е тук, на Далечния южен бряг на NSW, и си помислих, че ще пробвам още веднъж. Трябваше да спомена преди, че нашата среда за внедряване е RDS, което прави COPY по-малко привлекателен. Но идеята за предаване на масив, където всеки елемент включва данните от реда, е много привлекателен. Много прилича на INSERT с много стойности, но с различна синтактична захар. Разрових се малко в масивите в Postgres и винаги оставам объркан от синтаксиса. Намерих няколко наистина отлични теми с много подробности от някои най-добри плакати за изучаване:

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/

Оттам имам работеща тестова функция:

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;

За да затворите кръга, ето пример за въвеждане:

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

Връщайки се към резултатите от моите тестове, това работи приблизително толкова добре, колкото и първоначалната ми вмъкване с много стойности. Другите два метода, които публикувах първоначално, са, да кажем, 4 пъти по-бавни. (Резултатите са доста непостоянни, но винаги са много по-бавни.) Но все още оставам с първоначалния си въпрос:

Безопасна ли е тази инжекция?

Ако не, предполагам, че трябва да го пренапиша в PL/pgSQL с цикъл FOREACH и EXECUTE...USING или FORMAT, за да получа функциите за обработка/интерполкация на текст за почистване на инжектиране там. Някой знае ли?

Имам много други въпроси относно тази функция (трябва ли да е процедура, за да мога да управлявам транзакцията? Как да направя входния произволен масив? Какъв би бил разумният резултат за връщане?) Но мисля, че ще трябва преследват ги като свои собствени въпроси.

Благодаря за всяка помощ!




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да изчислим времето между два времеви клейма (PostgreSQL)

  2. Как да добавите брой дни в postgresql datetime

  3. Избор на правилния индекс за PostgreSQL заявка

  4. SQL сравнение на равенство/неравенство със стойности с nullable

  5. Ръководство за Pgpool за PostgreSQL:Част първа