PostgreSQL教程--实现类似于MySQL的show create table功能

背景

在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  f
		from pg_constraint c
		where 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 attname
		    
		   FROM pg_class c
		   JOIN pg_index x ON c.oid = x.indrelid
		   JOIN pg_class i ON i.oid = x.indexrelid
		   LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
		   WHERE  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 VOLATILE
  COST 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 '';
 
begin
       tt := 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 VOLATILE
  COST 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$
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 VOLATILE
  COST 100

3、postgresql中函数调用

select 'sys_dept' AS table,showcreatetable('public','sys_dept') AS create_table

4、实现效果

### MySQL `CREATE TABLE` 语法及用法 #### 基本语法结构 MySQL 中用于创建新表的核心命令是 `CREATE TABLE`。其基本语法如下: ```sql CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name ( column_definitions, constraints ) [TABLE_OPTIONS]; ``` 其中: - `[TEMPORARY]`: 可选关键字,表示该表仅在当前会话中可见,在会话结束时自动删除[^1]。 - `[IF NOT EXISTS]`: 防止重复创建同名表引发错误;如果指定名称的表已存在,则不会执行任何操作并返回警告而非错误[^4]。 #### 列定义与约束 列定义部分指定了每一列的数据类型及其属性设置。例如: ```sql id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ``` 上述例子展示了如何定义一列作为主键(`PRIMARY KEY`)以及设定默认值(`DEFAULT`)等特性。 对于更复杂的业务需求还可以加入各种类型的约束条件来维护数据完整性,比如唯一性约束 (`UNIQUE`) 或者外键关联 (`FOREIGN KEY`) 等。 #### 表选项 除了必要的字段之外,我们还能通过一系列可选参数进一步定制化我们的表格行为模式或者存储引擎的选择等方面的内容: ```sql ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` 这里设置了使用的存储引擎为 InnoDB ,字符集采用 UTF-8 编码形式,并且明确了具体的校对规则(utf8mb4_unicode_ci)。 #### 修改现有表结构的例子 当需要调整已经存在的数据库对象时候可以利用到 alter statement 来完成相应变更动作。下面给出了一条关于修改某一特定列长度限制的同时将其设为了不可为空状态的实际案例展示[^2]: ```sql ALTER TABLE t1 MODIFY b BIGINT NOT NULL; ``` 此语句的作用在于把名为`t1`中的某列b重新声明成bigint 类型并且不允许出现null 值的情况发生。 --- ### PostgreSQL 对应功能对比说明 值得注意的是不同关系型数据库管理系统之间虽然大体相似但在细节处理方式可能存在差异。就拿显示建表SQL来说,在MySql里可以直接借助show create table获得完整的DDL脚本输出;然而到了Postgres环境下就没有这么便捷的方法了,而是要依靠其他手段间接达成目的[^3]。 另外值得一提的小知识点就是有关于配置项查询方面两者也有所区别。像查看服务器端所处时区这样的简单任务,在Pg中可以通过简单的SHOW命令轻松搞定: ```sql postgres=# show timezone; TimeZone --------------- Asia/Shanghai (1 row) ``` 相比之下,Mysql则提供了更为丰富的全局变量管理机制供开发者调用获取相关信息。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值