How to generate the “create table” sql statement for an existing table in postgreSQL

后端 未结 19 2047
花落未央
花落未央 2020-11-28 17:49

I have created a table in postgreSQL. I want to look at the SQL statement used to create the table but cannot figure it out.

How do I get the create table

19条回答
  •  臣服心动
    2020-11-28 18:06

    My solution is to log in to the postgres db using psql with the -E option as follows:

    psql -E -U username -d database   
    

    In psql, run the following commands to see the sql that postgres uses to generate
    the describe table statement:

    -- List all tables in the schema (my example schema name is public)
    \dt public.*
    -- Choose a table name from above
    -- For create table of one public.tablename
    \d+ public.tablename  
    

    Based on the sql echoed out after running these describe commands, I was able to put together
    the following plpgsql function:

    CREATE OR REPLACE FUNCTION generate_create_table_statement(p_table_name varchar)
      RETURNS text AS
    $BODY$
    DECLARE
        v_table_ddl   text;
        column_record record;
    BEGIN
        FOR column_record IN 
            SELECT 
                b.nspname as schema_name,
                b.relname as table_name,
                a.attname as column_name,
                pg_catalog.format_type(a.atttypid, a.atttypmod) as column_type,
                CASE WHEN 
                    (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
                     FROM pg_catalog.pg_attrdef d
                     WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) IS NOT NULL THEN
                    'DEFAULT '|| (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
                                  FROM pg_catalog.pg_attrdef d
                                  WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)
                ELSE
                    ''
                END as column_default_value,
                CASE WHEN a.attnotnull = true THEN 
                    'NOT NULL'
                ELSE
                    'NULL'
                END as column_not_null,
                a.attnum as attnum,
                e.max_attnum as max_attnum
            FROM 
                pg_catalog.pg_attribute a
                INNER JOIN 
                 (SELECT c.oid,
                    n.nspname,
                    c.relname
                  FROM pg_catalog.pg_class c
                       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                  WHERE c.relname ~ ('^('||p_table_name||')$')
                    AND pg_catalog.pg_table_is_visible(c.oid)
                  ORDER BY 2, 3) b
                ON a.attrelid = b.oid
                INNER JOIN 
                 (SELECT 
                      a.attrelid,
                      max(a.attnum) as max_attnum
                  FROM pg_catalog.pg_attribute a
                  WHERE a.attnum > 0 
                    AND NOT a.attisdropped
                  GROUP BY a.attrelid) e
                ON a.attrelid=e.attrelid
            WHERE a.attnum > 0 
              AND NOT a.attisdropped
            ORDER BY a.attnum
        LOOP
            IF column_record.attnum = 1 THEN
                v_table_ddl:='CREATE TABLE '||column_record.schema_name||'.'||column_record.table_name||' (';
            ELSE
                v_table_ddl:=v_table_ddl||',';
            END IF;
    
            IF column_record.attnum <= column_record.max_attnum THEN
                v_table_ddl:=v_table_ddl||chr(10)||
                         '    '||column_record.column_name||' '||column_record.column_type||' '||column_record.column_default_value||' '||column_record.column_not_null;
            END IF;
        END LOOP;
    
        v_table_ddl:=v_table_ddl||');';
        RETURN v_table_ddl;
    END;
    $BODY$
      LANGUAGE 'plpgsql' COST 100.0 SECURITY INVOKER;
    

    Here is the function usage:

    SELECT generate_create_table_statement('tablename');
    

    And here is the drop statement if you don't want this function to persist permanently:

    DROP FUNCTION generate_create_table_statement(p_table_name varchar);
    

提交回复
热议问题