GaussDB (DWS) de combate de aplicativos: operações DDL nas tabelas referenciadas pela visualização

Resumo: GaussDB (DWS) evoluiu do Postgres.Como o Postgres, se uma tabela é referenciada por uma visão, algumas operações DDL não podem ser executadas diretamente em um cenário específico.

Nota de fundo

GaussDB (DWS) evoluiu do Postgres. Como o Postgres, se uma tabela for referenciada por uma visão, algumas operações DDL não podem ser realizadas diretamente em certos cenários, como modificar o tipo de campo referenciado pela visão, deletar a tabela, etc. Os campos recém-adicionados estão operacionais. O principal motivo é que a visão se refere aos campos da tabela e a visão precisa ser alterada se for modificada. Vamos demonstrar brevemente essa parte do conteúdo a seguir, o que acontecerá quando a tabela referenciada pela visualização realizar operações DDL. Em seguida, veja como modificar os campos da tabela e assim por diante.

Gerar conteúdo experimental

Crie 2 tabelas de teste e 3 visualizações de teste. As instruções SQL construídas são as seguintes. Observe que todas as visualizações usam os campos de t1 e não os campos de 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;

Um, exclua a tabela

DROP TABLE t1;
DROP TABLE t2;

A julgar pelo prompt do resultado da execução, DROP TABLE não foi executado com êxito devido à dependência da visualização. Você pode usar DROP ... CASCADE para deletar visões dependentes juntas, mas em geral, não queremos deletar visões.

Dois, modifique o campo

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

A julgar pelos prompts dos resultados da execução, a tabela t1 falhou em modificar o tipo de campo porque a visão v2 usou este campo, e a tabela t2 foi modificada com sucesso porque nenhuma visão usou o campo t2, embora a tabela t2 tenha sido usada na visão, mas apenas Para associação, o campo da visão não usa o campo da tabela t2, portanto o tipo de campo da tabela t2 pode ser modificado com sucesso.

A fim de atingir o objetivo com sucesso nos experimentos subsequentes, modifique a visualização de v2 aqui para obter o campo de 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;

Três, novos campos

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

Não há restrições para adicionar campos, porque quando a visão é criada, não há como referenciar campos que ainda não existem. Revisamos a definição da visualização CREATE VIEW v1 AS SELECT * FROM t1; Haverá alguma nova informação de campo para v1 neste momento? A resposta é não, a visão precisa ser atualizada para ter novos campos

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;

Como modificar a definição da tabela referenciada pela visão?

Portanto, a questão é: como podemos modificar a definição da tabela referenciada pela visão semelhante ao campo modificado acima?

Acho que pode ser dividido nas seguintes etapas

Definição da visualização de backup para texto -> definição de tabela de backup para texto -> modificar definição de tabela no texto -> tabela de backup (ALTER TABLE XX RENAME TO XX_BAK) -> adicionar tabela modificada -> inserir dados -> visualização de atualização de texto de visualização de backup

Uma das mais difíceis de obter é: quais visualizações são referenciadas pela tabela? Ele precisa usar o pg_rewrite para obter o relacionamento de referência, e com recursivo .. para obtê-lo ciclicamente.

Um, definição de visualização de backup para texto

Primeiro obtenha a visão do design da tabela, este SQL é um pouco complicado, aqui estão alguns passos para explicar

Obtenha a relação de dependência entre tabelas e visualizações por meio de 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

Obtenha todas as visualizações relevantes por meio do com xx recursivo como instrução de loop

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;

A partir do resultado, t2 então as visualizações relacionadas são duas visualizações v2 e v3.

Depois de obter a lista de visualizações, fazemos backup das duas visualizações v2 e v3 para o texto, usando gs_dump.

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

2. Fazer backup da definição da tabela para texto -> modificar a definição da tabela no texto -> fazer backup da tabela (ALTER TABLE XX RENAME TO XX_BAK) -> adicionar tabela modificada e inserir dados

Definição da tabela de backup para texto: use gs_dump para exportar a estrutura da tabela de t2 para um arquivo

Modifique a definição da tabela no texto: modifique o tipo de campo do nome do varchar (30) original para varchar (50)

Tabela de backup (ALTER TABLE XX RENAME TO XX_BAK): adicione a ação ALTER TABLE RENAME no texto

Adicione uma tabela modificada e insira dados: adicione SQL para inserir dados no texto

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

Depois que o conteúdo acima é modificado, o resultado é o seguinte

Execute a declaração de texto

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

Três, atualize a vista

Executar visualizações exportadas v2, v3

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

Em seguida, verifique se a definição da tabela t2 foi modificada e se a visualização pode ser consultada

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

Resumindo

Como a visualização usa a tabela, haverá uma relação de dependência. Ao modificar a definição da tabela da qual a visualização depende, não há como modificá-la em certas circunstâncias. Aqui eu acho que isso pode ser alcançado pelas seguintes etapas: definição de visualização de backup para texto -> definição de tabela de backup Vá para texto -> modificar a definição da tabela no texto -> tabela de backup (ALTER TABLE XX RENAME TO XX_BAK) -> adicionar tabela modificada -> inserir dados -> visualização de backup visualização de atualização de texto

Para a etapa de definição da visualização de backup, você precisa saber qual é a visualização relacionada da tabela que você precisa modificar. Este processo de consulta precisa usar a tabela pg_rewrite e com xx recursivo para obter recursivamente as visualizações relevantes. Depois que as visualizações relevantes são obtidas e seu backup, as etapas restantes são relativamente simples.

 

Clique para seguir e aprender sobre a nova tecnologia da Huawei Cloud pela primeira vez ~

Acho que você gosta

Origin blog.csdn.net/devcloud/article/details/108528596
Recomendado
Clasificación