Gleicher Code in mehreren gespeicherten Prozeduren

8

Ich bin kürzlich einer Firma beigetreten und habe gerade festgestellt, dass bei vielen gespeicherten Prozeduren derselbe Codeabschnitt durchgehend wiederholt wird. Ich habe es bemerkt, weil ich beauftragt wurde, einen kleinen Abschnitt dieses Codes in jedem SP zu ändern, in dem er aufgetreten ist :)

Es ist ein ziemlich umfangreiches Stück Code, ungefähr 30 Zeilen. Der Code ist Teil einer Einfügeanweisung und verbindet im Grunde 4 Tabellen mit WHERE/ANDBedingungen, die sich nicht wirklich von SP zu SP ändern. Es sieht ähnlich aus wie unten:

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

Der einzige Teil, der sich von SP zu SP ändert, sind die Werte ( 'abc', 'def', 'ghi' ).

Es kann auch unterschiedliche Mengen dieser Werte geben, so dass einige SPs 2 Werte haben, andere 5 usw.

Alles, woran ich denke, ändert diesen Codeabschnitt in dynamisches SQL, und ich bin mir nicht sicher, ob sich das lohnt. Der Programmierer in mir hasst diese Situation jedoch.

Sollte ich versuchen, eine Form der Wiederverwendung von Code zu implementieren? Hätte es einen ROI? Was sind meine Optionen? Ich musste ~ 100 gespeicherte Prozeduren durchlaufen, was ungefähr eine Stunde dauerte.

Die 100 SPs sind auf etwa 20 verschiedene Datenbanken verteilt. Ich habe die Berechtigung, eine Ansicht zu erstellen.

Jeff.Clark
quelle

Antworten:

11

Dies sollte für Sie funktionieren:

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

Dann ersetzen Sie in Procs durch:

...
FROM MyView
WHERE
MedicalPlanCode IN ('abc', 'def', 'ghi')
Chad Mattox
quelle
Gibt es eine Möglichkeit, diese einzelne Ansicht auf alle Datenbanken zu übertragen, die sie benötigen?
Jeff.Clark
1
Sind die Tabellen in den 20 Datenbanken dupliziert? Oder wählen sie aus Tabellen in einer einzigen Datenbank aus?
Chad Mattox
Die Tabellen (Struktur) werden in diesen 20 Datenbanken dupliziert. Die gespeicherten Prozeduren sind aufgrund der Art des Geschäfts - EDI-Berichterstattung für Krankenversicherungen für Obamacare - ähnlich (häufig werden hier und da dieselben Codeblöcke verwendet). Jede Datenbank repräsentiert ein anderes Unternehmen, jede gespeicherte Prozedur repräsentiert einen anderen Versicherungsträger (Blaues Kreuz / Kaiser / etc ...)
Jeff.Clark
Sie müssten dann die Ansicht für jede Datenbank duplizieren
Chad Mattox
2

Diese Lösung würde die Notwendigkeit ersetzen, dass mehr als 100 Procs dasselbe tun. Du hast einen Proc und eine Funktion. Die Funktion teilt alle Ihre medizinischen Codes von einer Zeichenfolge in eine Tabelle auf, die in einer CROSS APPLY im neuen Prozess verwendet werden kann. Auf diese Weise müssen Sie nur den einen Proc aufrufen. Natürlich müssten Sie den gesamten Code aktualisieren, der die anderen Prozesse aufruft, um nur diesen zu verwenden.

--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
quelle