Mismo código en múltiples procedimientos almacenados

8

Recientemente me uní a una empresa y me di cuenta de que muchos de los procedimientos almacenados tienen la misma sección de código repetida en todo momento. Me di cuenta porque tenía la tarea de cambiar una pequeña sección de ese código en cada SP que ocurría :)

Es un fragmento de código bastante fuerte, de aproximadamente 30 líneas. El código es parte de una instrucción de inserción, y básicamente une 4 tablas junto con WHERE/ANDcondiciones que realmente no cambian de SP a SP. Se parece a lo siguiente:

...
...
FROM <TableOne>
  INNER JOIN <TableTwo> ON ...
    AND .....
    AND .....
  LEFT JOIN <TableThree> ON ...
    AND .....
    AND .....
WHERE .....
  AND .....
  AND .....
  AND MedicalPlanCode IN ('abc', 'def', 'ghi')

La única parte que cambia de SP a SP son los valores ( 'abc', 'def', 'ghi' )

También puede haber diferentes cantidades de esos valores, por lo que algunos SP tendrán 2 valores, otros tendrán 5, etc.

Todo lo que pienso cambia esa sección de código a SQL dinámico, y no estoy seguro de si eso vale la pena. Sin embargo, el programador en mí odia esta situación.

¿Debería intentar implementar alguna forma de reutilización de código? ¿Tendría un ROI? ¿Cuáles son mis opciones? Tuve que pasar por ~ 100 procedimientos almacenados, que tomaron aproximadamente una hora.

Los 100 SP están distribuidos en más de 20 bases de datos diferentes. Tengo permisos para crear una vista.

Jeff.Clark
fuente

Respuestas:

11

Esto debería funcionar para usted:

CREATE VIEW MyView AS
SELECT <colList>
FROM <TableOne>
INNER JOIN <TableTwo> ON ...
AND .....
AND .....
LEFT JOIN <TableThree> ON ...
AND .....
AND .....
WHERE .....
AND .....
AND .....

Luego reemplace en Procs con:

...
FROM MyView
WHERE
MedicalPlanCode IN ('abc', 'def', 'ghi')
Chad Mattox
fuente
¿Hay alguna manera de hacer que esa vista única se propague a todas las bases de datos que la necesitan?
Jeff.Clark
1
¿Las tablas están duplicadas en las 20 bases de datos? ¿O están seleccionando de tablas en una sola base de datos?
Chad Mattox
Las tablas (estructura) están duplicadas en esas 20 bases de datos. Los procedimientos almacenados son similares (a menudo usan los mismos fragmentos de código aquí y allá) debido a la naturaleza del negocio: informes de EDI de seguro médico para Obamacare. Cada base de datos representa una compañía diferente, cada procedimiento almacenado representa una compañía de seguros diferente (Blue Cross / Kaiser / etc ...)
Jeff.Clark
Tendría que duplicar la vista para cada base de datos entonces
Chad Mattox
2

Esta solución reemplazaría la necesidad de tener más de 100 procs haciendo lo mismo. Tienes un proceso y una función. La función divide todos sus códigos médicos de una cadena a una tabla que puede usarse en una APLICACIÓN CRUZADA en el nuevo proceso. De esta manera solo tienes que llamar al único proceso. Por supuesto, tendría que actualizar todo el código llamando a los otros procesos para usar solo este.

--gfn_ParseList
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type in ('FN', 'IF', 'TF', 'FS', 'FT') AND name = 'gfn_ParseList')
    EXEC sp_executesql N'CREATE FUNCTION gfn_ParseList RETURNS @paresedIDs AS BEGIN SELECT 1 ParsedValue, 1 PositionID RETURN END'
GO


ALTER FUNCTION gfn_ParseList (@strToPars VARCHAR(8000), @parseChar CHAR(1))
RETURNS @parsedIDs TABLE
     (ParsedValue VARCHAR(255), PositionID INT IDENTITY)
AS
BEGIN

DECLARE 
    @startPos INT = 0
    , @strLen INT = 0

WHILE LEN(@strToPars) >= @startPos
    BEGIN

        IF (SELECT CHARINDEX(@parseChar,@strToPars,(@startPos+1))) > @startPos
            SELECT @strLen  = CHARINDEX(@parseChar,@strToPars,(@startPos+1))    - @startPos
        ELSE
            BEGIN
                SET @strLen = LEN(@strToPars) - (@startPos -1)

                INSERT @parsedIDs
                SELECT RTRIM(LTRIM(SUBSTRING(@strToPars,@startPos, @strLen)))
                BREAK
            END

        SELECT @strLen  = CHARINDEX(@parseChar,@strToPars,(@startPos+1))    - @startPos

        INSERT @parsedIDs
        SELECT RTRIM(LTRIM(SUBSTRING(@strToPars,@startPos, @strLen)))

        SET @startPos = @startPos+@strLen+1
    END
RETURN
END 


--New sp
create proc usp_ReturnSomeData (@medicalPlanCodes nvarchar(1000))
as

select YourColumn1, YourColumn2...
FROM <TableOne>
  CROSS APPLY gfn_ParseList(@medicalPlanCodes,',') p
  INNER JOIN <TableTwo> ON ...
    AND .....
    AND .....
  LEFT JOIN <TableThree> ON ...
    AND .....
    AND .....
WHERE .....
  AND .....
  AND .....
Steve Mangiameli
fuente