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

后端 未结 19 2019
花落未央
花落未央 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:12

    Like the other answers mentioned, there is no built in function that does this.

    Here is a function that attempts to get all of the information that would be needed to replicate the table - or to compare deployed and checked in ddl.

    This function outputs:

    • columns (w/ precision, null/not-null, default value)
    • constraints
    • indexes
    
    CREATE OR REPLACE FUNCTION public.show_create_table(
      in_schema_name varchar,
      in_table_name varchar
    )
    RETURNS text
    LANGUAGE plpgsql VOLATILE
    AS
    $$
      DECLARE
        -- the ddl we're building
        v_table_ddl text;
    
        -- data about the target table
        v_table_oid int;
    
        -- records for looping
        v_column_record record;
        v_constraint_record record;
        v_index_record record;
      BEGIN
        -- grab the oid of the table; https://www.postgresql.org/docs/8.3/catalog-pg-class.html
        SELECT c.oid INTO v_table_oid
        FROM pg_catalog.pg_class c
        LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
        WHERE 1=1
          AND c.relkind = 'r' -- r = ordinary table; https://www.postgresql.org/docs/9.3/catalog-pg-class.html
          AND c.relname = in_table_name -- the table name
          AND n.nspname = in_schema_name; -- the schema
    
        -- throw an error if table was not found
        IF (v_table_oid IS NULL) THEN
          RAISE EXCEPTION 'table does not exist';
        END IF;
    
        -- start the create definition
        v_table_ddl := 'CREATE TABLE ' || in_schema_name || '.' || in_table_name || ' (' || E'\n';
    
        -- define all of the columns in the table; https://stackoverflow.com/a/8153081/3068233
        FOR v_column_record IN
          SELECT
            c.column_name,
            c.data_type,
            c.character_maximum_length,
            c.is_nullable,
            c.column_default
          FROM information_schema.columns c
          WHERE (table_schema, table_name) = (in_schema_name, in_table_name)
          ORDER BY ordinal_position
        LOOP
          v_table_ddl := v_table_ddl || '  ' -- note: two char spacer to start, to indent the column
            || v_column_record.column_name || ' '
            || v_column_record.data_type || CASE WHEN v_column_record.character_maximum_length IS NOT NULL THEN ('(' || v_column_record.character_maximum_length || ')') ELSE '' END || ' '
            || CASE WHEN v_column_record.is_nullable = 'NO' THEN 'NOT NULL' ELSE 'NULL' END
            || CASE WHEN v_column_record.column_default IS NOT null THEN (' DEFAULT ' || v_column_record.column_default) ELSE '' END
            || ',' || E'\n';
        END LOOP;
    
        -- define all the constraints in the; https://www.postgresql.org/docs/9.1/catalog-pg-constraint.html && https://dba.stackexchange.com/a/214877/75296
        FOR v_constraint_record IN
          SELECT
            con.conname as constraint_name,
            con.contype as constraint_type,
            CASE
              WHEN con.contype = 'p' THEN 1 -- primary key constraint
              WHEN con.contype = 'u' THEN 2 -- unique constraint
              WHEN con.contype = 'f' THEN 3 -- foreign key constraint
              WHEN con.contype = 'c' THEN 4
              ELSE 5
            END as type_rank,
            pg_get_constraintdef(con.oid) as constraint_definition
          FROM pg_catalog.pg_constraint con
          JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid
          JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace
          WHERE nsp.nspname = in_schema_name
          AND rel.relname = in_table_name
          ORDER BY type_rank
        LOOP
          v_table_ddl := v_table_ddl || '  ' -- note: two char spacer to start, to indent the column
            || 'CONSTRAINT' || ' '
            || v_constraint_record.constraint_name || ' '
            || v_constraint_record.constraint_definition
            || ',' || E'\n';
        END LOOP;
    
        -- drop the last comma before ending the create statement
        v_table_ddl = substr(v_table_ddl, 0, length(v_table_ddl) - 1) || E'\n';
    
        -- end the create definition
        v_table_ddl := v_table_ddl || ');' || E'\n';
    
        -- suffix create statement with all of the indexes on the table
        FOR v_index_record IN
          SELECT indexdef
          FROM pg_indexes
          WHERE (schemaname, tablename) = (in_schema_name, in_table_name)
        LOOP
          v_table_ddl := v_table_ddl
            || v_index_record.indexdef
            || ';' || E'\n';
        END LOOP;
    
        -- return the ddl
        RETURN v_table_ddl;
      END;
    $$;
    

    example

    SELECT * FROM public.show_create_table('public', 'example_table');
    

    produces

    CREATE TABLE public.example_table (
      id bigint NOT NULL DEFAULT nextval('test_tb_for_show_create_on_id_seq'::regclass),
      name character varying(150) NULL,
      level character varying(50) NULL,
      description text NOT NULL DEFAULT 'hello there!'::text,
      CONSTRAINT test_tb_for_show_create_on_pkey PRIMARY KEY (id),
      CONSTRAINT test_tb_for_show_create_on_level_check CHECK (((level)::text = ANY ((ARRAY['info'::character varying, 'warn'::character varying, 'error'::character varying])::text[])))
    );
    CREATE UNIQUE INDEX test_tb_for_show_create_on_pkey ON public.test_tb_for_show_create_on USING btree (id);
    

提交回复
热议问题