PostgreSQL数据库中没有主键的表增加主键

PostgreSQL数据库测试环境中有多张表没有添加主键约束,只有一个serial的自增字段。现在需要把那些没有主键的表都加上,serial类型的字段为id 。

首先是怎么找到PostgreSQL数据库中哪些表没有主键?我们看下pg_class这个表,里面有个relhaspkey字段,如果为t说明有主键,f即没有主键。例如下面这个sql 。

SELECT n.nspname AS "Schema",c.relname AS "Table Name",c.relhaspkey AS "Has PK"
FROM
 pg_catalog.pg_class c
JOIN
 pg_namespace n
ON (
 c.relnamespace = n.oid
 AND n.nspname NOT IN ('information_schema', 'pg_catalog')
 AND c.relkind='r'
)
WHERE c.relhaspkey = 'f'
ORDER BY c.relhaspkey, c.relname
;
然后就是对这些表增加主键约束。删除和添加主键的sql如下所示:

alter table server drop constraint server_pkey ;
alter table server add primary key (id) ;
主键添加完成之后可以通过\d查看。

zhangnq=# \d server
 Table "public.server"
 Column | Type | Modifiers
--------+---------------+------------------------------------------------------
 id | integer | not null default nextval('server_int_seq'::regclass)
 ip | character(50) |
Indexes:
 "server_pkey" PRIMARY KEY, btree (id)
最后就是把这个思路写到脚本里面,运行脚本批量添加。脚本里面把执行失败的表都放在error.log文件中。

脚本:

#!/bin/bash
export PATH=/opt/PostgreSQL/93/bin:$PATH
export PGDATA=/data/pgsql
export PGHOME=/opt/PostgreSQL/93
export PGPORT=5432
dbname=$1
if [ ! $dbname ];then
 echo "Please enter the database name."
 exit 1
fi
psql -c "\dt" -d $dbname >/dev/null
if [ $? -ne 0 ];then
 exit 1
fi
error_log="error.log"
echo "">$error_log
sql=`cat << EOF
SELECT n.nspname AS "Schema",c.relname AS "Table Name"
FROM
 pg_catalog.pg_class c
JOIN
 pg_namespace n
ON (
 c.relnamespace = n.oid
 AND n.nspname NOT IN ('information_schema', 'pg_catalog')
 AND c.relkind='r'
)
WHERE c.relhaspkey = 'f'
ORDER BY c.relhaspkey, c.relname
;
EOF`
schemas=`psql -t -A -c "$sql" -d $dbname |cut -d "|" -f 1`
tables=`psql -t -A -c "$sql" -d $dbname |cut -d "|" -f 1`
for res in `psql -t -A -c "$sql" -d $dbname`
do
 schema=`echo $res|cut -d "|" -f 1`
 table=`echo $res|cut -d "|" -f 2`
 tablename=`echo "$schema.$table"`
 psql -e -c "alter table $tablename add primary key (id) " -d $dbname
 if [ $? -ne 0 ];then
 echo "$dbname : Add primary key to $tablename error." >>$error_log
 fi
done
说下碰到的的问题,在测试的时候发现如果把主键drop掉之后pg_class.relhaspkey值还是为t,但是用\d查看确实没有主键了。解决的办法是手动vacuum这个表,即vacuum server 。

zhangnq=# select relname,relhaspkey from pg_class where relname='server' ;
 relname | relhaspkey
---------+------------
 server | t
(1 row)
zhangnq=# alter table server drop constraint server_pkey ;
ALTER TABLE
zhangnq=# select relname,relhaspkey from pg_class where relname='server' ;
 relname | relhaspkey
---------+------------
 server | t
(1 row)
zhangnq=# vacuum server ;
VACUUM
zhangnq=# select relname,relhaspkey from pg_class where relname='server' ;
 relname | relhaspkey
---------+------------
 server | f
(1 row)
zhangnq=# alter table server add primary key (id) ;
ALTER TABLE
zhangnq=# select relname,relhaspkey from pg_class where relname='server' ;
 relname | relhaspkey
---------+------------
 server | t
(1 row)
查看pg_class的说明后发现原来pg_class只有在状态由false变成ture的时候会自动修改。这么设计可以提高并发性。

Several of the Boolean flags in pg_class are maintained lazily: they are guaranteed to be true if that's the correct state, but may not be reset to false immediately when the condition is no longer true. For example, relhasindex is set by CREATE INDEX, but it is never cleared by DROP INDEX. Instead, VACUUM clears relhasindex if it finds the table has no indexes. This arrangement avoids race conditions and improves concurrency.

时间: 2024-10-28 12:42:03

PostgreSQL数据库中没有主键的表增加主键的相关文章

mybatis-在java中怎么处理才能将数据存入postgresql数据库中类型为hstore的字段?

问题描述 在java中怎么处理才能将数据存入postgresql数据库中类型为hstore的字段? /** * 增加批量导入映射. * * @param * @return */ @Action(value = "addImportMapper", results = { @Result(name = "addImportMapper", type = "json", params = { "root", "json

oracel Alter table 给表增加主键 primary key

oracel alter table 给表增加主键 primary key sql> sql> create table emp (empno number(4) not null,   2                    ename varchar2(10),   3                    job varchar2(9),   4                    mgr number(4),   5                    hiredate date

在VB.NET中用ADO(不是ADO.NET)获取数据库中的所有非系统表名

ado|数据|数据库 '假设mCnnDB是个已打开某一数据库的ADO.Connection'获取数据库中的所有表名关键是用到ADO.Connection的OpenSchema方法'该方法返回一个只读的数据集,包括系统表和用户表.'因此,需要一个集合来保存其中的用户表    Public Function GetAllTableName() As System.Collections.ArrayList        Dim t As New System.Collections.ArrayLis

求助,数据库中读取数据生成张表

问题描述 小弟刚刚实习一个月,最近遇到个问题一直没有进展问题描述,从Mysql数据库中读取一个表,生成一个Excel表格,但是表格和表的结构不一样我怎么样写一个Servlet,来实现这个功能呢?我想知道的是生成这个表格,并把数据传入进去的步骤如果能有一种上传一个干净没有数据的Excel表格做模版向其中添加数据也是再好不过啦.拜托各位大神指点迷津了,您的一句指点将使我少走许多弯路,谢谢啦 解决方案 解决方案二:poi或者jxl都可以实现读数据库获取数据想必应该难不倒你最主要的是使用poi或者jxl

用java如何把postgresql数据库中的表数据数据读取到XML文件中

问题描述 目前是oralce好像可以,有哪位高手知道postgreSQL怎么搞importjava.sql.*;importoracle.xml.sql.query.*;importoracle.jdbc.*;publicclasssample{publicstaticvoidmain(Stringargs[])throwsException{DriverManager.registerDriver(neworacle.jdbc.driver.OracleDriver());Connection

PostgreSQL数据库对比mysql快速复制空表的技巧实例

MySQL 有一个和优秀的语法 create table ... like , 可以快速复制一张表,创建其副本. PostgreSQL 也有类似的语法,而且更加灵活,不过要注意些细节. 先来看看MySQL 语法: create table ... like 原始表T1,结构如下:     +----------+------------------+------+-----+---------+----------------+    | Field | Type | Null | Key |

在Oracle数据库中同时更新两张表的简单方法_oracle

以前只会写一些简单的updaet语句,比如updae table set c1='XXX' 之类的 今天遇到一个数据订正的问题,项目背景如下,有个表A,有两个字段a1,a2还有一个关联表B,其中也有两个字段,b1和b2.其中a2和b2是关联的,想把A中的字段a1更新成B中的b1 理论上sql应该挺好写的,但是在oralce中实现了半天一直报语法错误.而且确实还有些小小细节没有注意到. 首先上测试数据 表1,ZZ_TEST1 表2,ZZ_TEST2 要把表一的text更新成表二的text1值,对应

15个postgresql数据库实用命令分享_PostgreSQL

最初是想找postgresql数据库占用空间命令发现的这篇blog,发现其中提供的几 条命令很有用(但也有几条感觉是充数的=.=),于是就把它翻译过来了.另外这篇文章是09年的,所以里面的内容可能有点过时,我收集了原文中有用的评论放在了最后面. 现在有不少开源软件都在使用postgreSQL作为它们的数据库系统.但公司可能不会招一些全职的postgreSQL DBA来维护它(piglei: 在国内基本也找不到).而会让一些比如说Oracle DBA.Linux系统管理员或者程序员去 维护.在这篇

java-问题 如何用Java程序实现,父表的主键插入到子表的外键中?

问题描述 问题 如何用Java程序实现,父表的主键插入到子表的外键中? 需求从excel导入数据到mysql数据库,然后父表的主键是自增列,插入数据同时把主键插入子表的外键中(我已经把主表的数据插入了)