Même code dans plusieurs procédures stockées

8

J'ai récemment rejoint une entreprise et je viens de remarquer que la plupart des procédures stockées ont la même section de code répétée tout au long. J'ai remarqué parce que j'étais chargé de changer une petite section de ce code dans chaque SP qu'il s'est produit :)

C'est un morceau de code assez lourd, environ 30 lignes. Le code fait partie d'une instruction d'insertion, et il joint essentiellement 4 tables avec des WHERE/ANDconditions qui ne changent pas vraiment de SP en SP. Il ressemble à ci-dessous:

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

La seule partie qui passe de SP à SP sont les valeurs ( 'abc', 'def', 'ghi' )

Il peut également y avoir différentes quantités de ces valeurs, donc certains SP auront 2 valeurs, d'autres en auront 5, etc ...

Tout ce à quoi je pense transforme cette section de code en SQL dynamique, et je ne sais pas si cela en vaut la peine. Cependant, le programmeur en moi déteste cette situation.

Dois-je essayer d'implémenter une forme de réutilisation de code? Aurait-il un retour sur investissement? Quelles sont mes options? J'ai dû passer par ~ 100 procédures stockées, ce qui a pris environ une heure.

Les 100 SP sont répartis sur une vingtaine de bases de données différentes. J'ai des autorisations pour créer une vue.

Jeff.Clark
la source

Réponses:

11

Cela devrait fonctionner pour vous:

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

Remplacez ensuite dans Procs par:

...
FROM MyView
WHERE
MedicalPlanCode IN ('abc', 'def', 'ghi')
Chad Mattox
la source
Existe-t-il un moyen de faire en sorte que cette vue unique se propage à toutes les bases de données qui en ont besoin?
Jeff.Clark
1
Les tableaux sont-ils dupliqués dans les 20 bases de données? Ou sélectionnent-ils des tables dans une base de données unique?
Chad Mattox
Les tableaux (structure) sont dupliqués dans ces 20 bases de données. Les procédures stockées sont similaires (en utilisant souvent les mêmes morceaux de code ici et là) en raison de la nature de l'entreprise - les rapports EDI d'assurance maladie pour Obamacare. Chaque base de données représente une entreprise différente, chaque procédure stockée représente un assureur différent (Blue Cross / Kaiser / etc ...)
Jeff.Clark
Vous devrez alors dupliquer la vue pour chaque base de données
Chad Mattox
2

Cette solution remplacerait la nécessité d'avoir plus de 100 procs faisant la même chose. vous avez un proc et une fonction. La fonction divise tous vos codes médicaux d'une chaîne en une table qui peut être utilisée dans une APPLICATION CROISÉE dans le nouveau proc. De cette façon, vous n'avez qu'à appeler le seul proc. Bien sûr, vous devrez mettre à jour tout le code appelant les autres procs pour utiliser uniquement celui-ci.

--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
la source