2

After the excellent answer by Alexandre GUIDET, I attempted to run the following query:

 create table egg (id (SELECT 
  pg_catalog.format_type(a.atttypid, a.atttypmod) as Datatype 
  FROM 
  pg_catalog.pg_attribute a 
  WHERE 
    a.attnum > 0 
  AND NOT a.attisdropped 
  AND a.attrelid = ( 
    SELECT c.oid 
    FROM pg_catalog.pg_class c 
    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
    WHERE c.relname ~ '^(TABLENAME)$' 
   AND pg_catalog.pg_table_is_visible(c.oid) 
  ) 
  and a.attname = 'COLUMNNAME'));

PostgreSQL, however, complains about incorrect syntax. Specifically it says that I cannot write: create table egg (id (SELECT.
Are there any workarounds? Can't I convert the result of a query to text and reuse it as a query?

Community
  • 1
  • 1
David
  • 4,786
  • 11
  • 52
  • 80

3 Answers3

4

There is a much simpler way to do that.

SELECT pg_typeof(col)::text FROM tbl LIMIT 1

Only precondition is that the template table holds at least one row. See the manual on pg_typeof()

As Milen wrote, you need to EXECUTE dynamic DDL statements like this.
A much simpler DO statement:

DO $$BEGIN
EXECUTE 'CREATE TABLE egg (id '
         || (SELECT pg_typeof(col)::text FROM tbl LIMIT 1) || ')';
END$$;

Or, if you are not sure the template table has any rows:

DO $$BEGIN
EXECUTE (
   SELECT format('CREATE TABLE egg (id %s)'
               , format_type(atttypid, atttypmod))
   FROM   pg_catalog.pg_attribute
   WHERE  attrelid = 'tbl'::regclass  -- name of template table
   AND    attname = 'col'             -- name of template column
   AND    attnum > 0 AND NOT attisdropped
   );
END$$;

These conditions seem redundant, since you look for a specific column any

format() requires Postgres 9.1+.

Related:

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
1

You can either convert that query to a function or (if you have Postgres 9.0) to an anonymous code block:

DO $$DECLARE the_type text;
BEGIN
    SELECT ... AS datatype INTO the_type FROM <the rest of your query>;
    EXECUTE 'create table egg ( id ' || the_type || <the rest of your create table statement>;
END$$;
Milen A. Radev
  • 60,241
  • 22
  • 105
  • 110
0

You can either have a table a definition or a query, but not both. Maybe your thinking of the select into command.

nate c
  • 8,802
  • 2
  • 27
  • 28