Un recorrido línea por línea de un procedimiento almacenado heredado que se traslada a Databricks. Los cursores, las tablas temporales y las transacciones de múltiples instrucciones se mueven como SQL como parte de la migración del data warehouse.
por Abhishek Dey y Laurent Léturgez
En algún lugar de su almacén de datos, cientos de procedimientos almacenados se ejecutan cada noche y mantienen el negocio en marcha silenciosamente. Fueron escritos hace años por un grupo de desarrolladores de SQL que ya hace tiempo dejaron la empresa. Tienen cursores anidados. Crean tablas temporales sobre la marcha. Agrupan actualizaciones en varias tablas en una sola transacción. Y en algún lugar alrededor de la línea 47, hay un comentario que simplemente dice: “No modificar esto”. Ya nadie entiende completamente estos procedimientos. Sin embargo, todos dependen de ellos. El panel de control de ingresos, el cierre financiero, el informe de operaciones, todos ellos, de una forma u otra, se remontan a estas capas de lógica de negocio de SQL procedimental.
Mover datos al lakehouse es algo que ya se comprende bien. El punto de fricción ha sido el núcleo procedimental de cualquier migración de almacén de datos: los procedimientos almacenados, el manejo de transacciones, las tablas temporales, el flujo de control y el hecho de que gran parte de la empresa aún depende de las habilidades de SQL. Cada vez que surgía una migración, estos procedimientos eran lo primero a lo que todos señalaban: “No podemos migrar hasta que podamos ejecutar eso con cambios mínimos. Nuestra empresa todavía depende en gran medida de SQL”.
Así que decidimos tomar un caso de uso como el que probablemente esté pensando ahora mismo, un procedimiento compuesto que hemos visto en varias migraciones, y demostrarlo, pieza por pieza, en el Lakehouse. Este ejemplo se basa en un caso de uso de migración de Oracle, pero se puede aplicar a cualquier almacén de datos (heredado o basado en la nube).
Este procedimiento de ejemplo procesa los pedidos diarios. Almacena temporalmente los pedidos no procesados en una tabla temporal, los valida con el maestro de clientes, recorre los fallos para registrar cada rechazo de forma de manera individual, luego actualiza los resúmenes de ingresos regionales y marca todos los pedidos como procesados, todo dentro de una transacción que se revierte en caso de fallo.
Un trabajo nocturno que no se puede interrumpir.
Antes, migrar esto significaba reescribirlo por completo en Python y Spark. Semanas de trabajo, nuevos errores por encontrar y un equipo de SQL que ya no podía mantener su propia lógica de negocio.
No lo reescribimos. Lo tradujimos.
Cada procedimiento comienza con una firma y una red de seguridad. El sistema heredado envolvía el cuerpo en BEGIN ... EXCEPTION ... END. Databricks utiliza DECLARE EXIT HANDLER FOR SQLEXCEPTION en su lugar; la misma idea, una sintaxis ligeramente diferente. Supongamos que el catálogo y el esquema adecuados se han establecido en la sesión.
La gran diferencia no está en el código. Es lo que sucede después del despliegue. En Databricks, el procedimiento se registra en Unity Catalog. Obtiene controles de acceso, linaje a nivel de columna y capacidad de descubrimiento en todos los espacios de trabajo. En el sistema actual, vivía en un esquema del cual solo tres personas tenían la contraseña.
Heredado | Databricks |
CREATE OR REPLACE PROCEDURE name IS | CREATE OR REPLACE PROCEDURE [IF NOT EXISTS] <catalog>.<schema>.<procedure_name> ( [ procedure_parameter [, ...] ] ) [ characteristic [...] ] LANGUAGE SQL SQL SECURITY { INVOKER | DEFINER } AS BEGIN |
v_id NUMBER; antes de BEGIN | DECLARE v_id INT; dentro de BEGIN |
EXCEPTION WHEN OTHERS THEN | DECLARE EXIT HANDLER FOR SQLEXCEPTION |
Referencia: docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-ddl-create-procedure
El procedimiento original crea dos tablas temporales para staging y fallos de validación. Son el espacio de trabajo temporal del que depende el resto de la lógica.
En Databricks, esto se convierte en una de las partes más sencillas de la migración. Sin EXECUTE IMMEDIATE. Sin ON COMMIT PRESERVE ROWS. El CREATE TEMP TABLE con alcance de sesión es el reemplazo directo con una pequeña advertencia: CREATE OR REPLACE TEMP TABLE aún no es compatible, por lo que debes eliminarla (drop) primero si necesitas que se pueda volver a ejecutar en la misma sesión.
Referencia: docs.databricks.com/aws/en/tables/temporary-tables
Esta era la pieza que todos asumían que requeriría una reescritura. El procedimiento original recorre los fallos de validación uno por uno, rechaza cada pedido incorrecto y registra el motivo. El clásico patrón de cursor. Décadas de memoria muscular de sistemas heredados (Oracle, por ejemplo).
El scripting de SQL de Databricks admite cursores de forma nativa, OPEN, FETCH y CLOSE desde Runtime 18.1. El atributo %NOTFOUND se convierte en un CONTINUE HANDLER FOR NOT FOUND. Las etiquetas de bucle y LEAVE reemplazan a EXIT WHEN.
La comprobación condicional (si no hay filas para procesar, omitir y registrar) apenas cambió. SELECT ... INTO se convierte en SET var = (SELECT ...). Todo lo demás es idéntico.
Nuestro scripting de SQL admite el conjunto completo de herramientas procedimentales: IF/ELSE, WHILE, FOR, LOOP, REPEAT, LEAVE, ITERATE, SIGNAL/RESIGNAL. Si tu base de código contiene scripts de Teradata BTEQ, las directivas .GOTO y .LABEL se asignan a bucles etiquetados utilizando LEAVE e ITERATE.
Referencia: docs.databricks.com/aws/en/sql/language-manual/sql-ref-scripting
Esta fue la última pieza, la que hizo que la migración fuera realmente viable. El procedimiento original actualiza regional_revenue, marca los pedidos como procesados y registra el lote. Si alguna parte falla, todo se revierte.
En el sistema heredado, esta es una transacción implícita con un COMMIT explícito. En Databricks, BEGIN ATOMIC ... END proporciona la misma semántica: confirmación automática en caso de éxito y reversión automática en caso de fallo, con una ventaja significativa: detección de conflictos a nivel de fila. Los lotes simultáneos que escriben en la misma tabla solo entran en conflicto si afectan a las mismas filas. Por ejemplo, tanto Oracle como Snowflake utilizan el bloqueo a nivel de tabla, lo que obliga a una ejecución secuencial.
La sentencia MERGE se puede migrar a Databricks tal cual. El COMMIT explícito desapareció, ya que BEGIN ATOMIC se encarga de ello. Y el equipo dejó de preocuparse de que los trabajos por lotes simultáneos interfirieran entre sí.
Dos notas prácticas al adoptar este patrón:
Referencia: docs.databricks.com/aws/en/transactions/
Misma lógica de negocio. Mismo flujo de control. Gobernado por Unity Catalog.
Para ejecutarlo dentro de una transacción, envuelva la llamada:
Los plazos de migración de estos programas pueden reducirse entre un 50 y un 75%, incluso para procedimientos almacenados complejos con fuertes dependencias de paquetes PL/SQL. Esta eficiencia proviene de un proceso de traducción mecánica que preserva la lógica de negocio original, lo que garantiza que el equipo de SQL pueda continuar con su trabajo de mantenimiento sin problemas. Más allá de la migración en sí, los equipos obtienen una nueva y potente ventaja: una plataforma unificada donde los mismos datos gobernados alimentan sus paneles de control, modelos de machine learning e iniciativas de IA.
La única forma de saber si sus procedimientos se traducen es probar uno. Elija el procedimiento almacenado más pequeño de su lote, preferiblemente uno que a nadie le guste depurar. ¡Cree un proyecto de migración en su espacio de trabajo y comience a utilizar Agentic Code Convertor!
(Esta entrada del blog ha sido traducida utilizando herramientas basadas en inteligencia artificial) Publicación original
Suscríbete a nuestro blog y recibe las últimas publicaciones directamente en tu bandeja de entrada.