[postgresql] postgreSQL에서 기존 테이블에 대한 “create table”sql 문을 생성하는 방법

postgreSQL에서 테이블을 만들었습니다. 테이블을 만드는 데 사용 된 SQL 문을보고 싶지만 알아낼 수 없습니다.

create table커맨드 라인 또는 SQL 문을 통해 Postgres의 기존 테이블에 대한 SQL 문을 어떻게 얻 습니까?



답변

pg_dump -t 'schema-name.table-name' --schema-only database-name

자세한 내용은 설명서를 참조하십시오 .


답변

내 솔루션은 다음과 같이 -E 옵션과 함께 psql을 사용하여 postgres db에 로그인하는 것입니다.

psql -E -U username -d database   

psql에서 postgres가
describe table 문 을 생성 하는 데 사용하는 SQL을 보려면 다음 명령을 실행하십시오 .

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

이러한 describe 명령을 실행 한 후 반향 된 sql을 기반으로
다음 plpgsql 함수를 구성 할 수있었습니다 .

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;

함수 사용법은 다음과 같습니다.

SELECT generate_create_table_statement('tablename');

이 함수를 영구적으로 유지하지 않으려는 경우 drop 문은 다음과 같습니다.

DROP FUNCTION generate_create_table_statement(p_table_name varchar);


답변

Linux 명령 행에서 postgresql의 테이블에 대한 테이블 작성 명령문을 생성하십시오.

이 명령문은 나를 위해 테이블 ​​작성 sql 명령문을 출력합니다.

pg_dump -U your_db_user_name your_database -t your_table_name --schema-only

설명:

pg_dump는 데이터베이스 자체에 대한 정보를 얻는 데 도움이됩니다. -U사용자 이름을 나타냅니다. 내 pgadmin 사용자에게는 비밀번호가 설정되어 있지 않으므로 비밀번호를 입력 할 필요가 없습니다. -t옵션 수단은 하나 개의 테이블에 지정. --schema-only테이블의 데이터가 아닌 테이블에 대한 데이터 만 인쇄 함을 의미합니다. 내가 사용하는 정확한 명령은 다음과 같습니다.

pg_dump -U pgadmin kurz_prod -t fact_stock_info --schema-only


답변

pg_dump를 사용하지 않고 테이블에 대한 create 문을 찾으려면이 쿼리가 작동 할 수 있습니다 (테이블이 호출 된대로 ‘tablename’을 변경하십시오).

SELECT
  'CREATE TABLE ' || relname || E'\n(\n' ||
  array_to_string(
    array_agg(
      '    ' || column_name || ' ' ||  type || ' '|| not_null
    )
    , E',\n'
  ) || E'\n);\n'
from
(
  SELECT
    c.relname, a.attname AS column_name,
    pg_catalog.format_type(a.atttypid, a.atttypmod) as type,
    case
      when a.attnotnull
    then 'NOT NULL'
    else 'NULL'
    END as not_null
  FROM pg_class c,
   pg_attribute a,
   pg_type t
   WHERE c.relname = 'tablename'
   AND a.attnum > 0
   AND a.attrelid = c.oid
   AND a.atttypid = t.oid
 ORDER BY a.attnum
) as tabledefinition
group by relname;

psql에서 직접 호출하면 다음을 수행하는 것이 유용합니다.

\pset linestyle old-ascii

또한 이 스레드에서 generate_create_table_statement 함수 는 매우 잘 작동합니다.


답변

Dean Toader 정말 훌륭합니다! 테이블의 모든 제약 조건을 표시하고 테이블 이름에 regexp 마스크를 사용할 수 있도록 코드를 약간 수정했습니다.

CREATE OR REPLACE FUNCTION public.generate_create_table_statement(p_table_name character varying)
  RETURNS SETOF text AS
$BODY$
DECLARE
    v_table_ddl   text;
    column_record record;
    table_rec record;
    constraint_rec record;
    firstrec boolean;
BEGIN
    FOR table_rec IN
        SELECT c.relname FROM pg_catalog.pg_class c
            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                WHERE relkind = 'r'
                AND relname~ ('^('||p_table_name||')$')
                AND n.nspname <> 'pg_catalog'
                AND n.nspname <> 'information_schema'
                AND n.nspname !~ '^pg_toast'
                AND pg_catalog.pg_table_is_visible(c.oid)
          ORDER BY c.relname
    LOOP

        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 = table_rec.relname
                    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;

        firstrec := TRUE;
        FOR constraint_rec IN
            SELECT conname, pg_get_constraintdef(c.oid) as constrainddef
                FROM pg_constraint c
                    WHERE conrelid=(
                        SELECT attrelid FROM pg_attribute
                        WHERE attrelid = (
                            SELECT oid FROM pg_class WHERE relname = table_rec.relname
                        ) AND attname='tableoid'
                    )
        LOOP
            v_table_ddl:=v_table_ddl||','||chr(10);
            v_table_ddl:=v_table_ddl||'CONSTRAINT '||constraint_rec.conname;
            v_table_ddl:=v_table_ddl||chr(10)||'    '||constraint_rec.constrainddef;
            firstrec := FALSE;
        END LOOP;
        v_table_ddl:=v_table_ddl||');';
        RETURN NEXT v_table_ddl;
    END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.generate_create_table_statement(character varying)
  OWNER TO postgres;

예를 들어 다음과 같은 쿼리를 만들 수 있습니다.

SELECT * FROM generate_create_table_statement('.*');

다음과 같은 결과가 나타납니다.

CREATE TABLE public.answer (
     id integer DEFAULT nextval('answer_id_seq'::regclass) NOT NULL,
     questionid integer  NOT NULL,
     title character varying  NOT NULL,
     defaultvalue character varying  NULL,
     valuetype integer  NOT NULL,
     isdefault boolean  NULL,
     minval double precision  NULL,
     maxval double precision  NULL,
     followminmax integer DEFAULT 0 NOT NULL,
CONSTRAINT answer_pkey
     PRIMARY KEY (id),
CONSTRAINT answer_questionid_fkey
     FOREIGN KEY (questionid) REFERENCES question(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT answer_valuetype_fkey
     FOREIGN KEY (valuetype) REFERENCES answervaluetype(id) ON UPDATE RESTRICT ON DELETE RESTRICT);

각 사용자 테이블에 대해.


답변

내가 생각할 수있는 가장 쉬운 방법은 pgAdmin 3 ( here ) 을 설치 하고이를 사용하여 데이터베이스를 보는 것입니다. 해당 테이블을 생성하는 쿼리를 자동으로 생성합니다.


답변

한 번에 다양한 테이블에 대해이 작업을 수행하려면 -t 스위치를 여러 번 사용해야합니다 (쉼표로 구분 된 목록이 작동하지 않는 이유를 알아내는 데 시간이 걸렸습니다). 또한 결과를 아웃 파일 또는 파이프로 다른 시스템의 postgres 서버로 전송하는 데 유용 할 수 있습니다.

pg_dump -t table1 -t table2 database_name --schema-only > dump.sql

pg_dump -t table1 -t table2 database_name --schema-only | psql -h server_name database_name