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.

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')

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 .....
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.