tag:blogger.com,1999:blog-6230959840389481677.post-86430979081499213952008-04-14T05:27:00.000-07:002008-04-16T09:18:29.751-07:00Sobre comentarios y cómo actualizar secuenciasCuando se realizan cargas de datos en un esquema existente y no se utilizan las secuencias para asignar los valores de llave primaria, se produce un desfasaje entre identificadores y secuencias. Este desfasaje provoca errores de clave primaria ya existente, ya que los valores retornados por <span style="font-style: italic;">secuencia.NEXTVAL</span>, pueden ya existir entre los datos recientemente cargados.<br /><br />Para sincronizar las secuencias con los identificadores de llave primaria, puede crearse un script en PL/SQL el cual recree cada secuencia con su valor inicial según el máximo identificador de la tabla correspondiente. Para poder realizarlo, necesitamos primero tener una correspondencia entre tabla y secuencia, y en Oracle esta dependencia no existe.<br /><br />Es una buena oportunidad para comenzar a adoptar la buena práctica de usar comentarios sobre los objetos. Muchas veces, en el proceso de creación de una base de datos, este paso es omitido y considerado innecesario. Supuestamente, los objetos "no necesitan describirse" fundamentandose que el diseño es lo suficientemente explicativo y que los creadores van a permanecer durante todo el proceso de desarrollo, por lo tanto no vale la pena perder el tiempo describiendo los objetos. ¿No suenan estas excusas a holgazanería?<br /><br />No se deben ignorar estas máximas: 1) el diseñador puede abandonar el proyecto y 2) las personas externas que miren nuestro modelo pueden no entenderlo.<br /><br />En este sentido, el responsable de base de datos debe velar porque el modelo quede totalmente documentado y que no dependa de las personas que lo crearon, en definitiva que sea lo más auto-explicativo posible.<br /><br />Alguien puede considerar suficiente que la base de datos quede documentada en un diagrama o en un documento de word, pero ningún esfuerzo es suficiente si podemos hacer un poquito más. Los comentarios sobre objetos son almacenados en el diccionario de datos, y van a ser exportados junto a los objetos cuando estos sean migrados. Sin necesidad de consultar diagramas ni documentos, un programador en apuros puede hacer un DESCRIBE sobre una tabla en SQLPLUS, y saber al instante donde encontrar el dato que busca. Los comentarios ayudan a disipar las dudas más rapido, sobre todo a los que no están empapados en el modelo.<br /><br />Ahora si, volviendo al tema inicial, ¿cómo relacionamos una tabla con su secuencia? Precisamente, colocando en el comentario de la columna, el nombre de la secuencia que se utiliza:<pre style="color: rgb(0, 153, 0);">SQL> COMMENT ON cuentas.id_cuenta IS 'CUENTA_SEQ'</pre>Acabamos de documentar que para la columna <span style="font-style: italic;">id_cuenta</span> de la tabla <span style="font-style: italic;">cuentas</span>, se debe utilizar la secuencia <span style="font-style: italic;">cuenta_seq</span>. Observar que el efecto de esta sentencia es únicamente documental, todavía puede utilizarse la secuencia de la forma que se desee. La ventaja es que ahora podemos consultar la tabla de diccionario dba_col_comments en nuestros scripts.<br /><br />A modo de nota, mencionamos que tambien se pueden comentar tablas y vistas, con esta sintaxis:<pre style="color: rgb(0, 153, 0);">SQL> COMMENT ON cuentas 'Tabla para el registro de cuentas corrientes personales'</pre>Finalmente, el bloque que actualiza las secuencias utilizando los comentarios sobre columnas.<pre><span style="color: rgb(0, 153, 0);">DECLARE</span><br /><span style="color: rgb(0, 153, 0);"> v_max NUMBER(10) := 0;</span><br /><span style="color: rgb(0, 153, 0);"> v_desc varchar2(50);</span><br /><span style="color: rgb(0, 153, 0);">BEGIN</span><br /><br /><span style="color: rgb(0, 153, 0);"> FOR t IN (SELECT u.table_name,</span><br /><span style="color: rgb(0, 153, 0);"> u.column_name,</span><br /><span style="color: rgb(0, 153, 0);"> uc.comments secuencia</span><br /><span style="color: rgb(0, 153, 0);"> FROM user_tab_columns u,</span><br /><span style="color: rgb(0, 153, 0);"> user_col_comments uc</span><br /><span style="color: rgb(0, 153, 0);"> WHERE u.table_name = uc.table_name</span><br /><span style="color: rgb(0, 153, 0);"> AND u.column_name = uc.column_name</span><span style="color: rgb(0, 153, 0);"></span><br /><span style="color: rgb(0, 153, 0);"> AND u.column_name LIKE 'ID_%')</span><br /><span style="color: rgb(0, 153, 0);"> LOOP</span><br /><span style="color: rgb(0, 153, 0);"> EXECUTE IMMEDIATE 'SELECT MAX(' || t.column_name || ') FROM ' ||</span><br /><span style="color: rgb(0, 153, 0);">t.table_name INTO v_max;</span><br /><br /><span style="color: rgb(0, 153, 0);"> dbms_output.put_line('Eliminando secuencia '|| t.secuencia||'...');</span><br /><span style="color: rgb(0, 153, 0);"> v_desc := 'DROP SEQUENCE '|| t.secuencia;</span><br /><span style="color: rgb(0, 153, 0);"> EXECUTE IMMEDIATE 'DROP SEQUENCE '|| t.secuencia;</span><br /><br /><span style="color: rgb(0, 153, 0);"> EXECUTE IMMEDIATE 'CREATE SEQUENCE '|| t.secuencia ||' INCREMENT BY</span><br /><span style="color: rgb(0, 153, 0);">1 START WITH '|| (NVL(v_max,0) + 1);</span><br /><span style="color: rgb(0, 153, 0);"> dbms_output.put_line('Secuencia '|| t.secuencia||' recreada.');</span><br /><br /><span style="color: rgb(0, 153, 0);"> END LOOP;</span><br /><span style="color: rgb(0, 153, 0);">END;</span><br /></pre>Se requiere el permiso CREATE SEQUENCE por parte del ejecutor de este script.lferhttp://www.blogger.com/profile/00618392085702183279noreply@blogger.com