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 ~