Two-step flow
Build the DDL command dynamically and then execute:
- Build statement
SELECT 'CREATE TABLE why.am_i_doing_this AS SELECT '
|| string_agg(column_name, ', ' ORDER BY ordinal_position)
|| ' FROM original.table'
FROM information_schema.columns
WHERE table_schema = 'original'
AND table_name = 'table'
AND column_name NOT IN ('column_1', 'column_2');
- Execute statement
After checking it's good, execute the generated statement in a second round trip to the server.
This is based on the information schema view information_schema.columns
. Alternatively, you could use pg_catalog.pg_attribute
. See:
DO
statement from any client
DO
is just a simple wrapper for ad-hoc execution of PL/pgSQL code. Alternatively, persist the code in a function or procedure.
With EXECUTE
, you can build and execute dynamic SQL commands in a single round trip to the server:
DO
$do$
BEGIN
EXECUTE (
SELECT 'CREATE TABLE why.am_i_doing_this AS SELECT '
|| string_agg(column_name, ', ' ORDER BY ordinal_position)
|| ' FROM original.table'
FROM information_schema.columns
WHERE table_schema = 'original'
AND table_name = 'table'
AND column_name NOT IN ('column_1', 'column_2')
);
END
$do$;
psql meta-command \gexec
You mentioned the default interactive terminal psql
. There you can use \gexec
. It ...
Sends the current query buffer to the server, then treats each column
of each row of the query's output (if any) as a SQL statement to be
executed.
So:
SELECT 'CREATE TABLE why.am_i_doing_this AS SELECT '
|| string_agg(column_name, ', ' ORDER BY ordinal_position)
|| ' FROM original.table'
FROM information_schema.columns
WHERE table_schema = 'original'
AND table_name = 'table'
AND column_name NOT IN ('column_1', 'column_2')\gexec
except
syntax is a simple solution. – JacquesjacquetDO
statement is not entirely simple. But that's just the cherry on top. The basic statement is simple enough. And while at the topic of simplicity, I added\gexec
... (BTW, I'd love BigQuery'sEXCEPT
in standard SQL!) – Coelenterate