Mesmo código em vários procedimentos armazenados

8

Recentemente, ingressei em uma empresa e notei que muitos dos procedimentos armazenados têm a mesma seção de código repetida. Notei porque fui encarregado de alterar uma pequena seção desse código em todos os SP em que ocorreu :)

É um pedaço de código bastante robusto, com cerca de 30 linhas. O código faz parte de uma instrução de inserção e basicamente une 4 tabelas com WHERE/ANDcondições que realmente não mudam de SP para SP. É semelhante ao abaixo:

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

A única parte que muda de SP para SP são os valores ( 'abc', 'def', 'ghi' )

Também pode haver quantidades diferentes desses valores, portanto alguns SPs terão 2 valores, outros terão 5, etc ...

Tudo o que penso muda essa seção de código para SQL dinâmico e não tenho certeza se vale a pena. No entanto, o programador em mim odeia essa situação.

Devo tentar implementar alguma forma de reutilização de código? Teria um ROI? Quais são as minhas opções? Eu tive que passar por ~ 100 procedimentos armazenados, o que levou cerca de uma hora.

Os 100 SP estão espalhados por mais de 20 bancos de dados diferentes. Eu tenho permissões para criar uma exibição.

Jeff.Clark
fonte

Respostas:

11

Isso deve funcionar para você:

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

Em seguida, substitua no Procs por:

...
FROM MyView
WHERE
MedicalPlanCode IN ('abc', 'def', 'ghi')
Chad Mattox
fonte
Existe uma maneira de fazer com que essa visualização única se propague para todos os bancos de dados que precisam?
Jeff.Clark
11
As tabelas estão duplicadas nos 20 bancos de dados? Ou eles estão selecionando as tabelas em um único banco de dados?
Chad Mattox
As tabelas (estrutura) são duplicadas nesses 20 bancos de dados. Os procedimentos armazenados são semelhantes (geralmente usando os mesmos blocos de código aqui e ali) devido à natureza dos negócios - relatórios de seguro saúde EDI para Obamacare. Cada banco de dados representa uma empresa diferente, cada procedimento armazenado representa um diferente Insurance Carrier (Cruz Azul / Kaiser / etc ...)
Jeff.Clark
Você precisaria de duplicar a visão para cada banco de dados, em seguida,
Chad Mattox
2

Essa solução substituiria a necessidade de ter mais de 100 procs fazendo a mesma coisa. você tem um proc e uma função. A função divide todos os seus códigos médicos de uma string para uma tabela que pode ser usada em um CROSS APPLY no novo proc. Dessa forma, você só precisa chamar o proc. Claro que você teria que atualizar todo o código chamando os outros procs para usar apenas 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
fonte