修改表结构提示有试图依赖的处理方法
Posted 瀚高PG实验室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了修改表结构提示有试图依赖的处理方法相关的知识,希望对你有一定的参考价值。
目录
环境
症状
问题原因
解决方案
环境
系统平台:N/A
版本:4.3.2,4.7.5,4.7.6,4.7.7,4.7.8,6.0
症状
修改表结构时,提示该表有其它视图依赖,例如:
错误: 0A000: 不能使用视图或规则改变一个字段的类型
DETAIL: 规则 _RETURN 在 视图 hgtest_vw1,hgtest_vw2 倚赖于字段 “name”
问题原因
瀚高数据库中,直接修改视图依赖的表时会有规则冲突,需要删除依赖视图,修改完毕后再重建视图。
解决方案
1、创建测试表和视图
highgo=# create table hgtest (id int,name varchar(10),des text);
CREATE TABLE
highgo=# create view hgtest_vw1 as select name from hgtest where id >2;
CREATE VIEW
highgo=# create view hgtest_vw2 as select name from hgtest where id <3;
CREATE VIEW
2、 插入模拟数据
highgo=# insert into hgtest values (1,'highgo01','The first line'),(2,'highgo02','The second line'),(3,'highgo03','The third line'),(4,'highgo04','The fourth line');
INSERT 0 4
highgo=# select * from hgtest ;
id | name | des
----+----------+-----------------
1 | highgo01 | The first line
2 | highgo02 | The second line
3 | highgo03 | The third line
4 | highgo04 | The fourth line
(4 rows)
highgo=# select * from hgtest_vw1 ;
name
----------
highgo03
highgo04
(2 rows)
3、修改表结构(模拟问题)
highgo=# alter table hgtest alter COLUMN name type varchar(50);
错误: 0A000: 不能使用视图或规则改变一个字段的类型
DETAIL: 规则 _RETURN 在 视图 hgtest_vw1,hgtest_vw2 倚赖于字段 "name"
4、 找出该表上的所有视图
方法一:
highgo=# select viewname,definition from pg_views where viewname ~ '^hgtest';
viewname | definition
------------+--------------------------
hgtest_vw1 | SELECT hgtest.name +
| FROM hgtest +
| WHERE (hgtest.id > 2);
hgtest_vw2 | SELECT hgtest.name +
| FROM hgtest +
| WHERE (hgtest.id < 3);
(2 rows)
方法二:
CREATE OR REPLACE FUNCTION funvread(db varchar(30),sm varchar(30),textlist text,flag BOOLEAN DEFAULT true)
RETURNS void
LANGUAGE plpgsql
AS $function$
declare cur refcursor;
i int DEFAULT 1;
v_sql varchar;
v_sql1 varchar;
v_name text;
begin
--递归判断 第一次调用
IF flag THEN
--表不存在则创建
CREATE TABLE IF NOT EXISTS drop_view_sql(id serial,vname text,def text);
--清空表
DELETE FROM drop_view_sql;
END IF;
--递归增view字段
create temp TABLE IF NOT EXISTS tempTable(id serial,vname text);
while i<=array_length(regexp_split_to_array(textlist,','),1)
LOOP
DELETE FROM tempTable;
--根据表名,或者view 查出对应view名,view 建立语句
v_sql='INSERT INTO drop_view_sql(vname,def) SELECT view_name,view_definition FROM information_schema.view_table_usage a inner JOIN information_schema.views b ON b.table_name=view_name WHERE b.table_catalog='''||db||''' AND b.table_schema= '''||sm||''' AND a.table_name= '''||(regexp_split_to_array(textlist,',')::text[])[i]||'''';
execute(v_sql);
--增虚拟表,循环调用
v_sql1='INSERT INTO tempTable(vname) SELECT view_name FROM information_schema.view_table_usage a inner JOIN information_schema.views b ON b.table_name=view_name WHERE b.table_catalog='''||db||''' AND b.table_schema= '''||sm||''' AND a.table_name= '''||(regexp_split_to_array(textlist,',')::text[])[i]||'''';
execute(v_sql1);
SELECT string_agg(vname,',') INTO v_name FROM tempTable;
IF v_name!='' THEN
PERFORM funvread(db,sm,v_name,FALSE);
END IF;
i=i+1;
END LOOP;
--raise notice '***%***', '已保存view到表drop_view_sql';
end;
$function$
5、 删除视图
方法一:
drop view hgtest_vw1;
drop view hgtest_vw2;
方法二:
CREATE OR REPLACE FUNCTION funvread(db varchar(30),sm varchar(30),textlist text,flag BOOLEAN DEFAULT true)
RETURNS void
LANGUAGE plpgsql
AS $function$
declare cur refcursor;
i int DEFAULT 1;
v_sql varchar;
v_sql1 varchar;
v_name text;
begin
--递归判断 第一次调用
IF flag THEN
--表不存在则创建
CREATE TABLE IF NOT EXISTS drop_view_sql(id serial,vname text,def text);
--清空表
DELETE FROM drop_view_sql;
END IF;
--递归增view字段
create temp TABLE IF NOT EXISTS tempTable(id serial,vname text);
while i<=array_length(regexp_split_to_array(textlist,','),1)
LOOP
DELETE FROM tempTable;
--根据表名,或者view 查出对应view名,view 建立语句
v_sql='INSERT INTO drop_view_sql(vname,def) SELECT view_name,view_definition FROM information_schema.view_table_usage a inner JOIN information_schema.views b ON b.table_name=view_name WHERE b.table_catalog='''||db||''' AND b.table_schema= '''||sm||''' AND a.table_name= '''||(regexp_split_to_array(textlist,',')::text[])[i]||'''';
execute(v_sql);
--增虚拟表,循环调用
v_sql1='INSERT INTO tempTable(vname) SELECT view_name FROM information_schema.view_table_usage a inner JOIN information_schema.views b ON b.table_name=view_name WHERE b.table_catalog='''||db||''' AND b.table_schema= '''||sm||''' AND a.table_name= '''||(regexp_split_to_array(textlist,',')::text[])[i]||'''';
execute(v_sql1);
SELECT string_agg(vname,',') INTO v_name FROM tempTable;
IF v_name!='' THEN
PERFORM funvread(db,sm,v_name,FALSE);
END IF;
i=i+1;
END LOOP;
--raise notice '***%***', '已保存view到表drop_view_sql';
end;
$function$
5、 删除视图
方法一:
drop view hgtest_vw1;
drop view hgtest_vw2;
方法二:
CREATE OR REPLACE FUNCTION fun_vdrop()
RETURNS void
LANGUAGE plpgsql
AS $function$
declare cur refcursor;
v_name text;
begin
open cur for SELECT vname FROM drop_view_sql ORDER BY id desc;
--循环删除VIEW
fetch cur into v_name;
while (Found)
loop
execute('drop view '||v_name);
fetch cur into v_name;
end loop;
close cur;
end;
$function$
SELECT fun_vdrop(); --删除视图
6、 修改表结构
alter table hgtest alter COLUMN name type varchar(50);
7、 重建视图
方法一:
highgo=# create view hgtest_vw1 as select name from hgtest where id >2;
CREATE VIEW
highgo=# create view hgtest_vw2 as select name from hgtest where id <3;
CREATE VIEW
方法二:
创建视图函数
CREATE OR REPLACE FUNCTION fun_vrecreate()
RETURNS void
LANGUAGE plpgsql
AS $FUNCTION$
DECLARE cur refcursor;
v_name TEXT;
v_def TEXT;
BEGIN
OPEN cur FOR SELECT
vname,
def
FROM
drop_view_sql
ORDER BY
ID;
--循环删除VIEW
FETCH cur INTO v_name,
v_def;
while
( FOUND )
loop
EXECUTE ( 'create OR REPLACE view ' || v_name || ' as ' || v_def );
FETCH cur INTO v_name,
v_def;
END loop;
CLOSE cur;
END;
$FUNCTION$
select fun_vrecreate(); --重建视图
至此,完成表结构修改。
以上是关于修改表结构提示有试图依赖的处理方法的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 数据库 - 使用UEStudio修改dmp文件版本号,解决imp命令恢复的数据库与dmp本地文件版本号不匹配导致的导入失败问题,“ORACLE error 12547”问题处理(代码片段