背景
在MySQL数据库中,可以通过show create table查询表的create sql 语句,
但在PostgreSQL数据库中,没有类似的命令,但可以通过function 来实现
1、show create table函数
CREATE OR REPLACE FUNCTION "public"."showcreatetable"("namespace" varchar, "tablename" varchar)RETURNS "pg_catalog"."varchar" AS $BODY$
declare
tableScript character varying default '';begin
-- columns
tableScript:=tableScript || ' CREATE TABLE '|| tablename|| ' ( '|| chr(13)||chr(10) || array_to_string(array(
select ' ' || concat_ws(' ',fieldName, fieldType, fieldLen, indexType, isNullStr, fieldComment ) as column_line
from (
select a.attname as fieldName,format_type(a.atttypid,a.atttypmod) as fieldType,' ' as fieldLen,
'' as indexType,
(case when a.attnotnull=true then 'not null' else 'null' end) as isNullStr,
' 'as fieldComment
from pg_attribute a where attstattarget=-1 and attrelid = (select c.oid from pg_class c,pg_namespace n where c.relnamespace=n.oid and n.nspname =namespace and relname =tablename)) as string_columns
),','||chr(13)||chr(10)) || ',';-- 约束
tableScript:= tableScript || chr(13)||chr(10) || array_to_string(
array(select concat(' CONSTRAINT ',conname ,c ,u,p,f) from (select conname,case when contype='c' then ' CHECK('|| ( select findattname(namespace,tablename,'c') ) ||')' end as c ,case when contype='u' then ' UNIQUE('|| ( select findattname(namespace,tablename,'u') ) ||')' end as u ,case when contype='p' then ' PRIMARY KEY ('|| ( select findattname(namespace,tablename,'p') ) ||')' end as p ,case when contype='f' then ' FOREIGN KEY('|| ( select findattname(namespace,tablename,'u') ) ||') REFERENCES '|| (select p.relname from pg_class p where p.oid=c.confrelid ) || '('|| ( select findattname(namespace,tablename,'u') ) ||')' end as ffrom pg_constraint cwhere contype in('u','c','f','p') and conrelid=( select oid from pg_class where relname=tablename and relnamespace =(select oid from pg_namespace where nspname = namespace))) as t
) ,',' || chr(13)||chr(10) ) || chr(13)||chr(10) ||' ); ';-- indexs
-- CREATE UNIQUE INDEX pg_language_oid_index ON pg_language USING btree (oid); -- table pg_language--
/** **/
--- 获取非约束索引 column
-- CREATE UNIQUE INDEX pg_language_oid_index ON pg_language USING btree (oid); -- table pg_language
tableScript:= tableScript || chr(13)||chr(10) || chr(13)||chr(10) || array_to_string(array(select 'CREATE INDEX ' || indexrelname || ' ON ' || tablename || ' USING btree '|| '(' || attname || ');' from (SELECT i.relname AS indexrelname , x.indkey, ( select array_to_string (array( select a.attname from pg_attribute a where attrelid=c.oid and a.attnum in ( select unnest(x.indkey) )) ,',' ) )as attnameFROM pg_class cJOIN pg_index x ON c.oid = x.indrelidJOIN pg_class i ON i.oid = x.indexrelidLEFT JOIN pg_namespace n ON n.oid = c.relnamespaceWHERE c.relname=tablename and i.relname not in( select constraint_name from information_schema.key_column_usage where table_name=tablename ))as t
) ,','|| chr(13)||chr(10));-- COMMENT COMMENT ON COLUMN sys_activity.id IS '主键';
tableScript:= tableScript || chr(13)||chr(10) || chr(13)||chr(10) || array_to_string(
array(
SELECT 'COMMENT ON COLUMN ' || tablename || '.' || a.attname ||' IS '|| ''''|| d.description ||''''
FROM pg_class c
JOIN pg_description d ON c.oid=d.objoid
JOIN pg_attribute a ON c.oid = a.attrelid
WHERE c.relname=tablename
AND a.attnum = d.objsubid),';'|| chr(13)||chr(10)) ;return tableScript;end
$BODY$LANGUAGE plpgsql VOLATILECOST 100
2、findattname函数
CREATE OR REPLACE FUNCTION "public"."findattname"("namespace" varchar, "tablename" varchar, "ctype" varchar)RETURNS "pg_catalog"."varchar" AS $BODY$declare
tt oid ;
aname character varying default '';begintt := oid from pg_class where relname= tablename and relnamespace =(select oid from pg_namespace where nspname=namespace) ;aname:= array_to_string(array(select a.attname from pg_attribute a where a.attrelid=tt and a.attnum in ( select unnest(conkey) from pg_constraint c where contype=ctype and conrelid=tt and array_to_string(conkey,',') is not null ) ),',');return aname;
end
$BODY$LANGUAGE plpgsql VOLATILECOST 100
3、generate_create_table_statement函数
CREATE OR REPLACE FUNCTION "public"."generate_create_table_statement"("p_table_name" varchar)RETURNS "pg_catalog"."text" AS $BODY$
DECLAREv_table_ddl text;column_record record;
BEGINFOR 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 dWHERE 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 dWHERE 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_attnumFROM pg_catalog.pg_attribute aINNER JOIN (SELECT c.oid,n.nspname,c.relnameFROM pg_catalog.pg_class cLEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespaceWHERE c.relname ~ ('^('||p_table_name||')$')AND pg_catalog.pg_table_is_visible(c.oid)ORDER BY 2, 3) bON a.attrelid = b.oidINNER JOIN (SELECT a.attrelid,max(a.attnum) as max_attnumFROM pg_catalog.pg_attribute aWHERE a.attnum > 0 AND NOT a.attisdroppedGROUP BY a.attrelid) eON a.attrelid=e.attrelidWHERE a.attnum > 0 AND NOT a.attisdroppedORDER BY a.attnumLOOPIF column_record.attnum = 1 THENv_table_ddl:='CREATE TABLE '||column_record.schema_name||'.'||column_record.table_name||' (';ELSEv_table_ddl:=v_table_ddl||',';END IF;IF column_record.attnum <= column_record.max_attnum THENv_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 VOLATILECOST 100
3、postgresql中函数调用
select 'sys_dept' AS table,showcreatetable('public','sys_dept') AS create_table