Как создать инструкцию sql" create table " для существующей таблицы в postgreSQL
У меня есть таблица, созданная в postgreSQL. Я хочу посмотреть на инструкцию sql, используемую для создания таблицы, но не могу понять ее.
Как получить инструкцию sql "create table" для существующей таблицы в postgresql с помощью командной строки или инструкции sql?
14 ответов:
pg_dump -t 'aschema.atable' --schema-only database-nameподробнее - в руководство.
мое решение-войти в базу данных postgres с помощью psql с опцией-E следующим образом:
psql -E -U username -d databaseв psql выполните следующие команды, чтобы увидеть sql, который postgres использует для создания
опишите в таблице:-- 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на основе 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);
сгенерируйте инструкцию create table для таблицы в postgresql из командной строки linux:
этот оператор выводит таблицу create 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
Если вы хотите найти инструкцию create для таблицы без использования pg_dump, этот запрос может работать для вас (измените '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 в этой теме очень хорошо работает.
самый простой способ, который я могу придумать, это установить pgAdmin 3 (найти здесь) и использовать его для просмотра базы данных. Он автоматически сгенерирует запрос, который создаст соответствующую таблицу.
Если вы хотите сделать это для разных таблиц сразу, вы должны использовать переключатель-t несколько раз (мне потребовалось некоторое время, чтобы выяснить, почему список разделенных запятыми не работает). Кроме того, может быть полезно отправлять результаты в outfile или pipe на сервер 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
Это вариант, который работает для меня:
pg_dump -U user_viktor -h localhost unit_test_database -t floorplanpreferences_table --schema-onlyкроме того, если вы используете схемы, вам, конечно, нужно будет указать и это:
pg_dump -U user_viktor -h localhost unit_test_database -t "949766e0-e81e-11e3-b325-1cc1de32fcb6".floorplanpreferences_table --schema-onlyвы получите вывод, который можно использовать для создания таблицы снова, просто запустите этот вывод в psql.
вот немного улучшенная версия shekwi ' s запрос.
Он генерирует ограничение первичного ключа и способен обрабатывать временные таблицы:with pkey as ( select cc.conrelid, format(E', constraint %I primary key(%s)', cc.conname, string_agg(a.attname, ', ' order by array_position(cc.conkey, a.attnum))) pkey from pg_catalog.pg_constraint cc join pg_catalog.pg_class c on c.oid = cc.conrelid join pg_catalog.pg_attribute a on a.attrelid = cc.conrelid and a.attnum = any(cc.conkey) where cc.contype = 'p' group by cc.conrelid, cc.conname ) select format(E'create %stable %s%I\n(\n%s%s\n);\n', case c.relpersistence when 't' then 'temporary ' else '' end, case c.relpersistence when 't' then '' else n.nspname || '.' end, c.relname, string_agg( format(E'\t%I %s%s', a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod), case when a.attnotnull then ' not null' else '' end ), E',\n' order by a.attnum ), (select pkey from pkey where pkey.conrelid = c.oid)) as sql from pg_catalog.pg_class c join pg_catalog.pg_namespace n on n.oid = c.relnamespace join pg_catalog.pg_attribute a on a.attrelid = c.oid and a.attnum > 0 join pg_catalog.pg_type t on a.atttypid = t.oid where c.relname = :table_name group by c.oid, c.relname, c.relpersistence, n.nspname;использовать
table_nameпараметр для указания имени таблицы.
Тоадер Дин просто отлично! Я бы немного изменил ваш код, чтобы показать все ограничения в таблице и сделать возможным использование маски 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);для каждой таблицы пользователей.
вот запрос с некоторыми правками,
select 'CREATE TABLE ' || a.attrelid::regclass::text || '(' || string_agg(a.attname || ' ' || pg_catalog.format_type(a.atttypid, a.atttypmod)|| 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 || CASE WHEN a.attnotnull = true THEN ' NOT NULL' ELSE '' END,E'\n,') || ');' FROM pg_catalog.pg_attribute a join pg_class on a.attrelid=pg_class.oid WHERE a.attrelid::regclass::varchar = 'TABLENAME_with_or_without_schema' AND a.attnum > 0 AND NOT a.attisdropped and pg_class.relkind='r' group by a.attrelid;
простое решение, в чистом одном SQL. Вы получаете идею, вы можете расширить ее до большего количества атрибутов, которые вы хотите показать.
with c as ( SELECT table_name, ordinal_position, column_name|| ' ' || data_type col , row_number() over (partition by table_name order by ordinal_position asc) rn , count(*) over (partition by table_name) cnt FROM information_schema.columns WHERE table_name in ('pg_index', 'pg_tables') order by table_name, ordinal_position ) select case when rn = 1 then 'create table ' || table_name || '(' else '' end || col || case when rn < cnt then ',' else '); ' end from c order by table_name, rn asc;выход:
create table pg_index(indexrelid oid, indrelid oid, indnatts smallint, indisunique boolean, indisprimary boolean, indisexclusion boolean, indimmediate boolean, indisclustered boolean, indisvalid boolean, indcheckxmin boolean, indisready boolean, indislive boolean, indisreplident boolean, indkey ARRAY, indcollation ARRAY, indclass ARRAY, indoption ARRAY, indexprs pg_node_tree, indpred pg_node_tree); create table pg_tables(schemaname name, tablename name, tableowner name, tablespace name, hasindexes boolean, hasrules boolean, hastriggers boolean, rowsecurity boolean);
еще больше модификаций на основе ответа от @vkkeeper. Добавлена возможность запроса таблицы из конкретной схемы.
CREATE OR REPLACE FUNCTION public.describe_table(p_schema_name character varying, 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, c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE relkind = 'r' AND n.nspname = p_schema_name AND relname~ ('^('||p_table_name||')$') 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.oid = table_rec.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 relnamespace = (SELECT ns.oid FROM pg_namespace ns WHERE ns.nspname = p_schema_name) ) 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;
в базе данных pgadminIII > > схемы> > таблицы> > щелкните правой кнопкой мыши на ' your table '>>scripts>> ' выберите любой (создать,вставить,обновить,удалить..)'
Comments