Reputation: 4519
I have a common situation that comes up where I want to join with a table moredata. To give the simplest example, imagine I have:
SELECT *
FROM x
JOIN moredata d on x.yyyymmdd = d.yyyymmdd
x
will vary while moredata
stays the same. What's a good way stylistically to reuse code, automate the above so that I can apply it to different tables (eg. do the same thing on table 'y' instead of 'x')?
One way would be to write a plpgsql function using dynamic SQL that operates on the name of the table. Something like:
CREATE FUNCTION joinmoredata(tblname text) RETURNS TABLE(...) AS $$
BEGIN
RETURN QUERY EXECUTE format('SELECT * FROM %I JOIN moredata on ...', tblname);
END;
$$ LANGUAGE plpgsql;
But then you couldn't apply it to a derived table or a CTE. Is there a better way? Or is dynamic SQL the best way to reuse code in this situation?
(Note, the actual query is a lot more complicated than SELECT * FROM x JOIN moredata d on x.yyyymmdd = d.yyyymmdd
which is why I want to reuse code.)
Upvotes: 1
Views: 1059
Reputation: 657867
As long as you use the same column names with the same data types from each table in place of x
and return the same row type, that's a good candidate for dynamic SQL. Exactly like you already have in your question. Your use of format()
with %I
suggests you are aware of how to sanitize identifiers avoid syntax errors and SQL injection.
You need to have a plan for privilege management. And I would pass schema-qualified table names or data type regclass
to avoid confusion with table name resolution and possibly other tables with the same name in a different schema.
Closely related, with more details:
If it gets more complicated - varying column names and types - you can always concatenate query strings in a client program ...
Upvotes: 2
Reputation: 2312
I can only say that I use dynamic SQL any time I need to reuse bigger parts of SQL code and change only something in WHERE clause or table names etc. And it works OK and I do this way also very complicated CTE queries containing also INSERTs or UPDATESs and it works. So I would vote for dynamic SQL.
Upvotes: 1