GaussDB (DWS) application combat: DDL operations on the tables referenced by the view

Abstract: GaussDB (DWS) evolved from Postgres. Like Postgres, if a table is referenced by a view, some DDL operations cannot be executed directly in a specific scenario.

Background note

GaussDB (DWS) evolved from Postgres. Like Postgres, if a table is referenced by a view, some DDL operations cannot be performed directly under certain scenarios, such as modifying the type of the field referenced by the view, deleting the table, etc. The newly added fields are operable. The main reason is that the view refers to the fields of the table, and the view needs to be changed if it is modified. Let's briefly demonstrate this part of the content below, what will happen when the table referenced by the view performs DDL operations. Then look at how to modify the table fields and so on.

Generate experiment content

Build 2 test tables and 3 test views. The SQL statements built are as follows. Note that all views use the fields of t1 and not the fields of t2.

CREATE TABLE t1 (id int,name varchar(20));
CREATE TABLE t2 (id int,name varchar(20));
CREATE OR REPLACE VIEW v1 as select * from t1;
CREATE OR REPLACE VIEW v2 as select a.* from t1 a inner join t2 b on a.id = b.id;
CREATE OR REPLACE VIEW v3 as select a.* from v1 a inner join v2 b on a.id = b.id inner join t1 c on a.id = c.id;

One, delete the table

DROP TABLE t1;
DROP TABLE t2;

Judging from the execution result prompt, DROP TABLE was not executed successfully because of the view dependency. You can use DROP...CASCADE to delete dependent views together, but in general, we don't want to delete views.

Two, modify the field

ALTER TABLE T1 MODIFY NAME VARCHAR(30);
ALTER TABLE T2 MODIFY NAME VARCHAR(30);

Judging from the prompts of the execution results, the t1 table failed to modify the field type because the view v2 used this field, and the t2 table was modified successfully because no view used the t2 field, although the t2 table was used in the view, but only For association, the field of the view does not use the field of the t2 table, so the field type of the t2 table can be modified successfully.

In order to successfully achieve the goal in the subsequent experiments, modify the view of v2 here to get the field of t2

ALTER TABLE T2 MODIFY NAME VARCHAR(20);
CREATE OR REPLACE VIEW v2 as select b.* from t1 a inner join t2 b on a.id = b.id;

Three, new fields

ALTER TABLE t1 ADD COMMENT VARCHAR(30);
ALTER TABLE t2 ADD  COMMENT VARCHAR(30);

There are no restrictions on adding fields, because when the view is created, there is no way to reference fields that do not yet exist. We review the definition of the view CREATE VIEW v1 AS SELECT * FROM t1; Will there be any new field information for v1 at this time? The answer is no, the view needs to be refreshed to have new fields

select * from v2;
CREATE OR REPLACE VIEW v2 as select a.* from t1 a inner join t2 b on a.id = b.id;
select * from v2;

How to modify the table definition referenced by the view?

So the question is, how can we modify the definition of the table referenced by the view similar to the above modified field?

I think it can be divided into the following steps

Backup view definition to text -> backup table definition to text -> modify table definition in text -> backup table (ALTER TABLE XX RENAME TO XX_BAK) -> add modified table -> insert data -> backup view text refresh view

One of the more difficult to obtain is, which views are referenced by the table? It needs to use pg_rewrite to get the reference relationship, and with recursive .. as to get it cyclically.

One, backup view definition to text

First get the view of the table design, this SQL is a bit complicated, here are a few steps to explain

Get the dependency relationship between tables and views through pg_rewrite

select c.nspname as schemaname,b.relname,rel_oid,b.relkind,d.oid as ori_oid,d.relname ori_name
    from (
    select unnest(regexp_matches(ev_action::text,':relid (\d+)', 'g'))::oid  rel_oid,ev_class --rel_oid 被依赖对象 ,ev_class 视图名称
    from pg_rewrite 
    union 
    select unnest(regexp_matches(ev_action::text,':resorigtbl (\d+)','g'))::oid,ev_class
    from pg_rewrite 
     ) deptbl                   --pg_write获取依赖关系
    inner join pg_class b       --被依赖对象获取表名等信息
    on deptbl.rel_oid = b.oid
    inner join pg_namespace c
    on b.relnamespace = c.oid
    inner join pg_class d     --视图获取视图名等信息,且用于排除pg_write获取的自身对象,即rel_oid <> ev_class
    on deptbl.ev_class = d.oid
    and deptbl.rel_oid <> d.oid
    where  b.relname = 't2'; --指定表名t2

Get all relevant views through the with recursive xx as loop statement

with recursive rec_view as (
    select c.nspname as schemaname,b.relname,rel_oid,b.relkind,d.oid as ori_oid,d.relname ori_name
    ,0 as level  --level防止死循环
    from (
    select unnest(regexp_matches(ev_action::text,':relid (\d+)', 'g'))::oid  rel_oid,ev_class --rel_oid 被依赖对象 ,ev_class 视图名称
    from pg_rewrite 
    union 
    select unnest(regexp_matches(ev_action::text,':resorigtbl (\d+)','g'))::oid,ev_class
    from pg_rewrite 
     ) deptbl                   --pg_write获取依赖关系
    inner join pg_class b       --被依赖对象获取表名等信息
    on deptbl.rel_oid = b.oid
    inner join pg_namespace c
    on b.relnamespace = c.oid
    inner join pg_class d     --视图获取视图名等信息,且用于排除pg_write获取的自身对象,即rel_oid <> ev_class
    on deptbl.ev_class = d.oid
    and deptbl.rel_oid <> d.oid
    where  b.relname = 't2' --指定表名t2
union all
    select c.nspname,b.relname,deptbl.rel_oid,b.relkind,d.oid as ori_oid,d.relname ori_name,level+1
    from (
    select unnest(regexp_matches(ev_action::text,':relid (\d+)', 'g'))::oid  rel_oid,ev_class
    from pg_rewrite 
  union 
    select unnest(regexp_matches(ev_action::text,':resorigtbl (\d+)','g'))::oid,ev_class
    from pg_rewrite 
  ) deptbl 
    inner join pg_class b
    on deptbl.rel_oid = b.oid
    inner join pg_namespace c
    on b.relnamespace = c.oid
    inner join pg_class d
    on deptbl.ev_class = d.oid
    and deptbl.rel_oid <> d.oid
    inner join rec_view e          --循环语句关联条件
    on deptbl.rel_oid = e.ori_oid
    where level <=10    --level防止死循环
)
select * from rec_view;

From the result, t2 so related views are v2 and v3 two views.

After getting the view list, we back up the two views v2 and v3 to the text, using gs_dump.

gs_dump mydb1 -s -t v2 -t v3 -c -f view.ddl -p 25308

2. Backup table definition to text -> modify table definition in text -> backup table (ALTER TABLE XX RENAME TO XX_BAK) -> add modified table and insert data

Backup table definition to text: use gs_dump to export the table structure of t2 to a file

Modify the table definition in the text: modify the field type of name from the original varchar(30) to varchar(50)

Backup table (ALTER TABLE XX RENAME TO XX_BAK): add ALTER TABLE RENAME action in the text

Add a modified table and insert data: add SQL to insert data in the text

gs_dump mydb1 -s -t t2  -f t2.ddl -p 25308

After the above content is modified, the result is as follows

Execute the text statement

gsql -d mydb1 -p 25308 -r  -f t2.ddl

Three, refresh the view

Perform exported v2, v3 views

gsql -d mydb1 -p 25308 -r  -f view.ddl

Then check whether the definition of the t2 table is modified, and see whether the view can be queried

\d t2
select * from v2;
select * from v3;

to sum up

Because the view uses the table, there will be a dependency relationship. When modifying the definition of the table that the view depends on, there is no way to modify it under certain circumstances. Here I think it can be achieved through the following steps: backup view definition to text -> backup table definition Go to text -> modify table definition in text -> backup table (ALTER TABLE XX RENAME TO XX_BAK) -> add modified table -> insert data -> backup view text refresh view

For the backup view definition step, you need to know what the related view of the table you need to modify is. This query process needs to use the pg_rewrite table and with recursive xx as to recursively obtain the relevant views. After the relevant views are obtained and backed up, the remaining steps are relatively simple.

 

Click to follow and learn about Huawei Cloud's fresh technology for the first time~

Guess you like

Origin blog.csdn.net/devcloud/article/details/108528596