For processing a single row or processing rows one-by one, you can use the SQL RETURNING
clause of INSERT
combined with the plpgsql INTO
clause. Example:
But you are obviously trying to process a whole set at once.
calculate distance from address points to all streets within a distance of 50 meters ...
Use a set-based approach. Much faster and cleaner. If you want to return rows from the INSERT
additionally use a set-returning function. Example:
You would not need a function at all. Just this query:
INSERT INTO street(ad_geom, st_geom, distance, traffic_ct) -- any columns in street
SELECT ad.geom, st.geom, ST_Distance(ad.geom, st.geom), ad.traffic_ct
FROM ad
LEFT JOIN st ON ST_DWithin(ad.geom, st.geom, 50.0)
RETURNING * -- all columns in street
I guess you don't actually need anything returned any more, since this query does all you wanted, but I kept RETURNING
as proof of concept. You can just skip it.
Use [INNER] JOIN
instead of LEFT [OUTER] JOIN
if you don't want to include adresses with no matching street.
The manual about RETURNING
in INSERT
:
The optional RETURNING
clause causes INSERT
to compute and return
value(s) based on each row actually inserted [...] any expression
using the table's columns is allowed. The syntax of the RETURNING
list is identical to that of the output list of SELECT
. Only rows
that were successfully inserted or updated will be returned.
If you need to wrap this into a plpgsql function (could also be a simple SQL function) - and still return all rows:
CREATE OR REPLACE FUNCTION insert_neighbours()
RETURNS SETOF street AS
$func$
BEGIN
RETURN QUERY
INSERT INTO street(ad_geom, st_geom, distance, traffic_ct) -- any columns in street
SELECT ad.geom, st.geom, ST_Distance(ad.geom, st.geom), ad.traffic_ct
FROM ad
LEFT JOIN st ON ST_DWithin(ad.geom, st.geom, 50.0)
RETURNING *; -- all columns in street
END
$func$ LANGUAGE plpgsql;
Call:
SELECT * FROM insert_neighbours(); -- use SELECT * FROM ... !
For simplicity I return the whole row, but you can return select columns as well. See above example.
Creating the function gives no error
That's because PL/pgSQL currently only runs superficial syntax checks on CREATE FUNCTION
. You have to actually execute the function to test it - and make sure that all branches of code in plpgsql functions get tested.