PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Sisipan/pembaruan massal Postgres yang aman untuk injeksi. Mungkin fungsi yang menggunakan array?

Ini pagi di sini di Pantai Selatan Jauh NSW, dan saya pikir saya akan mencoba lagi. Saya seharusnya menyebutkan sebelumnya bahwa lingkungan penerapan kami adalah RDS, yang membuat COPY kurang menarik. Tetapi gagasan untuk melewatkan larik di mana setiap elemen menyertakan data baris sangat menarik. Ini seperti INSERT multi-nilai, tetapi dengan gula sintaksis yang berbeda. Saya telah sedikit menyodok array di Postgres, dan selalu bingung dengan sintaksnya. Saya menemukan beberapa utas yang sangat bagus dengan banyak detail dari beberapa poster teratas untuk dipelajari:

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/

Dari sana, saya mendapatkan fungsi pengujian yang berfungsi:

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;

Untuk menutup lingkaran, berikut ini contoh beberapa masukan:

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

Kembali ke hasil pengujian saya, ini bekerja secara kasar sebaik sisipan multi-nilai asli saya. Dua metode lain yang saya posting awalnya, katakanlah, 4x lebih lambat. (Hasilnya cukup tidak menentu, tetapi selalu jauh lebih lambat.) Tapi saya masih memiliki pertanyaan awal saya:

Apakah suntikan ini aman?

Jika tidak, saya rasa saya perlu menulis ulang dalam PL/pgSQL dengan perulangan FOREACH dan EXECUTE...USING atau FORMAT untuk mendapatkan fitur pemrosesan teks/interpolasi pembersih injeksi di sana. Ada yang tahu?

Saya memiliki banyak pertanyaan lain tentang fungsi ini (Haruskah ini menjadi prosedur agar saya dapat mengelola transaksi? Bagaimana cara membuat array input? Apa hasil yang masuk akal untuk dikembalikan?) Tapi saya pikir saya harus melakukannya kejar itu sebagai pertanyaan mereka sendiri.

Terima kasih atas bantuannya!




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menghilangkan tanda kutip ganda untuk melakukan kueri di PostgreSQL

  2. postgresql - bilangan bulat di luar jangkauan

  3. Gabungkan beberapa baris menjadi satu dengan lebih dari satu nilai baris dalam satu kolom

  4. Npgsql/ Postgresql:fungsi tidak ada pesan kesalahan saat itu

  5. Penyortiran alami yang mendukung angka besar