Один и тот же код в нескольких хранимых процедурах

8

Недавно я присоединился к компании и заметил, что многие хранимые процедуры повторяют один и тот же раздел кода. Я заметил, потому что мне было поручено изменить небольшой раздел этого кода в каждом SP, что это произошло :)

Это довольно здоровенный кусок кода, около 30 строк. Код является частью оператора вставки и в основном объединяет 4 таблицы вместе с WHERE/ANDусловиями, которые на самом деле не меняются от SP к SP. Это выглядит примерно так:

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

Единственная часть, которая изменяется от SP к SP, это значения ( 'abc', 'def', 'ghi' )

Также может быть различное количество этих значений, поэтому у некоторых SP будет 2 значения, у других - 5 и т. Д.

Все, что я думаю об изменении этого раздела кода на динамический SQL, и я не уверен, стоит ли это того. Однако программист во мне ненавидит эту ситуацию.

Должен ли я попытаться реализовать какую-то форму повторного использования кода? Будет ли это иметь ROI? Какие у меня варианты? Мне пришлось пройти около 100 хранимых процедур, что заняло около часа.

100 SP распределены по 20 разным базам данных. У меня есть разрешения на создание представления.

Jeff.Clark
источник

Ответы:

11

Это должно работать для вас:

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

Затем замените в Procs:

...
FROM MyView
WHERE
MedicalPlanCode IN ('abc', 'def', 'ghi')
Чад Мэттокс
источник
Есть ли способ заставить это единственное представление распространяться на все базы данных, которые в нем нуждаются?
Джефф
1
Дублируются ли таблицы в 20 базах данных? Или они выбирают из таблиц в одной базе данных?
Чад Мэттокс
Таблицы (структура) дублируются в этих 20 базах данных. Хранимые процедуры схожи (часто с использованием одних и тех же частей кода здесь и там) из-за характера бизнеса - отчетности EDI медицинского страхования для Obamacare. Каждая база данных представляет
отдельную
Тогда вам нужно будет продублировать представление для каждой базы данных
Чад Мэттокс
2

Это решение заменит необходимость иметь 100+ проков, делающих одно и то же. у вас есть проц и функция. Функция разбивает все ваши медицинские коды от строки до таблицы, которую можно использовать в CROSS APPLY в новом процессе. Таким образом, вам нужно вызвать только один процесс. Конечно, вам придется обновить весь код, вызывающий другие процессы, чтобы использовать только этот.

--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 .....
Стив Мангиамели
источник