Combate de la aplicación GaussDB (DWS): operaciones DDL en las tablas a las que hace referencia la vista

Resumen: GaussDB (DWS) evolucionó a partir de Postgres. Al igual que Postgres, si una vista hace referencia a una tabla, algunas operaciones DDL no se pueden ejecutar directamente en ciertos escenarios.

Nota de antecedentes

GaussDB (DWS) evolucionó a partir de Postgres. Al igual que Postgres, si una vista hace referencia a una tabla, algunas operaciones DDL no se pueden realizar directamente en ciertos escenarios, como modificar el tipo de campo al que hace referencia la vista, eliminar la tabla, etc. Los campos recién agregados son operables La razón principal es que la vista se refiere a los campos de la tabla y la vista debe cambiarse si se modifica. Demostremos brevemente esta parte del contenido a continuación, qué sucederá cuando la tabla a la que hace referencia la vista realice operaciones DDL. Luego mire cómo modificar los campos de la tabla y así sucesivamente.

Generar contenido de experimentos

Construya 2 tablas de prueba y 3 vistas de prueba. Las declaraciones SQL construidas son las siguientes. Tenga en cuenta que todas las vistas usan los campos de t1 y no los 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;

Uno, borra la mesa

DROP TABLE t1;
DROP TABLE t2;

A juzgar por la solicitud del resultado de la ejecución, DROP TABLE no se ejecutó correctamente debido a la dependencia de la vista. Puede usar DROP ... CASCADE para eliminar vistas dependientes juntas, pero en general, no queremos eliminar vistas.

Dos, modifica el campo

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

A juzgar por las indicaciones de los resultados de la ejecución, la tabla t1 no pudo modificar el tipo de campo porque la vista v2 usó este campo, y la tabla t2 se modificó correctamente porque ninguna vista usó el campo t2, aunque la tabla t2 se usó en la vista, pero solo Para la asociación, el campo de la vista no utiliza el campo de la tabla t2, por lo que el tipo de campo de la tabla t2 se puede modificar correctamente.

Para lograr con éxito el objetivo en los experimentos posteriores, modifique la vista de v2 aquí para obtener el 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;

Tres nuevos campos

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

No hay restricciones para agregar campos, porque cuando se crea la vista, no hay forma de hacer referencia a campos que aún no existen. Revisamos la definición de la vista CREATE VIEW v1 AS SELECT * FROM t1; ¿Habrá alguna nueva información de campo para v1 en este momento? La respuesta es no, la vista debe actualizarse para tener nuevos 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;

¿Cómo modificar la definición de tabla a la que hace referencia la vista?

Entonces, la pregunta es, ¿cómo podemos modificar la definición de la tabla a la que hace referencia la vista similar al campo modificado anterior?

Creo que se puede dividir en los siguientes pasos.

Copia de seguridad de la definición de la vista en texto -> copia de seguridad de la definición de la tabla en texto -> modificar la definición de la tabla en texto -> copia de seguridad de la tabla (ALTER TABLE XX RENAME TO XX_BAK) -> agregar tabla modificada -> insertar datos -> copia de seguridad de la vista de actualización de texto

Uno de los más difíciles de obtener es, ¿a qué vistas hace referencia la tabla? Necesita usar pg_rewrite para obtener la relación de referencia, y con recursive .. para obtenerla cíclicamente.

Uno, definición de vista de respaldo en texto

Primero obtenga la vista del diseño de la tabla, este SQL es un poco complicado, aquí hay algunos pasos para explicar

Obtenga la relación de dependencia entre tablas y vistas a través 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

Obtenga todas las vistas relevantes a través de la instrucción recursiva xx como bucle

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 del resultado, t2, por lo que las vistas relacionadas son dos vistas v2 y v3.

Después de obtener la lista de vistas, hacemos una copia de seguridad de las dos vistas v2 y v3 en el texto, usando gs_dump.

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

2. Copia de seguridad de la definición de la tabla al texto -> modificar la definición de la tabla en el texto -> copia de seguridad de la tabla (ALTER TABLE XX RENAME TO XX_BAK) -> agregar la tabla modificada e insertar datos

Copia de seguridad de la definición de la tabla en texto: use gs_dump para exportar la estructura de la tabla de t2 a un archivo

Modifique la definición de la tabla en el texto: modifique el tipo de campo del nombre del varchar (30) original a varchar (50)

Tabla de respaldo (ALTER TABLE XX RENAME TO XX_BAK): agregue la acción ALTER TABLE RENAME en el texto

Agregar una tabla modificada e insertar datos: agregue SQL para insertar datos en el texto

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

Después de modificar el contenido anterior, el resultado es el siguiente

Ejecuta la declaración de texto

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

Tres, refresca la vista

Realizar vistas exportadas v2, v3

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

Luego, verifique si la definición de la tabla t2 está modificada y vea si la vista se puede consultar

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

para resumir

Debido a que la vista usa la tabla, habrá una relación de dependencia. Al modificar la definición de la tabla de la que depende la vista, no hay forma de modificarla bajo ciertas circunstancias. Aquí creo que se puede lograr mediante los siguientes pasos: definición de la vista de respaldo al texto -> definición de la tabla de respaldo Ir al texto -> modificar la definición de la tabla en el texto -> tabla de respaldo (ALTER TABLE XX RENAME TO XX_BAK) -> agregar tabla modificada -> insertar datos -> vista de respaldo de actualización de texto

Para el paso de definición de la vista de respaldo, necesita saber cuál es la vista relacionada de la tabla que necesita modificar. Este proceso de consulta necesita usar la tabla pg_rewrite y con xx recursivo para obtener de forma recursiva las vistas relevantes. Una vez obtenidas y respaldadas las vistas relevantes, los pasos restantes son relativamente simples.

 

Haga clic para seguir y conocer la nueva tecnología de Huawei Cloud por primera vez ~

Supongo que te gusta

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