Author: Han high PG Laboratory (Highgo PG Lab) - Bo
PostgreSQL does not get the same function table ddl as oracle, offers two ways to get a table ddl statement below. The function is relatively simple and only realizes the DDL of the ordinary table, if other types of tables or objects are needed, they need to be modified.
Use SQL query directly, the statement is as follows
with t as (
select schema_name,table_name,string_agg(column_name||' '||column_type||' '||column_default_value ||' '||column_not_null||chr(10),',') as aaa from(
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 ~ ('^('||'修改为要获取的表名'||')$')
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) as f
GROUP by schema_name,table_name)
select 'create table '||schema_name||'.'||table_name||' ('||aaa||')' from t;
The effect is as follows:
?column?
-------------------------------------------------------
create table public.emp (empno numeric(4,0) NOT NULL+
,ename character varying NULL +
,job character varying NULL +
,mgr numeric(4,0) NULL +
,hiredate date NULL +
,sal numeric(7,2) NULL +
,comm numeric(7,2) NULL +
,deptno numeric(2,0) NULL +
)
(1 row)
Rewritten as a stored procedure, the code is as follows
create or replace function get_tab_ddl(tab_name varchar)
returns text as
$$
declare
--定义变量
tab_ddl text;
curs refcursor;
tmp_col record;
tab_info record;
begin
--获取表的pid、schema信息
open curs for 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 ~ ('^('||tab_name||')$')AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY 2,3;
fetch curs into tmp_col;
--判断是否存在该表
if tmp_col.oid is null then
return 'Table "'||tab_name||'" was not queried';
end if;
--如表存在,获取表的列信息
FOR tab_info IN
SELECT
a.attname as col_name,
pg_catalog.format_type(a.atttypid, a.atttypmod) as col_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 col_default_value,
CASE WHEN a.attnotnull = true THEN
'NOT NULL'
ELSE
'NULL'
END as col_not_null,
a.attnum as attnum,
e.max_attnum as max_attnum
FROM
pg_catalog.pg_attribute a
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 a.attrelid=tmp_col.oid
AND NOT a.attisdropped
ORDER BY a.attnum
--拼接为ddl语句
LOOP
IF tab_info.attnum = 1 THEN
tab_ddl:='CREATE TABLE '||tmp_col.nspname||'.'||tmp_col.relname||' (';
ELSE
tab_ddl:=tab_ddl||',';
END IF;
IF tab_info.attnum <= tab_info.max_attnum THEN
tab_ddl:=tab_ddl||chr(10)||' '||tab_info.col_name||' '||tab_info.col_type||' '||tab_info.col_default_value||' '||tab_info.col_not_null;
END IF;
END LOOP;
tab_ddl:=tab_ddl||');';
--输出结果
RETURN tab_ddl;
end;
$$ language plpgsql;
The effect is as follows
highgo=# select get_tab_ddl('emp');
get_tab_ddl
------------------------------------
CREATE TABLE public.emp ( +
empno numeric(4,0) NOT NULL, +
ename character varying NULL,+
job character varying NULL, +
mgr numeric(4,0) NULL, +
hiredate date NULL, +
sal numeric(7,2) NULL, +
comm numeric(7,2) NULL, +
deptno numeric(2,0) NULL);
(1 row)