PostgreSQL資料庫中沒有主鍵的表增加主鍵

來源:互聯網
上載者:User

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.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.