Как я могу сделать эту хранимую процедуру (SQL Server) проще для чтения? - PullRequest
0 голосов
/ 20 февраля 2019

Ниже приведен псевдокод моей текущей хранимой процедуры.Во-первых, у меня есть ОГРОМНЫЙ запрос, который создает временную таблицу.Затем у меня есть другие запросы внутри хранимой процедуры, которые запрашивают эту временную таблицу.

Моя цель - сделать хранимую процедуру более читабельной.ОГРОМНЫЙ запрос усложняет задачу, поскольку занимает много места.Я попытался создать отдельную хранимую процедуру для этого огромного запроса, чтобы создать временную таблицу, но временная таблица не может быть доступна за пределами этой другой хранимой процедуры.

Кто-нибудь знает более читаемый способ написания этого кода?Если мой вопрос не имеет смысла, я перефразирую его.Спасибо.

Alter Procedure spMyStoredProc
Begin
    --Value of 1 for each param means I want to execute the query
    @sqlQueryA Bit = 0,
    @sqlQueryB Bit = 0,
    @sqlQueryC Bit = 0

    Select Columns
    Into #MyTempTable
    From **HUGE Query**

    If @sqlQueryA = 1 
    Begin    
        Select * From #MyTempTable
    End
    Else If @sqlQueryB = 1
       ... 
    Else If @sqlQueryC = 1
    Begin
        Query something else from #MyTempTable
    End
    Else
        Return
End

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

CREATE FUNCTION fn_myFunction()
RETURNS TABLE
AS
RETURN
(
    --Declaration is not allowed
    Declare @myLocalVar As DateTime
    Set @myLocalVar = '2019-01-10'

    #HUGE Query
    Where SomeColumn = @myLocalVar
)

Ответы [ 4 ]

0 голосов
/ 21 февраля 2019

Идея от Эвалдаса Буйнаускаса оказалась тем ответом, который мне больше всего понравился.Это решило проблему читабельности, проблему локальных переменных и работало хорошо.Обратите внимание, что я переместил свой ОГРОМНЫЙ запрос во встроенную табличную функцию.Вы можете видеть, что это вызывается в коде ниже.Я передаю свои локальные переменные в качестве параметров функции.Функция создает временную таблицу, в которой я нуждался.

Alter Procedure spMyStoredProc
Begin

@SqlAsParam Nvarchar(100),
@otherParam DataType,
…

Declare @localVarA DataType
Set @localVarA = value

Declare @localVarB DataType
Set @localVarB = value  

Select * 
Into #MyTempTable
From dbo.fn_GetHUGEquery(@localVarA, @localVarB)

If @SqlAsParam = 'sqlQueryA'
  Begin    
     Select * From #MyTempTable
  End
Else If @SqlAsParam = 'sqlQueryB'
       ... 
Else If @SqlAsParam = 'sqlQueryC'
  Begin
      Query something else from #MyTempTable
  End
Else
     Return
End
0 голосов
/ 20 февраля 2019

Вы упомянули это:

Моя цель - сделать мою хранимую процедуру более читабельной.ОГРОМНЫЙ запрос усложняет задачу, поскольку занимает много места.Я попытался создать отдельную хранимую процедуру для этого огромного запроса, чтобы создать временную таблицу, но временная таблица не может быть доступна вне этой другой хранимой процедуры.

В зависимости от того, имеет ли ваш запрос параметры или нет,Я бы, вероятно, обернул бы этот запрос в представление или встроенную табличную функцию, чтобы изолировать его.

Таким образом, ваша хранимая процедура тогда буквально становится такой же короткой, как у вас сейчас:

ALTER PROCEDURE spMyStoredProc
BEGIN
    SET NOCOUNT ON;

    -- Value of 1 for each param means I want to execute the query
    @sqlQueryA BIT = 0,
    @sqlQueryB BIT = 0,
    @sqlQueryC BIT = 0,

    SELECT Columns
    INTO #MyTempTable
    FROM dbo.ViewOrInlineValuedFunction

    IF @sqlQueryA = 1
    BEGIN
        SELECT *
        FROM #MyTempTable
    END;
    ELSE IF @sqlQueryB = 1
    BEGIN
        SELECT *
        FROM #MyTempTable;
    END;
    ELSE IF @sqlQueryC = 1
    BEGIN
        SELECT *
        FROM #MyTempTable
    END;
END;

CouldnВы изменяете функцию для принятия параметров?:)

CREATE FUNCTION fn_myFunction(@myLocalVar DATE)
RETURNS TABLE
AS
RETURN (
    SELECT *
    FROM HugeQuery
    WHERE SomeColumn = @myLocalVar
);

Тогда вызов функции можно вызвать так же просто:

SELECT *
FROM dbo.fn_myFunction('2019-01-10');
0 голосов
/ 21 февраля 2019

Вы можете использовать оператор INSERT EXEC.

Alter Procedure spMyStoredProc
Begin
    --Value of 1 for each param means I want to execute the query
    @sqlQueryA Bit = 0,
    @sqlQueryB Bit = 0,
    @sqlQueryC Bit = 0

    Insert Into #MyTempTable
    Exec spHugeQuery --here you execute the stored proc that selects from huge query 

    If @sqlQueryA = 1 
    Begin    
        Select * From #MyTempTable
    End
    Else If @sqlQueryB = 1
       ... 
    Else If @sqlQueryC = 1
    Begin
        Query something else from #MyTempTable
    End
    Else
        Return
End

Преимущество

Это решение наиболее соответствует вашему исходному решению и будет работать хорошо, если вам нужно установить переменные, которые будут использоваться в запросе.

Недостаток

Хранимая процедура spHugeQuery должна возвращать правильное количество столбцов и правильные типы данных, которые можно вставить в вашу временную таблицу.Если что-то изменится либо в вашем определении временной таблицы, либо в операторе select в хранимой процедуре, вы не узнаете об этом, пока не произойдет сбой во время выполнения.

0 голосов
/ 20 февраля 2019

Сделайте ваш огромный запрос представлением

Select *
Into #MyTempTable
From MyView

Кроме того, поскольку ваш запрос является взаимоисключающим, вам не нужно три бита.

Передайте одно значение, строку илиперечисляемое значение, чтобы проверить, какой запрос нужно выполнить, а затем короткое замыкание путем возврата.

IF @Query = 'QueryA'
BEGIN
 Select QueryA From #MyTempTable
RETURN 1;
END;

IF @Query = 'QueryB'
BEGIN
 Select QueryB From #MyTempTable
RETURN 1;
END;

--throw an error if the query is not found
...