I'm trying to insert data into a table using a plpgsql function or stored procedure. However, I want to insert multiple records at once. I now these will all be VARCHAR so I thought I could use a function formed like function(tablename VARCHAR, records VARCHAR[][])
. But then I found out multidimensional array support in plpgsql isn.t quite so fantastic.
This is what my function looks like at the moment. This doesn't produce the result I'm looking for. When I ask
SELECT insert_data('tennis', ARRAY[ARRAY['1','2'], ARRAY['3','4']])
I get the following error
ERROR: syntax error at or near "{"
LINE 1: INSERT INTO tennis VALUES (null, {{1}}), (null, {{3}});
^
QUERY: INSERT INTO tennis VALUES (null, {{1}}), (null, {{3}});
CONTEXT: PL/pgSQL function "insert_data" line 26 at EXECUTE statement
However I am expecting a query like
INSERT INTO tennis VALUES (null, '1', '2'), (null, '3', '4');
which would work because table tennis has this structure.
CREATE OR REPLACE FUNCTION insert_data (dsetname_in VARCHAR, records VARCHAR[][])
RETURNS BOOLEAN AS $PROC$
DECLARE
insertquery TEXT;
val VARCHAR;
i INT;
j INT;
BEGIN
insertquery = $$INSERT INTO $$ || dsetname_in || $$ VALUES $$;
FOR i IN array_lower(records, 1)..array_upper(records, 1)
LOOP
insertquery = insertquery || $$(null, $$;
FOR j IN array_lower(records[i:i], 1)..array_upper(records[i:i], 1)
LOOP
val = records[i:i][j:j];
insertquery = insertquery || val;
IF j <> array_upper(records[i:i], 1) THEN
insertquery = insertquery || $$, $$;
END IF;
END LOOP;
insertquery = insertquery || $$)$$;
IF i <> array_upper(records, 1) THEN
insertquery = insertquery || $$, $$;
END IF;
END LOOP;
insertquery = insertquery || $$;$$;
EXECUTE insertquery;
RETURN TRUE;
END;$PROC$ LANGUAGE 'plpgsql';
I'm dubious about the value of this whole approach because I don't see that it adds any useful level of abstraction; but if you must do it, and all your values are character strings, I think the cleanest approach is this:
CREATE OR REPLACE FUNCTION insert_data(dsetname_in text, records text[])
RETURNS VOID LANGUAGE plpgsql AS $PROC$
DECLARE
insertquery text;
i int;
BEGIN
insertquery := 'INSERT INTO ' || dsetname_in || ' VALUES ';
FOR i IN array_lower(records, 1)..array_upper(records, 1)
LOOP
insertquery := insertquery || '(null, ' || records[i] || '),';
END LOOP;
insertquery := left(insertquery, char_length(insertquery) - 1);
EXECUTE insertquery;
END;
$PROC$;
You can then call it like this, which seems cleaner than what you showed for the nested arrays:
SELECT insert_data('tennis',
ARRAY[$$'1','2'$$,
$$'3','4'$$]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With