【问题标题】:Using query to set the column type in PostgreSQL在 PostgreSQL 中使用查询设置列类型
【发布时间】:2010-12-02 15:13:21
【问题描述】:

在 Alexandre GUIDET 出色的 answer 之后,我尝试运行以下查询:

 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 抱怨语法不正确。具体来说,它说我不能写:create table egg (id (SELECT.
有什么解决方法吗?我不能将查询结果转换为文本并将其作为查询重复使用吗?

【问题讨论】:

    标签: postgresql dynamic-sql plpgsql


    【解决方案1】:

    有一种更简单的方法可以做到这一点。

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

    唯一的前提是模板表包含至少一行。见manual on pg_typeof()

    正如 Milen 所写,您需要像这样 EXECUTE 动态 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$$;
    

    这些条件似乎是多余的,因为您要查找任何特定列

    format() 需要 Postgres 9.1+。

    相关:

    【讨论】:

      【解决方案2】:

      您可以将该查询转换为 function 或(如果您有 Postgres 9.0)转换为 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$$;
      

      【讨论】:

        【解决方案3】:

        您可以有一个表一个定义或一个查询,但不能两者兼而有之。也许你想到了select into 命令。

        【讨论】:

          猜你喜欢
          • 2016-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-17
          • 2018-12-01
          • 1970-01-01
          • 2018-04-11
          相关资源
          最近更新 更多