Cómo encontrar reglas ocultas al migrar PL/SQL
Una migración de PL/SQL funciona al inventariar paquetes, triggers, estado de sesión y efectos, y demostrar la paridad antes de mover cada regla.

La parte peligrosa de una migración de PL/SQL no es convertir la sintaxis. Es descubrir de qué comportamiento de la base de datos depende la empresa antes de que la base antigua deje de proporcionarlo. Los cuerpos de paquetes, los triggers de fila y de sentencia, las llamadas programadas, el estado de sesión y las rutas de error pueden contener reglas que no aparecen en ningún repositorio de la aplicación.
Una migración creíble trata el esquema Oracle como un sistema ejecutable, no como un contenedor de procedimientos almacenados. El inventario establece qué existe. Las trazas establecen qué se ejecuta. Las pruebas de caracterización establecen qué significa. Solo entonces puede un equipo decidir si una regla debe vivir en un servicio Go, un núcleo Rust, un cliente TypeScript, una restricción de Postgres o en ninguna parte.
Inventariar el esquema como sistema ejecutable
Empiece con una extracción repetible desde una base con forma de producción, porque una copia del repositorio rara vez coincide con lo que Oracle ejecuta. Hay correcciones urgentes que se compilan desde un puesto de trabajo, objetos con ediciones ocultos tras sinónimos y permisos que determinan qué tablas puede tocar el código con derechos del definidor. Exporte DDL, código fuente, estado, metadatos de triggers, tareas, sinónimos, permisos y dependencias en una captura con fecha y hora.
La vista ALL_SOURCE de Oracle expone el texto de los procedimientos, funciones, paquetes, cuerpos de paquetes, triggers, tipos y cuerpos de tipos accesibles. Use DBA_SOURCE cuando la cuenta de evaluación tenga los privilegios necesarios y el alcance cubra varios esquemas. La siguiente consulta produce un inventario estable del código en lugar de un directorio lleno de archivos anónimos:
SELECT owner,
type,
name,
COUNT(*) AS source_lines
FROM dba_source
WHERE owner IN ('BILLING', 'ORDERS', 'FINANCE')
GROUP BY owner, type, name
ORDER BY owner, type, name;
El resultado contiene una fila por objeto almacenado: OWNER, TYPE, NAME y SOURCE_LINES. Un paquete aparece en filas separadas como PACKAGE y PACKAGE BODY. No las una. La especificación es un contrato público; el cuerpo contiene rutinas privadas, código de inicialización y casi todos los detalles de implementación.
Extraiga el DDL de creación además del texto. DBMS_METADATA.GET_DDL conserva detalles del objeto que se pierden al concatenar ALL_SOURCE.TEXT. Para un paquete, solicite PACKAGE_SPEC y PACKAGE_BODY; para un trigger, TRIGGER. Guarde junto a cada archivo la versión de la base, el esquema, el estado del objeto, la edición y la hora de extracción. El equipo debe poder responder qué definición compilada produjo un resultado capturado.
Incluya los objetos no válidos y los errores de compilación en vez de filtrarlos. Un trigger no válido aún puede bloquear la sentencia que lo dispara, y un paquete invalidado por un cambio de tabla puede recompilarse bajo demanda en condiciones que el repositorio nunca reprodujo. DBA_OBJECTS.STATUS y DBA_ERRORS convierten esas condiciones en pruebas. Inventaríe también vistas materializadas, columnas virtuales, índices basados en funciones, políticas de acceso detallado y expresiones predeterminadas que llamen funciones. No todos son contenedores PL/SQL, pero cualquiera puede invocar lógica almacenada o depender de ella.
Tome una segunda captura después del periodo de observación. Una comparación suele revelar herramientas de despliegue, tareas nocturnas o administradores que sustituyen cuerpos de paquetes fuera del proceso formal de publicación. No empiece una reescritura contra un objetivo móvil sin congelar esos cambios o incorporarlos a la extracción y las pruebas.
El recuento no es la puntuación de riesgo. Un trigger de seis líneas que cambia en silencio un periodo contable puede importar más que un paquete de informes de 9.000 líneas. El inventario delimita el espacio de búsqueda y permite detectar cambios; no dice qué código posee significado empresarial.
Encontrar los puntos de entrada antes de leer paquetes
Rastree quién puede invocar PL/SQL y qué eventos de base lo hacen, y lea hacia dentro desde esos puntos. Leer paquetes por orden alfabético desperdicia tiempo porque las utilidades privadas y el código muerto parecen tan importantes como las rutas usadas en cada pedido.
Construya una tabla de puntos de entrada con al menos estas fuentes:
- Llamadas de aplicación que contengan bloques anónimos,
CALLo nombres cualificados de procedimientos de paquete - Triggers DML, DDL, de inicio de sesión, de arranque e instead-of habilitados
- Tareas del planificador y entradas de colas de trabajos antiguas
- Vistas y funciones invocadas desde sentencias SQL
- Herramientas externas, informes, cargadores de archivos y scripts operativos
Para los triggers, capture algo más que el cuerpo. Consulte en DBA_TRIGGERS los campos TRIGGERING_EVENT, TRIGGER_TYPE, TABLE_OWNER, TABLE_NAME, STATUS, WHEN_CLAUSE y ACTION_TYPE. Cruce ese inventario con las tablas que escribe cada flujo de aplicación. Una regla adjunta a ORDERS puede ejecutarse cuando un script de soporte actualiza la tabla aunque el servicio principal nunca llame al trigger por su nombre.
La guía de Oracle sobre triggers PL/SQL contiene dos puntos que afectan al diseño de la migración. Los triggers se ejecutan automáticamente para sus eventos definidos con independencia del usuario o aplicación que emita la sentencia. El código tampoco debe depender del orden en que una sentencia SQL procesa las filas. Si el sistema existente incumple el segundo punto mediante una variable global de paquete que un trigger de fila actualiza, el comportamiento ya puede ser no determinista. Conserve los resultados observados para la paridad, pero marque la dependencia para un rediseño explícito en vez de aceptarla como requisito.
La inicialización de paquetes es otro punto de entrada que suele omitirse. Oracle ejecuta la sección de inicialización del cuerpo la primera vez que una sesión hace referencia al paquete. Si carga configuración, calcula una fecha de negocio o establece una variable, la primera llamada pública tiene un prólogo invisible. Busque la región final BEGIN ... END de cada cuerpo y registre sus lecturas, escrituras, excepciones y dependencias de contexto.
Termine esta fase con un grafo de llamadas cuyas raíces sean eventos operativos y no meros nombres de objetos. Cada raíz debe nombrar el actor que inicia, la transacción, la forma de entrada, el paquete o trigger alcanzado, las tablas leídas y escritas, los efectos externos y los errores observados. Las celdas desconocidas son útiles: muestran exactamente dónde faltan pruebas de ejecución.
Los procedimientos de paquete sobrecargados necesitan firmas, no solo nombres. Recoja posición, modo y tipo de argumentos, presencia de valor predeterminado e identificador de sobrecarga desde ALL_ARGUMENTS, y relacione esas firmas con quienes llaman. Los controladores pueden enlazar por posición, exponer tipos de colección de Oracle o depender de la forma de un cursor OUT. Sustituir ORDER_API.SUBMIT por un endpoint HTTP cambia un contrato de comunicación aunque el resultado empresarial sea idéntico. Catalogue ese trabajo de compatibilidad aparte de la recuperación de reglas.
Las dependencias estáticas no revelan todo el programa
Trate ALL_DEPENDENCIES como un límite inferior útil, porque Oracle no puede registrar una dependencia normal de compilación para un nombre de objeto construido dentro de SQL dinámico. Los sinónimos, enlaces de base de datos, resolución con derechos del invocador, contextos de aplicación y cadenas guardadas en tablas amplían la brecha.
Empiece con el grafo estático:
SELECT owner,
name,
type,
referenced_owner,
referenced_name,
referenced_type
FROM dba_dependencies
WHERE owner IN ('BILLING', 'ORDERS', 'FINANCE')
ORDER BY owner, name, referenced_owner, referenced_name;
Después busque en el código comportamientos que el grafo no resuelve con fiabilidad: EXECUTE IMMEDIATE, DBMS_SQL, OPEN ... FOR, marcadores de enlaces, SYS_CONTEXT, pragmas de transacción autónoma, paquetes de archivos y colas, llamadas de correo y manejadores de excepciones que escriban. Busque nombres configurados de procedimientos en los datos si la aplicación distribuye llamadas según metadatos.
El SQL dinámico exige revisar la procedencia de sus cadenas. Para cada sentencia, identifique la plantilla, todos los identificadores sustituidos, los valores enlazados, el esquema usado para resolver nombres y ejemplos capturados durante la ejecución. Una línea como EXECUTE IMMEDIATE l_sql USING p_id dice poco hasta saber si l_sql actualiza una partición conocida o llama a un paquete específico del inquilino seleccionado en una tabla de configuración.
El comportamiento de los privilegios pertenece al mismo análisis. Un paquete sin AUTHID CURRENT_USER explícito usa por defecto derechos del definidor, por lo que sus referencias de objeto sin cualificar y sus permisos no se comportan como una consulta de servicio emitida con la identidad del usuario final. Registre AUTHID, permisos directos, roles, sinónimos y lecturas del contexto de aplicación. Mover la rutina a un servicio puede eliminar por accidente una frontera legítima de autoridad o dar a la cuenta de servicio mucho más acceso del que tuvo el paquete.
No responda instrumentando cada línea. Añada observación en los límites: entrada y salida del paquete, resultado de la transacción, disparo del trigger, forma de las sentencias dinámicas y llamadas externas. Use un identificador de correlación que sobreviva desde la petición de la aplicación hasta los metadatos de sesión. Capture valores enlazados solo cuando la política lo permita y oculte los campos sensibles antes de almacenarlos. El objetivo es un mapa de comportamiento, no una segunda base de producción llena de secretos.
El análisis estático también exagera algunas dependencias. El cuerpo de un paquete puede contener rutinas abandonadas que hacen referencia a tablas sin uso desde hace años. Marcar cada arista como activa hace crecer el alcance más rápido que las pruebas. Mantenga grafos separados para «puede llamar» y «llamó», y conserve junto al segundo la ventana de observación y la carga. Que algo no aparezca en una traza no demuestra que sea código muerto, pero permite exigir un propietario o una prueba diseñada antes de reconstruirlo.
Convertir los hallazgos en un registro de comportamiento
Un registro de comportamiento convierte los hallazgos del código en contratos comprobables. Cada fila describe una regla con significado externo e incluye entradas, salidas, cambios de estado, fallos y pruebas. Sin este artefacto intermedio, los arquitectos tienden a asignar paquetes enteros a componentes de destino y trasladan límites accidentales al reemplazo.
Piense en un procedimiento de paquete que confirma una factura. Valida el estado, calcula el impuesto desde tablas de cliente y vigencia, inserta asientos contables, cambia el estado de la factura y encola una notificación. No es una sola regla. El registro debe separar admisibilidad, selección fiscal, contabilización, transición de estado e intención de notificar, porque cada una puede necesitar un destino y un oráculo de prueba distintos.
Una entrada útil del registro contiene:
- Identificador de la regla y una declaración clara con su ubicación en el código
- Evento que la dispara y estado necesario de sesión, tablas y paquete
- Entradas, salidas, escrituras, mensajes, archivos y confirmaciones o reversiones
- Casos límite, errores de Oracle, códigos personalizados y comportamiento de reintentos
- Pruebas del código, trazas, ejemplos de producción y un responsable que apruebe
Asigne a cada regla un estado como observada, inferida, discutida, aprobada u obsoleta. El código por sí solo respalda «inferida» cuando la rama podría ser inalcanzable. Una ejecución capturada respalda «observada». Finanzas u operaciones pueden aprobar si un comportamiento extraño es contractual. Esto evita la reunión habitual en que un resultado sorprendente se llama error solo porque el nuevo diseño no lo reprodujo.
Separe las reglas empresariales de la mecánica de la base. «Una factura no se puede contabilizar en un periodo cerrado» es una regla. «Un trigger BEFORE INSERT consulta PERIOD_CONTROL y lanza -20041» es una implementación. «Asignar UPDATED_AT desde SYSTIMESTAMP» puede ser una política de persistencia. «Incrementar una global del paquete» puede ser una solución provisional. La consecuencia importa: migre la regla, pruebe el mecanismo antiguo y consérvelo solo cuando su semántica forme parte del contrato.
Registre también el espacio negativo. Si las actualizaciones SQL directas evitan una validación de aplicación pero siguen alcanzando un trigger, ese trigger define el límite real de cumplimiento. Si un paquete confirma internamente, quienes llaman no pueden revertir todo el flujo aunque su código parezca controlar la transacción. Estos hechos incómodos determinan el cambio y no deben suavizarse en documentos de arquitectura.
Haga ejecutables los desacuerdos cuando sea posible. Si operaciones afirma que se permite una cancelación retroactiva y finanzas dice que no, conserve ambos ejemplos candidatos, sus resultados esperados y las condiciones de datos. Pida al responsable que apruebe un resultado en el registro. Un requisito en prosa como «gestionar correctamente la retroactividad» sobrevivirá a todas las revisiones sin dar al equipo nada que comparar.
El registro también controla la eliminación. Cuando nadie puede aportar un actor invocador, una ejecución observada, un motivo regulatorio o un ejemplo aprobado para una rutina, márquela como candidata a retirarse. Conserve el código antiguo y demuestre que ningún llamador la alcanza; no invierta tiempo en traducirla solo porque compila.
Probar transacciones, no funciones aisladas
Las pruebas de caracterización deben manejar el sistema antiguo a través de sus límites públicos reales y comparar el resultado completo de la transacción. Una prueba unitaria de una función fiscal privada no ve efectos de triggers, estado de paquetes, ajustes NLS, consumo de secuencias, traducción de excepciones ni comportamiento de confirmación.
Cree un entorno Oracle desechable a partir de un conjunto de datos enmascarado y coherente en sus referencias. Fije explícitamente las entradas de sesión: zona horaria, NLS_DATE_FORMAT, caracteres numéricos, esquema actual, contexto de aplicación y fuentes de fecha de negocio. Restablezca tablas y secuencias a una base conocida en cada caso cuando importen los identificadores exactos. Use sesiones separadas para pruebas que involucren estado de paquete.
Oracle documenta que cada sesión recibe su propia instancia de un paquete y que los valores de un paquete con estado suelen persistir durante la sesión. Recompilar un paquete con estado ya instanciado puede descartar ese estado y provocar ORA-04068 en la llamada siguiente. Un pool de conexiones convierte así las globales de paquete en memoria oculta por conexión. La suite necesita casos para una sesión nueva, llamadas repetidas en una sesión, dos sesiones simultáneas, reutilización de una sesión del pool, reversión e invalidación del paquete si los despliegues de producción pueden causarla.
Para cada prueba, capture un registro de observación normalizado:
{
"case": "closed-period-credit",
"entry": "billing.invoice_api.post_credit",
"result": {"status": "error", "oracle_code": -20041},
"tables": {"invoice": [], "ledger_entry": []},
"events": [],
"transaction": "rolled_back"
}
La nueva implementación debe producir la misma observación empresarial, no necesariamente la misma pila de Oracle o valor de secuencia. Normalice los identificadores generados a alias estables, compare el dinero con su escala declarada, ordene conjuntos solo si el orden es contractual y compare marcas de tiempo con la precisión expuesta por la interfaz antigua. Mantenga códigos personalizados exactos cuando los llamadores bifurquen según ellos; en otro caso, asígnelos a un error de dominio explícito en el límite de compatibilidad y pruebe esa asignación.
Pruebe fallos y trabajo parcial de forma deliberada. Fuerce una clave duplicada después de insertar una auditoría. Deje no disponible la cola de notificaciones. Lance una excepción desde un trigger de fila tras procesar varias filas. Ejercite DML masivo, donde el momento de los triggers por sentencia y por fila cambia lo que sobrevive. Un resultado feliz no revela una transacción autónoma que escribió una fila de auditoría aunque se revirtiera la transacción empresarial.
Un fallo común se desarrolla así: una aplicación abre una transacción, llama a un paquete para reservar crédito, inserta un pedido y revierte cuando falla la asignación de inventario. El paquete actualiza una caché global de «crédito disponible» y una rutina autónoma de auditoría confirma un registro de reserva. La actualización de tabla se revierte, pero el valor del paquete queda en esa sesión del pool y el registro de auditoría queda confirmado. Un reemplazo que envuelva todo en una transacción limpia de servicio se comportará de otro modo en la petición siguiente. El registro debe decidir si esos restos son necesarios, defectos tolerados o comportamiento que retirar, y la suite debe fijar la elección aprobada.
El orden de triggers necesita casos propios cuando varios comparten tabla y punto temporal. Oracle ofrece FOLLOWS y, de manera limitada, PRECEDES para relaciones declaradas, pero los triggers sin conexión no obtienen un orden total fiable. Capture el DDL y pruebe los resultados finales con sentencias de varias filas. No escriba una prueba de destino que exija una secuencia accidental salvo que la fuente la declare y el resultado empresarial dependa de ella.
Mida la cobertura por reglas del registro y puntos de entrada, no por líneas PL/SQL. Una prueba puede ejecutar cada línea de un paquete fiscal sin demostrar qué tasa gana en un límite de vigencia. Por el contrario, una matriz compacta de fechas, jurisdicciones, clases de cliente y estados de reversión puede caracterizar el contrato dejando ramas defensivas sin visitar. Mantenga la cobertura de código ordinaria como diagnóstico, no como criterio de aceptación.
El tráfico de producción aporta casos, no la verdad
El tráfico de producción registrado es la mejor fuente de entradas realistas, pero no define la especificación completa. Sobrerrepresenta los casos normales, contiene accidentes históricos y rara vez captura las entradas contrarias que deberían fallar.
Registre peticiones en el límite donde aún es visible el significado de la entrada. Incluya la operación llamada, llamadas ordenadas dentro de una transacción, parámetros saneados, contexto de sesión relevante, clase de resultado e identificadores para recoger filas afectadas. Para puntos de entrada gobernados por SQL, registre valores enlazados y agrupación de transacciones en lugar de solo texto SQL. Para lotes, conserve la forma del archivo y totales de control sin copiar datos restringidos a un almacén de pruebas sin control.
Reproduzca cada caso contra las implementaciones antigua y nueva desde estados iniciales equivalentes. Compare valores devueltos, errores, cambios de base, eventos emitidos y límites de confirmación. Si los resultados difieren, clasifique el motivo antes de cambiar código: regla ausente, rediseño intencionado, falta de determinismo, datos de prueba defectuosos o un defecto antiguo que el responsable decidió retirar.
El tráfico debe complementarse con casos diseñados desde el registro. Añada fechas límite, valores nulos, peticiones duplicadas, reintentos tras un timeout, escala numérica máxima, usuarios no autorizados, periodos contables cerrados y actualizaciones simultáneas de la misma entidad. Añada comprobaciones metamórficas cuando sea difícil enumerar un resultado exacto. Por ejemplo, contabilizar y luego revertir una factura admisible debería dejar en cero su efecto neto en el libro, sujeto a la regla antigua de redondeo.
Muestree por comportamiento además de por volumen. Un millón de pedidos correctos añade pocas pruebas cuando se repiten las formas de entrada, mientras que un cierre anual, un cambio de horario o un ajuste manual puede cubrir una rama única. Conserve deliberadamente los casos raros y proporcióneles datos estables. La frecuencia de producción debe guiar las pruebas de rendimiento; la consecuencia empresarial y la singularidad de la rama deben guiar la cobertura de paridad.
CodeHero usa un banco de paridad contra tráfico de producción registrado al reescribir sistemas, incluidos entornos PL/SQL, y lee los lenguajes que rodean el código de base como un único código fuente. Es importante porque el contrato de un procedimiento almacenado suele estar repartido entre un llamador Java, un script programado y las filas que cambia un trigger. El banco aún necesita los casos negativos y límite del registro; el volumen reproducido no prueba un comportamiento que el tráfico nunca ejercitó.
No envíe entradas capturadas de producción a un modelo o entorno de pruebas sin una decisión sobre clasificación de datos. El enmascaramiento debe conservar las propiedades que usan las reglas, como grupos de igualdad, orden de fechas, prefijos de cuenta e integridad referencial. Sustituir cada valor por texto aleatorio puede proteger la identidad mientras destruye justo los casos que debe probar la migración.
Colocar cada regla en su límite fiable más estrecho
Coloque una regla donde deba pasar toda escritura relevante y donde el equipo pueda observarla y probarla. Esto suele producir una arquitectura repartida, no una campaña para llevar todo PL/SQL a servicios o mantener todas las reglas en Postgres.
Use restricciones de base para invariantes expresables contra una fila o el estado relacional: nulabilidad, unicidad, claves foráneas y rangos comprobables. Las restricciones cubren a todos los escritores y aportan hechos útiles al planificador. No sustituya una restricción declarativa por código de aplicación solo porque el código parezca más fácil de versionar.
Conserve una función pequeña o un trigger solo cuando la regla pertenezca realmente a todos los escritores, no pueda expresarse de forma declarativa y esos escritores vayan a seguir evitando un único servicio. Haga que los efectos sean explícitos y mínimos. Un trigger que marque contexto de auditoría puede ser defendible; otro que calcule precios, escriba cinco tablas, envíe un mensaje y confirme de forma autónoma oculta un flujo que necesita una API con propietario.
Ponga las reglas de flujo en un servicio cuando coordinen agregados, llamen a sistemas externos, necesiten reintentos explícitos o requieran observación a nivel de producto. El servicio debe controlar la transacción o usar un patrón outbox para el trabajo posterior a la confirmación. No publique un mensaje antes del commit esperando que los consumidores toleren una reversión. No permita que lo emitan a la vez el trigger de compatibilidad y el nuevo servicio.
Ponga núcleos numéricos en Rust solo cuando el trabajo se beneficie de un límite de cálculo estrecho y comprobable de manera independiente. Ponga reglas de presentación en clientes TypeScript solo cuando el servidor o la base sigan imponiendo el invariante. Un botón deshabilitado ofrece información útil; no es autorización.
Postgres no es Oracle con otra ortografía. El estado de sesión de los paquetes no tiene un destino directo, las cadenas vacías y los nulos difieren, las excepciones y transacciones autónomas se comportan de otro modo y el orden de triggers merece diseño explícito. Modernice estos límites en vez de transliterarlos. Una petición de servicio, una transacción y un registro de outbox explícitos son más fáciles de razonar que una red nueva de callbacks ocultos.
Un registro de decisión para cada regla debe nombrar propietario elegido, punto de cumplimiento, plan de compatibilidad, casos de prueba y condición para retirar la implementación Oracle. Si nadie posee una regla, no se ha movido. Si dos componentes la aplican, documente cuál manda y cuánto durará la duplicación.
Cambiar sin ejecutar reglas dos veces
El mayor riesgo del cambio es el comportamiento duplicado: el nuevo servicio aplica una regla mientras un trigger antiguo la ejecuta otra vez en silencio. Aparecen asientos contables duplicados, notificaciones repetidas, marcas de tiempo en conflicto o una actualización que supera un validador y falla en el otro.
Construya una matriz de activación regla por regla. Las filas son identificadores del registro. Las columnas son aplicación antigua, paquete Oracle, trigger Oracle, servicio nuevo, restricción o trigger Postgres y consumidor de eventos. Marque para cada estado de despliegue un ejecutor con autoridad y cualquier observador. Rechace estados con dos ejecutores salvo que la operación sea demostrablemente idempotente y la duplicación sea deliberada.
La ejecución en sombra no debe modificar el estado compartido de producción. Ejecute la nueva lógica de decisión en modo de observación, o reproduzca entradas capturadas contra un destino aislado, y compare su resultado propuesto con el resultado confirmado de Oracle. Para flujos con efectos externos, sustituya el destino por un sumidero que registre la intención sin enviar correo, cargar una cuenta ni publicar en un tema activo.
Las escrituras dobles son populares porque parecen facilitar el rollback. Suelen crear dos modos de fallo y una fuente de verdad ambigua. Prefiera un escritor con captura de cambios u outbox, con retardo de replicación medido y consulta de conciliación. Si las escrituras dobles temporales son inevitables, asigne una clave de idempotencia en el límite de la petición original y persista el resultado a ambos lados.
Cambie por punto de entrada coherente, no por archivo de paquete arbitrario. Mueva el procedimiento, los triggers de los que depende, su semántica transaccional y sus efectos posteriores como una unidad de comportamiento. Bloquee o redirija escritores directos que eviten la nueva autoridad. Mantenga una fachada de compatibilidad solo cuando los llamadores necesiten tiempo, y haga que invoque al nuevo propietario en vez de contener una segunda implementación.
El rollback debe especificar la dirección de los datos, no solo la del despliegue. Indique qué sistema conserva la autoridad, qué escrituras se detienen, cómo vuelven a Oracle los registros exclusivos del destino si es preciso y cómo se concilian los efectos emitidos. Revertir un contenedor no revierte el negocio después de que dinero, mensajes o archivos hayan salido de la transacción.
Retirar Oracle es una prueba de aceptación
Una migración de PL/SQL termina cuando la empresa puede operar con el comportamiento pertinente de Oracle deshabilitado y el equipo puede demostrar por qué los resultados siguen siendo correctos. «Todos los cuerpos de paquetes traducidos» no dice nada sobre triggers, tareas, globales de sesión, scripts operativos o llamadores que aún se conectan directamente.
Para cada punto de entrada, exija una cadena cerrada desde el actor que inicia hasta una regla aprobada, un propietario de destino, casos de caracterización superados, estado de cambio y observación en producción. Repita el inventario del esquema y compárelo con la captura inicial. Todo trigger aún habilitado, permiso de ejecución, tarea programada, sinónimo y conexión de aplicación necesita un motivo explícito.
Después realice una prueba de denegación en un entorno con forma de producción. Revoque la ruta antigua o deshabilite el trigger migrado, ejecute toda la suite de tráfico y casos diseñados y supervise los intentos de conexión. La prueba debe fallar si alguna ruta todavía depende de Oracle. Una ejecución satisfactoria aporta más pruebas que una hoja donde cada responsable marcó su fila como terminada.
Conserve la captura del código, el registro de comportamiento, las observaciones normalizadas, las decisiones y los resultados de paridad como un único conjunto de pruebas. Explican más que el funcionamiento del código antiguo. Muestran qué rarezas aceptó la empresa, qué defectos retiró y dónde vive ahora cada regla superviviente.
CodeHero entrega reescrituras de sistemas antiguos en menos de 30 días, pero la velocidad no justifica adivinar el comportamiento de la base. La forma de avanzar rápido es inspeccionar todo el sistema a la vez, convertir los hallazgos en comparaciones ejecutables y no considerar migrada una regla mientras Oracle aún tenga que imponerla.
Preguntas frecuentes
¿Cómo encuentro todo el código PL/SQL de una base Oracle?
Consulte DBA_SOURCE o ALL_SOURCE para paquetes, cuerpos, procedimientos, funciones, triggers y tipos, y extraiga su DDL con DBMS_METADATA. Añada tareas, permisos, sinónimos, objetos no válidos, columnas virtuales, índices basados en funciones y políticas, porque el código por sí solo no describe cada ruta de llamada.
¿Puede ALL_DEPENDENCIES encontrar todas las dependencias PL/SQL?
No. Registra dependencias normales de compilación, pero el SQL dinámico, nombres configurados, sinónimos, enlaces de base, resolución con derechos del invocador y llamadas externas pueden escapar del grafo. Combínela con búsquedas en el código y trazas de ejecución.
¿Debe sacarse la lógica empresarial de los triggers?
Mueva los flujos y efectos externos a un servicio con propietario, pero mantenga los invariantes universales en el límite más estrecho que todo escritor deba cruzar. Una restricción declarativa suele ser mejor que un trigger o controles duplicados en la aplicación.
¿Cómo pruebo un paquete PL/SQL antes de reescribirlo?
Llame a sus puntos de entrada públicos contra datos Oracle controlados y capture retornos, errores, cambios de tablas, eventos y resultados de transacción. Repita los casos en sesiones nuevas, reutilizadas, simultáneas e invalidadas si el paquete mantiene estado.
¿Por qué importa el estado de paquetes Oracle en una migración?
Las variables de paquete pueden persistir durante la sesión, por lo que un pool transporta estado oculto entre peticiones. Un reemplazo sin estado puede cambiar el comportamiento si las pruebas no exponen la dependencia y los responsables no deciden si conservarla o retirarla.
¿Basta el tráfico de producción para demostrar paridad PL/SQL?
No. La reproducción aporta entradas realistas, pero omite fallos raros, fechas límite, llamadas no autorizadas y ramas nunca ejecutadas. Añada casos diseñados desde un registro de comportamiento y compare los efectos completos de la transacción.
¿Cómo deben migrarse las transacciones autónomas?
Primero determine por qué el código antiguo confirma trabajo de manera independiente y si la empresa depende de que sobreviva a un rollback. La mayoría de auditorías o mensajes se entienden mejor como un outbox explícito o una escritura con propietario separado, pero debe mandar el comportamiento aprobado.
¿Se puede traducir Oracle PL/SQL directamente a PostgreSQL?
La sintaxis se puede convertir, pero una traducción directa omite diferencias de estado de paquete, cadenas vacías y nulos, errores, privilegios, transacciones y triggers. Recupere primero el comportamiento y elija después un propietario nativo para cada regla.
¿Cómo evito efectos de triggers duplicados durante el cambio?
Mantenga una matriz de activación con un único ejecutor autorizado para cada regla del registro. Ejecute la lógica nueva en sombra sin mutaciones compartidas y deshabilite o evite el ejecutor antiguo cuando la ruta nueva empiece a escribir.
¿Cuándo está realmente completa una migración de PL/SQL?
Está completa cuando las rutas Oracle migradas pueden deshabilitarse y tanto la reproducción de tráfico como los casos diseñados siguen pasando. Cada trigger, tarea, permiso, sinónimo y conexión directa restante debe tener un propietario y una razón explícitos.