亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

為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/bashexport PATH=/opt/PostgreSQL/93/bin:$PATHexport PGDATA=/data/pgsqlexport PGHOME=/opt/PostgreSQL/93export PGPORT=5432dbname=$1if [ ! $dbname ];then
 echo "Please enter the database name."
 exit 1fipsql -c "\dt" -d $dbname >/dev/nullif [ $? -ne 0 ];then
 exit 1fierror_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 fidone

说下碰到的的问题,在测试的时候发现如果把主键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.

参考链接:

http://www.postgresql.org/message-id/[email protected]

原文链接:http://outofmemory.cn/postgresql/add-primary-key-for-table-without-primary-key

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消