Is there some way to do a INSERT INTO t1 SELECT * FROM... such that it fails if the column names do not coincide?
I’m using Postgresql 9.x The columns names are not known in advance.
Motivation: I’m doing a periodic refresh of materialized views by the (quite standard) PL/pgSQL procedure:
CREATE OR REPLACE FUNCTION matview_refresh(name) RETURNS void AS
$BODY$
DECLARE
matview ALIAS FOR $1;
entry matviews%ROWTYPE;
BEGIN
SELECT * INTO entry FROM matviews WHERE mv_name = matview;
IF NOT FOUND THEN
RAISE EXCEPTION 'Materialized view % does not exist.', matview;
END IF;
EXECUTE 'TRUNCATE TABLE ' || matview;
EXECUTE 'INSERT INTO ' || matview || ' SELECT * FROM ' || entry.v_name;
UPDATE matviews SET last_refresh=CURRENT_TIMESTAMP WHERE mv_name=matview;
RETURN;
END
I preferred a TRUNCATE followed by a SELECT * INTO instead of a DROP/CREATE because it seemed more light and concurrent-friendly. It would fail if someone adds/remove columns from the view (then I would do the DROP/CREATE) but, it doesn’t matter, in that case the refresh would not complete and we would catch the problem soon. What does matter is what happened today: someone changed the order of two columns of the view (of the same type), and the refresh inserted bogus data.
Build this into your plpgsql function to verify that view and table share the same column names in the same sequence exactly:
The
FULL OUTER JOINadds a row withNULLvalues for any mismatch between the list of column names. So, ifEXISTSfinds a row, something is off.And the cast to
::regclasswould raise an exception right away if either table or view do not exist (or is out of scope – not in thesearch_pathand not schema-qualified).If you also want to check data types of the columns, just add
atttypidto theUSINGclause.As an aside: Querying
pg_catalogtables is regularly faster by an order of magnitude than querying the bloated views intinformation_schema– information_schema is only good for SQL standard compliance and portability of code. Since you are writing 100 % Postgres-specific code, neither is relevant here.