HG数据库恢复表中被删除的列 在PG和瀚高数据库中当一个表的列被删除时,其实并没有真正的删除而是在系统表中将该列标记为删除,在表不经过VACUUM FULL和UPDATE操作的情况下,通过修该pg_attribute表的attname、atttypid、attisdropped列的值是可以对被删除的列的值进行恢复。其中数据库自动的VACUUM不是VACUUM FULL。
pg_attribute表字段的信息:
名字
类型
引用
描述
attrelid
oid
pg_class.oid
此字段所属的表。
atttypid
oid
pg_type.oid
字段的数据类型。
attstattarget
int4
attstattarget控制ANALYZE为这个字段设置的统计细节的级别。零值表示不收集统计信息,负数表示使用系统缺省的统计对象。正数值的确切信息是和数据类型相关的。
attlen
int2
该字段所属类型的长度。(pg_type.typlen的拷贝)
attnum
int2
字段的编号,普通字段是从1开始计数的。系统字段,如oid,是任意的负数。
attndims
int4
如果该字段是数组,该值表示数组的维数,否则是0。
attcacheoff
int4
在磁盘上总是-1,但是如果装载入内存中的行描述器中, 它可能会被更新为缓冲在行中字段的偏移量。
atttypmod
int4
表示数据表在创建时提供的类型相关的数据(比如,varchar字段的最大长度)。其值对那些不需要atttypmod的类型而言通常为-1。
attbyval
bool
pg_type.typbyval字段值的拷贝。
attstorage
char
pg_type.typstorage字段值的拷贝。
attalign
char
pg_type.typalign字段值的拷贝。
attnotnull
bool
如果该字段带有非空约束,则为真,否则为假。
atthasdef
bool
该字段是否存在缺省值,此时它对应pg_attrdef表里实际定义此值的记录。
attisdropped
bool
该字段是否已经被删除。如果被删除,该字段在物理上仍然存在表中,但会被分析器忽略,因此不能再通过SQL访问。
attislocal
bool
该字段是否局部定义在对象中的。
attinhcount
int4
该字段所拥有的直接祖先的个数。如果一个字段的祖先个数非零,那么它就不能被删除或重命名。
1、删除表列 创建测试表并查询pg_attribute:
create table test1(id int,name varchar(32), address varchar(30)); insert into test1 values(1,'张三','北京'); insert into test1 values(2,'李四','上海'); highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 北京 2 | 李四 | 上海 (2 rows) select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test2'::regclass and attnum >0; attrelid | attname | atttypid | attnum | attisdropped ----------+---------+----------+--------+-------------- 57355 | id | 23 | 1 | f 57355 | name | 1043 | 2 | f 57355 | address | 1043 | 3 | f (3 rows)
通过使用::regclass, 我们就不需要通过查询pg_class表来获取对象与oid的对应关系了,也可以通过pg_class获取到oid,语句如下。
select oid from pg_class where relname='test1'; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='查询到的oid' and attnum >0;
查询结果中attnum是字段的编号,普通字段是从1开始计数的。系统字段,如oid,是任意的负数。
删除列后,查看到这个
列对应的行的attname变为了 ……..pg.dropped.3……..,且字段类型也从原有数值变为了0,attisdropped也从f变为了空,被打上了删除标记。
注意:atttypid字段类型需要和原来的相对应,否则尽管数据恢复了,数据也是错的,可能原来相应的存储的字母变为数字等等。
alter table test1 drop column address; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test1'::regclass and attnum >0; attrelid | attname | atttypid | attnum | attisdropped ----------+------------------------------+----------+--------+-------------- 57355 | id | 23 | 1 | f 57355 | name | 1043 | 2 | f 57355 | ........pg.dropped.3........ | 0 | 3 | t update pg_attribute set attname='address',atttypid=1043,attisdropped='f' where attrelid='test1'::regclass and attnum=3; highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 北京 2 | 李四 | 上海 (2 rows)
结论:数据可以正常恢复。其中
attname:表示表中列的名字。
atttypid:表示表中列的字段类型。
attisdropped:表示表中的列是否被删除;
f表示未被删除;
t表示被删除。
2、表列删除后,执行VACUUM FULL操作 select * from test1; alter table test1 drop column address; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test1'::regclass and attnum >0; vacuum full test1; update pg_attribute set attname='address',atttypid=1043,attisdropped='f' where attrelid='test1'::regclass and attnum=3; highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 2 | 李四 |
结论:被删除的列不会恢复
3、表列被删除后,执行VACUUM操作 恢复数据
select * from test1; alter table test1 drop column address; select * from test1; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test1'::regclass and attnum >0; vacuum test1; update pg_attribute set attname='address',atttypid=1043,attisdropped='f' where attrelid='test1'::regclass and attnum=3; highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 北京 2 | 李四 | 上海 (2 rows)
结论:数据可以正常恢复。
4、删除列后,执行INSERT alter table test1 drop column address; insert into test1 values(1,'王二'); select * from test1; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test1'::regclass and attnum >0; update pg_attribute set attname='address',atttypid=1043,attisdropped='f' where attrelid='test1'::regclass and attnum=3; highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 北京 2 | 李四 | 上海 1 | 王二 | (3 rows)
结论:表在删除列后新增的列,在删除的列恢复后,新增列无值,原始行该列的值被恢复。删除列上的若原有非空约束也会消失
5、删除列后,执行UPDATE alter table test1 drop column address; select * from test1; update test1 set name='王名' where name='李四'; select * from test1; select attrelid,attname,atttypid,attnum,attisdropped from pg_attribute where attrelid='test1'::regclass and attnum >0; update pg_attribute set attname='address',atttypid=1043,attisdropped='f' where attrelid='test1'::regclass and attnum=3; highgo=# select * from test1; id | name | address ----+------+--------- 1 | 张三 | 北京 2 | 王名 | (2 rows)
结论:表在删除列后UPDATE,在删除的列恢复后,被UPDATE的行的列的值无法恢复。