Confiezo uno de mis mayores pecados: fui fanático de los Procedimientos Almacenados (stored procedures) en entornos de base de datos, eso fue hasta el año 2001 debido a las críticas no solamente de los autores sino de los gerentes de sistemas con los que trabajaba. De hecho abandonar dicha técnica fue una obligación, ya que un sistema que tube que mantener por 18 meses no los utilizaba (había una prohibición expresa) y tampoco utilizaba vistas !!!.
Había una razón muy importante para ello, el software funcionaba con tres sistemas bases de datos diferentes: Oracle, SqlServer e Interbase según las disponibilidad de cada una de los 43 empresas donde funcionaba el sistema. En tal caso como programador me tocó desempolvar mis conocimientos de estructuras de datos y familiarizarme con UML.
Hoy no voy a detallar los pros y contras de desarrollar con Procedimientos almacenados. Pero si les voy a contar que hace unos meses tube que migrar rápidamente una base de datos a estructuras en memoria construídas con C#. Habían algunos miles de líneas en TransactSql, las que debían ser analizadas cuidadosamente unas veces para mantener la misma lógica y otras para corregirla.
La manera más rápido de hacerlo fue analizar los Cursores, pero no con SQL Server, sino con Groovy.
Los cursores son la razón de ser los lenguajes almacenados.
Miremos la porción de código en TransactSql:
1 . 2 . 3 . 4 set @anio = 2007 5 6 declare MICURSOR cursor for 7 select 8 p.PVEHAMOD as anio_modelo, 9 c.CVEHCATV as cod_categoria_v, 10 p.PVEHFECO as fe_co 11 from 12 CVEH c, 13 PVEH p 14 where 15 c.CVEHCATV = p.CVEHCATV 16 and p.PVEHANIO = @anio 17 18 for each row in MICURSOR { 19 // ... 20 // manejar cada registro del cursor 21 // ... 22 } 23 . 24 . 25 .
Y ahora analicemos el equivalente en Groovy ...
1 . 2 . 3 . 4 int anio = 2007 5 6 String mainSql = """ 7 select 8 p.PVEHAMOD as anio_modelo, 9 c.CVEHCATV as cod_categoria_v, 10 p.PVEHFECO as fe_co 11 from 12 CVEH c, 13 PVEH p 14 where 15 c.CVEHCATV = p.CVEHCATV 16 and p.PVEHANIO = $anio """ 17 18 db.eachRow(mainSql) { rec -> 19 // ... 20 // manejar cada registro en la variable rec 21 // ... 22 } 23 . 24 . 25 .
Esta estructura simple me permitió extraer la lógica desde unos fuentes en SQL Server para colocarla con mejoras en lenguaje C# y trabajar sobre eficientes tablas texto. Al final de cuentas el problema era matemático y no transaccional sobre base de datos.