2011-05-16 10 views
6

En una base de datos federada de DB2 (basada en servidores remotos y apodos), necesito limpiar el modelo y volver a crearlo desde otra base de datos. Necesito eliminar todos los objetos de la base de datos, excepto esos servidores y apodos.¿Existe una manera eficiente de eliminar cada vista/función/tabla/sp de una base de datos?

Sé cómo recuperar la lista de objetos del esquema SYSCAT. Ahora necesito ejecutar las declaraciones DROP en cada una. Obviamente, las dependencias se interpondrán en el camino.

El enfoque de la fuerza bruta sería ejecutar las DROP en un ciclo hasta que todas hayan tenido éxito, pero dependiendo del orden (afortunado o no), podría llevar mucho tiempo.

¿Conoces una manera de ordenar eficientemente la declaración DROP para que el tiempo total para la eliminación sea el más corto posible?

No se espera una solución perfecta. Una solución razonablemente inteligente es lo suficientemente buena.

Gracias

Respuesta

1

Esta consulta es capaz de ordenar las declaraciones de acuerdo con el número total de elementos de los que dependen. El orden resultante funciona casi sin problemas, el segundo paso del enfoque de "fuerza bruta" contiene solo un puñado de objetos (de varios miles de objetos para eliminar).

problema, es muy lento ...

EDIT: Se cometió un error en la consulta que lo hizo regresar datos más o menos correcta, pero muy lentamente.

WITH FIRST_LEVEL_DEPENDENCIES (BSCHEMA, BNAME, DTYPE, DSCHEMA, DNAME) AS 
(
    SELECT T1.TABSCHEMA AS BSCHEMA, T1.TABNAME AS BNAME, T1.BTYPE, T1.BSCHEMA, T1.BNAME 
    FROM SYSCAT.TABDEP T1 
    WHERE T1.TABSCHEMA NOT LIKE 'SYS%' 
    AND T1.BTYPE <> 'N' 
    UNION ALL 
    SELECT T1.ROUTINESCHEMA AS BSCHEMA, T1.SPECIFICNAME AS BNAME, T1.BTYPE, T1.BSCHEMA, T1.BNAME 
    FROM SYSCAT.ROUTINEDEP T1 
    WHERE T1.ROUTINESCHEMA NOT LIKE 'SYS%' 
    AND T1.BTYPE <> 'N' 
    UNION ALL 
    SELECT T1.TABSCHEMA AS BSCHEMA, T1.TABNAME AS BNAME, 'T', T1.REFTABSCHEMA, T1.REFTABNAME 
    FROM SYSCAT.REFERENCES T1 
    WHERE T1.TABSCHEMA NOT LIKE 'SYS%' 
), 
RECURSIVE_DEPENDENCIES (LEVEL, BSCHEMA, BNAME, DTYPE, DSCHEMA, DNAME) AS 
(
    SELECT 1, U.BSCHEMA, U.BNAME, U.DTYPE, U.DSCHEMA, U.DNAME 
    FROM FIRST_LEVEL_DEPENDENCIES AS U 
    UNION ALL 
    SELECT LEVEL + 1, REC.BSCHEMA, REC.BNAME, U.DTYPE, U.DSCHEMA, U.DNAME 
    FROM RECURSIVE_DEPENDENCIES REC, 
      FIRST_LEVEL_DEPENDENCIES U 
    WHERE LEVEL < 6 
     AND U.BSCHEMA = REC.DSCHEMA 
     AND U.BNAME = REC.DNAME 
) 
SELECT BSCHEMA, BNAME, COUNT(*) 
    FROM RECURSIVE_DEPENDENCIES 
GROUP BY BSCHEMA, BNAME 
ORDER BY COUNT(*) 
2

Es posible que desee ver las referencias de cada tabla (que se pueden hacer con syscat.references acuerdo con http://www.ibm.com/developerworks/data/library/techarticle/dm-0401melnyk/) y construido un árbol de las dependencias usted mismo (debería ser factible por ejemplo, con las tablas temporales, si están restringidos a sql solamente). Entonces puedes caer desde el fondo de ese árbol.

Así que, básicamente, mi respuesta a su pregunta sería que para hacerlo rápido, simplemente ordene las tablas basadas en las referencias que tienen entre ellas antes de eliminarlas. Como no debería haber ciclos de dependencia, siempre debería poder elegir una tabla a la que no se haga referencia. Suelta y repite.

Es posible que también desee ver esta pregunta (¿similar?): DB2 cascade delete command? en caso de que desee eliminar los datos primero.

Si me equivoco en algún momento, corrígelo. Esta respuesta se basa en mis experiencias con otras bases de datos, por lo que podría no ser totalmente adecuada para DB2. A pesar de que se debe trabajar;)

+2

Gracias, pero el problema es que tengo que abandonar no sólo las tablas, pero vistas, funciones y procedimientos, así –

+2

Entonces me retire primero los puntos de vista, a continuación, procedimientos, entonces las tablas. Sin embargo, no tengo idea de cómo contar las referencias de las vistas (Internet dice 'SYSCAT.TABDEP' - http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm .db2.udb.admin.doc/doc/r0011297.htm) o procedimientos ('syscat.routines' debe listar los procedimientos y' sourceschema' debe señalar la tabla a la que pertenece?). Si en DB2 los procedimientos se analizan cuando se activan, debe poder eliminar todas las funciones una por una, incluso si se referencian entre sí. – Sorrow

+1

Mientras tanto, he llegado a una (casi) solución de trabajo. Para ser justos y porque proporcionó información valiosa, disfrute de la recompensa. Gracias;) –

0

yo no tengo una solución directa para DB2, pero puedo sugerir que:

A) En Microsoft SQL Server 2008, se ha resuelto el problema de eliminar (no soltar) la mesas respeto del orden teclas extranjera, en este enlace:

Generate Delete Statement From Foreign Key Relationships in SQL 2008?

B) en Oracle PL/SQL, se ha resuelto el problema de eliminar (no dejar caer) respetando las claves externas orden, en este enlace:

How to generate DELETE statements in PL/SQL, based on the tables FK relations?

Creo que puede organizar uno de estos dos scripts para obtener la solución para DB2.

¿Estás de acuerdo o no?

EDIT 1: En este enlace:

http://bytes.com/topic/db2/answers/183189-how-delete-tables-completely

puedo leer:

Robert, por qué no simplemente

LOAD FROM /dev/null of del replace into tablename NONRECOVERABLE 

- Este trunca la mesa muy rápidamente, no estoy seguro si es rec laims actualiza las estadísticas de espacio por defecto? Esto tiene la ventaja adicional de que no es necesario que realice las eliminaciones en el orden correcto de RI. (aunque se tenga que hacer un SET INTEGRITY después) OK

EDIT 2: Por favor, consulte los siguientes:

Dropping a schema and all of its contents in DB2 8.x

+2

Gracias, pero el problema es que no solo tengo que eliminar tablas, sino también vistas, funciones y procedimientos –

+1

http://bytes.com/topic/db2/answers/584023-cómo-drop-table-drop-related-views-functions-etc – UltraCommit

Cuestiones relacionadas