Postgresql数据库测试环境中有多张表没有添加主键约束,只有一个serial的自增字段。现在需要把那些没有主键的表都加上,serial类型的字段为id 。
首先是怎么找到Postgresql数据库中哪些表没有主键?我们看下pg_class这个表,里面有个relhaspkey字段,如果为t说明有主键,f即没有主键。例如下面这个sql 。
SELECTn.nspnameAS"Schema",c.relnameAS"TableName",c.relhaspkeyAS"HasPK" FROM pg_catalog.pg_classc JOIN pg_namespacen ON( c.relnamespace=n.oid ANDn.nspnameNOTIN('information_schema','pg_catalog') ANDc.relkind='r' ) WHEREc.relhaspkey='f' ORDERBYc.relhaspkey,c.relname ;
然后就是对这些表增加主键约束。删除和添加主键的sql如下所示:
altertableserverdropconstraintserver_pkey; altertableserveraddprimarykey(id);
主键添加完成之后可以通过\d查看。
zhangnq=#\dserver Table"public.server" Column|Type|Modifiers --------+---------------+------------------------------------------------------ id|integer|notnulldefaultnextval('server_int_seq'::regclass) ip|character(50)| Indexes: "server_pkey"PRIMARYKEY,btree(id)
最后就是把这个思路写到脚本里面,运行脚本批量添加。脚本里面把执行失败的表都放在error.log文件中。
脚本:
#!/bin/bash exportPATH=/opt/Postgresql/93/bin:$PATH exportPGDATA=/data/pgsql exportPGHOME=/opt/Postgresql/93 exportPGPORT=5432 dbname=$1 if[!$dbname];then echo"Pleaseenterthedatabasename." exit1 fi psql-c"\dt"-d$dbname>/dev/null if[$?-ne0];then exit1 fi error_log="error.log" echo"">$error_log sql=`cat<<EOF SELECTn.nspnameAS"Schema",c.relnameAS"TableName" FROM pg_catalog.pg_classc JOIN pg_namespacen ON( c.relnamespace=n.oid ANDn.nspnameNOTIN('information_schema',c.relname ; EOF` schemas=`psql-t-A-c"$sql"-d$dbname|cut-d"|"-f1` tables=`psql-t-A-c"$sql"-d$dbname|cut-d"|"-f1` forresin`psql-t-A-c"$sql"-d$dbname` do schema=`echo$res|cut-d"|"-f1` table=`echo$res|cut-d"|"-f2` tablename=`echo"$schema.$table"` psql-e-c"altertable$tablenameaddprimarykey(id)"-d$dbname if[$?-ne0];then echo"$dbname:Addprimarykeyto$tablenameerror.">>$error_log fi done
说下碰到的的问题,在测试的时候发现如果把主键drop掉之后pg_class.relhaspkey值还是为t,但是用\d查看确实没有主键了。解决的办法是手动vacuum这个表,即vacuum server 。
zhangnq=#selectrelname,relhaspkeyfrompg_classwhererelname='server'; relname|relhaspkey ---------+------------ server|t (1row) zhangnq=#altertableserverdropconstraintserver_pkey; ALTERTABLE zhangnq=#selectrelname,relhaspkeyfrompg_classwhererelname='server'; relname|relhaspkey ---------+------------ server|t (1row) zhangnq=#vacuumserver; VACUUM zhangnq=#selectrelname,relhaspkeyfrompg_classwhererelname='server'; relname|relhaspkey ---------+------------ server|f (1row) zhangnq=#altertableserveraddprimarykey(id); ALTERTABLE zhangnq=#selectrelname,relhaspkeyfrompg_classwhererelname='server'; relname|relhaspkey ---------+------------ server|t (1row)
查看pg_class的说明后发现原来pg_class只有在状态由false变成ture的时候会自动修改。这么设计可以提高并发性。
SeveraloftheBooleanflagsinpg_classaremaintainedlazily:theyareguaranteedtobetrueifthat'sthecorrectstate,butmaynotberesettofalseimmediatelywhentheconditionisnolongertrue.Forexample,relhasindexissetbyCREATEINDEX,butitisneverclearedbyDROPINDEX.Instead,VACUUMclearsrelhasindexifitfindsthetablehasnoindexes.Thisarrangementavoidsraceconditionsandimprovesconcurrency.
参考链接:
http://www.postgresql.org/message-id/1395116664140-5796526.post@n5.nabble.com
原文地址:http://www.sijitao.net/2026.html
原文链接:https://www.f2er.com/postgresql/194998.html