在PostgreSQL中使用query设置列类型

在PostgreSQL中使用query设置列类型,postgresql,dynamic-sql,plpgsql,Postgresql,Dynamic Sql,Plpgsql,在Alexandre GUIDET的精彩演讲之后,我尝试运行以下查询: 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 = ( S

在Alexandre GUIDET的精彩演讲之后,我尝试运行以下查询:

 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抱怨语法不正确。具体来说,它说我不能写:createtableeggdelect。
有什么解决办法吗?我不能将查询结果转换为文本并将其重新用作查询吗?

您可以将该查询转换为文本,或者如果您有Postgres 9.0,则可以:


您可以有一个表、一个定义或一个查询,但不能两者都有。也许您想使用select into命令。

有一种更简单的方法

SELECT pg_typeof(col)::text FROM tbl LIMIT 1
唯一的先决条件是模板表至少包含一行。见

正如Milen所写,您需要像这样执行动态DDL语句。 更简单的DO语句:

DO $$BEGIN
EXECUTE 'CREATE TABLE egg (id '
         || (SELECT pg_typeof(col)::text FROM tbl LIMIT 1) || ')';
END$$;
或者,如果您不确定模板表是否有任何行:

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$$;
这些条件似乎是多余的,因为您可以随时查找特定的列

要求博士后9.1以上

相关的:

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$$;