En mi empresa, diseñamos la base de datos con designer y luego generamos el esquema en la base de datos.Siempre llega un punto del desarrollo en que es bastante incómodo borrar el esquema y volver a generarlo, sobretodo por volver a llenar las tablas. A partir de ese momento tratamos siempre de sincronizar lo que tenemos en designer con lo que vamos volcando en la bd. Sin embargo esta sincronización es… humana.
Lo que hacemos entonces es generar el esquema de designer en otro usuario en blanco y luego comparamos los dos esquemas, el de desarrollo y el de designer. Para facilitarme esta tarea me he creado un script de informe de tablas y otro de informe de constraints. El resto de objetos no me preocupan porque tanto vistas como triggers como paquetes y demás los tengo en ficheros de texto. Lo que hago es lanzar los informes para las dos versiones de la base de datos y compararlos con algún programilla tipo diff.
Éste es el script para el informe de tablas. Muestra para cada tabla del usuario conectado el nombre de la tabla, un nº que indica el orden del campo en la clave primaria (si el campo pertenece a la clave), el nombre del campo, el tipo de dato con precisión, si es opcional o no y si tiene algún valor por defecto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /* Fichero: informe_tablas.sql http://www.tsoracle.com */ SET LINES 100 SET PAGES 20000 SET HEADING ON SET VERIFY OFF ------------------------- -- Definición de columnas ------------------------- COLUMN TABLE_NAME FORMAT A20 COLUMN CLAVE_PRIMARIA FORMAT A1 COLUMN COLUMN_NAME FORMAT A20 COLUMN TIPO FORMAT A15 COLUMN DEFECTO FORMAT A15 ---------- -- Selects ---------- BREAK ON TABLE_NAME SELECT M.TABLE_NAME, P.PK CLAVE_PRIMARIA, M.COLUMN_NAME, M.DATA_TYPE || DECODE( M.DATA_TYPE, /*************************************/ 'DATE', NULL, -- Poner aquí los tipos 'LONG', NULL, -- de varible para los 'BLOB', NULL, -- que no queramos ver 'CLOB', NULL, -- la precisión /*************************************/ '(' || TO_CHAR( NVL( M.DATA_PRECISION, M.DATA_LENGTH))|| DECODE( M.DATA_SCALE, NULL, NULL, ',' || TO_CHAR( M.DATA_SCALE ) ) || ')' ) TIPO, M.NULLABLE, M.DATA_DEFAULT DEFECTO FROM ( SELECT N.TABLE_NAME, L.COLUMN_NAME, L.POSITION PK FROM USER_CONS_COLUMNS L, USER_CONSTRAINTS N WHERE L.CONSTRAINT_NAME = N.CONSTRAINT_NAME AND N.CONSTRAINT_TYPE = 'P' ) P, -- Clave primaria USER_TAB_COLUMNS M WHERE M.TABLE_NAME = P.TABLE_NAME (+) AND M.COLUMN_NAME = P.COLUMN_NAME (+) ORDER BY M.TABLE_NAME, M.COLUMN_NAME / |
Y este es el informe de constraints. Tiene tres secciones. La primera de foreign keys, donde sólo me interesa el nombre de las dos tablas implicadas. En mi caso puedo descartar la posibilidad de tener diferentes columnas en la FK. Y el nombre me da igual.
La segunda sección es para las check constraints. Como las check de no nulidad ya las contrasto en el informe de tablas, aquí solo me preocupo de la tabla sobre la que se define la CHK y la propia condición.
Por último tengo una sección de claves únicas. En este caso particular me interesa el orden de las columnas ya que me interesa que los índices basados en estas claves sean correctos.
Es bastante pesado de lanzar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /* Fichero: informe_con.sql http://www.tsoracle.com */ PROMPT CLAVES FORÁNEAS... BREAK ON TABLE_NAME ON TABLA_FORANEA SELECT A.TABLE_NAME, B.TABLE_NAME TABLA_FORANEA FROM USER_CONSTRAINTS A, USER_CONSTRAINTS B WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_TYPE = 'R' ORDER BY A.TABLE_NAME, B.TABLE_NAME / PROMPT ************************************************************ PROMPT CHECKS SELECT TABLE_NAME, SEARCH_CONDITION FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'C' AND CONSTRAINT_NAME NOT LIKE 'SYS%' ORDER BY TABLE_NAME, SEARCH_CONDITION / PROMPT ************************************************************ PROMPT CLAVES ÚNICAS BREAK ON TABLE_NAME ON CONSTRAINT_NAME SELECT A.TABLE_NAME, A.CONSTRAINT_NAME, C.COLUMN_NAME FROM USER_CONS_COLUMNS C, USER_CONSTRAINTS A WHERE A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND A.CONSTRAINT_TYPE = 'U' ORDER BY A.TABLE_NAME, A.CONSTRAINT_NAME, C.POSITION / |