postgresql修改表结构报错

error: cannot alter type of column used by a view or rule

分析原因是由于在该表之上有建了视图或规则。

场景模拟:

新建一张表

create table ptemp.online_job_info

(etl_system char(3) check (etl_system ~ '^[A-Z0-9_]*$')

,etl_job varchar(50) check (etl_job ~ '^[A-Z0-9_]*$')

,txdate date

,operator_type char(2) check (operator_type in ('重跑','下线','新增','变更'))

,request_person_name varchar(100) check (request_person_name not in ('')) not null

,remark varchar(200)

,last_modify_date date

,insert_time timestamp with time zone

,unique(etl_system,etl_job,txdate,last_modify_date)

)

distributed by (etl_system,etl_job);

在表基础上建视图

create view ptemp.v_online_job_info as
select * from ptemp.online_job_info;

更新字段,复现报错

alter table ptemp.v_online_job_info alter column remark type varchar(300);

error: cannot alter type of column used by a view or rule

解决方案一:

1.先将依赖ptemp.online_job_info的视图删除掉

drop view ptemp.online_job_info;

2.修改ptemp.online_job_info表结构

alter table ptemp.v_online_job_info alter column remark type varchar(300);

修改成功。

3.把视图建回来

create view ptemp.v_online_job_info as

select * from ptemp.online_job_info;

完成,表结构修改完毕。

作为一个拥有灵魂的SQL boy ,怎么可能就这样解决问题。动作一点都不酷!!!

分析原因:方案一解决这种问题的前提是,被修改表的所有依赖于被修改表的视图或其它都十分清楚,能够被你全部列举出来;只要有一条漏掉,你就修改不成功。除非使用绝招:把表级联删除掉,然后重新建表建视图建规则;当然这种操作危险性可想而知,反正我是不会在生产上这么操作的。

解决方案二:

思路:

1.先从数据库系统中把目标表的所有上游视图规则什么的全部找出来(而且不止一层,要递归查出所有),并找一张表保存起来;

2.按照递归出来的层级关系,从最后一层开始一个一个删除掉;

3.修改目标表结构;

4.按照第一步保存的层级关系,把所有依赖按照层级关系,从第一层一个一个把视图规则等建回来。

实践操作:

1.建表。该表的作用是为了把等下查依赖关系的视图相关信息及建视图删视图预计保存下来。

create table ptemp.drop_create_view_sql_tmp(

parent_oid oid

,parent_table varchar(200)

,childer_oid oid

,childer_table varchar(200)

,drop_view_sql text

,create_view_sql text

,"level"" interger

) distributed by (parend_oid);

2.创建第一个函数。从系统中获取表上游所有相关信息

create or replace function ptemp.alter_table1(schema_name varchar(20),table_name varchar(100)) returns void

as

$$

declare

  v_table_name varchar(150);

  drop_view_cursor  cursor for select drop_view_sql from ptemp.drop_create_view_sql_tmp order by "level" desc;

  v_drop_view text;

begin

 v_table_name := schema_name || '.' || table_name;

 delete from ptemp.drop_create_view_sql_tmp;

 insert into ptemp.drop_create_view_sql_tmp 

 wirh recursive rectbl (parent_oid,childer_oid,level) as (

select dep.parent_oid,rwr.ev_class childer_oid,1 from (select refobjid parent_oid,objid from pg_depend dep1

where dep1.refobjid = v_table_name::regclass

and dep1.deptype = 'n'

and dep1.classid = 'pg_rewrite'::regclass

group by refobjid,objid ) dep

 inner join pg_rewrite rwr

on dep.objid = rwr.oid

where dep.parent_oid <> rwr.ev_class

union all

 select b.refobjid,c.ev_class,level+1

 from rectbl a

 inner join pg_depend b

 on a.childer_oid = b.b.refobjid

inner join pg_rewrite c

 on b.objid = c.oid

 where a.childer_oid <> c.ev_class

)

select parent_oid

           ,parent_oid::regclass parent_table

           ,childer_oid

           ,childer_oid::regclass childer_table

           ,'DROP VIEW ' || childer_oid::regclass || ';'  drop_view_sql

          ,'CREATE VIEW ' || childer_oid::regclass || ' AS' || chr(13) || pg_get_viewdef(childer_oid,true) as view_def

         ,level

from rectbl group by parent_oid,childer_oid,level;

 

----drop_view_cursor

open drop_view_cursor;

loop

FETCH drop_view_cursor INTO v_drop_view;

EXIT WHEN NOT FOUND;

execute v_drop_view;

end loop;

close drop_view_cursor;

end

$$

LANGUAGE plpgsql;

3.创建第二个函数。用于修改表结构化恢复依赖关系

create or replace function ptemp.alter_table2()

returns void

as

$$

declare

 create_view_cursor cursor for select create_view_sql from ptemp.drop_create_view_sql_tmp order by "level" ;

 v_create_view text;

begin

----create_view_cursor

 open create_view_cursor;

loop

FETCH create_view_cursor INTO v_create_view;

EXIT WHEN NOT FOUND;

execute v_create_view;

end loop;

close create_view_cursor;

end

$$

LANGUAGE plpgsql;

测试:

 1.备份依赖关系

select * from ptemp.alter_table1('ptemp','online_job_info');

2.真正修改表结构

alter table ptemp.v_online_job_info alter column remark type varchar(300);

3.还原表视图依赖

select * from ptemp.alter_table2();

当然也可以查看上次修改表的相关依赖信息:

select * from ptemp.drop_create_view_sql_tmp;

到这就结束了。

如果特别自信修改表结构的语句没有问题,是可以把第一个函数和第二个函数合并成一个函数,增加一个传递修改语句的参数进去就可,这样就能过一句执行就行,而不是分三步。

本人自己是建了一步修改表结构函数的,但是平时用的最多的还是方案二的三步曲。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值