如何使此存储过程(SQL Server)更易于阅读?
下面是我当前存储过程的伪代码。首先,我有一个创建临时表的巨大查询。然后,在存储过程中还有其他查询正在查询该临时表 我的目标是使存储过程更具可读性。庞大的查询占用了太多的空间,这使得它变得很困难。我已经尝试为这个巨大的查询创建一个单独的存储过程来创建一个临时表,但是不能在其他存储过程之外访问临时表 有人知道写这段代码的更易读的方法吗?如果我的问题没有意义,那么我会重新措辞。谢谢如何使此存储过程(SQL Server)更易于阅读?,sql,sql-server,stored-procedures,temp-tables,code-readability,Sql,Sql Server,Stored Procedures,Temp Tables,Code Readability,下面是我当前存储过程的伪代码。首先,我有一个创建临时表的巨大查询。然后,在存储过程中还有其他查询正在查询该临时表 我的目标是使存储过程更具可读性。庞大的查询占用了太多的空间,这使得它变得很困难。我已经尝试为这个巨大的查询创建一个单独的存储过程来创建一个临时表,但是不能在其他存储过程之外访问临时表 有人知道写这段代码的更易读的方法吗?如果我的问题没有意义,那么我会重新措辞。谢谢 Alter Procedure spMyStoredProc Begin --Value of 1 for ea
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
下面是Evaldas Buinauskas和我在这条线上讨论的一个次要问题:
我在下面添加了包含内联表值函数的代码。我的大查询有几个局部变量。下面是伪代码。代码导致了一个错误
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
)
让你的大查询成为一个视图
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
让你的大查询成为一个视图
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
你提到:
我的目标是使存储过程更具可读性。庞大的查询占用了太多的空间,这使得它变得很困难。我已经尝试为这个巨大的查询创建一个单独的存储过程来创建一个临时表,但是不能在其他存储过程之外访问临时表
根据查询是否具有参数,我可能会将该查询包装到视图或内联表值函数中以隔离它
因此,您的存储过程实际上变得和现在一样短:
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;
无法修改函数以接受参数吗?:)
那么函数调用可以简单地调用,如下所示:
SELECT *
FROM dbo.fn_myFunction('2019-01-10');
你提到:
我的目标是使存储过程更具可读性。庞大的查询占用了太多的空间,这使得它变得很困难。我已经尝试为这个巨大的查询创建一个单独的存储过程来创建一个临时表,但是不能在其他存储过程之外访问临时表
根据查询是否具有参数,我可能会将该查询包装到视图或内联表值函数中以隔离它
因此,您的存储过程实际上变得和现在一样短:
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;
无法修改函数以接受参数吗?:)
那么函数调用可以简单地调用,如下所示:
SELECT *
FROM dbo.fn_myFunction('2019-01-10');
您可以使用
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
优势
此解决方案与原始解决方案最为一致,如果您需要设置查询中要使用的变量,它将很好地工作
劣势
存储的proc
spHugeQuery
需要返回可插入临时表的正确列数和数据类型。如果临时表定义或存储过程中的select语句发生了更改,则只有在运行时失败时才能知道。您可以使用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
优势
此解决方案与原始解决方案最为一致,如果您需要设置查询中要使用的变量,它将很好地工作
劣势
存储的proc
spHugeQuery
需要返回可插入临时表的正确列数和数据类型。如果您的临时表定义或存储过程中的select语句发生了更改,则在运行时失败之前,您不会知道。Evaldas Buinauskas的想法最终是最适合我的答案。它解决了可读性问题、局部变量问题,性能良好。请注意,我将我的大型查询移到了一个内联表值函数中。您可以在下面的代码中看到它被调用。我将本地变量作为参数传递给函数。该函数创建我需要的临时表
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
Evaldas Buinauskas的想法最终成为最适合我的答案。它解决了可读性问题、局部变量问题,性能良好。请注意,我将我的大型查询移到了一个内联表值函数中。您可以在下面的代码中看到它被调用。我将本地变量作为参数传递给函数。该函数创建我需要的临时表
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
问题:让它可读有什么问题?使用间距/注释使其更干净。您可以将较大的查询分离到它自己的SP中,并在temp db之外使用一个永久表并将其命名为StagingSomething,但除非您在其他地方使用它,否则这会使它变得更复杂。这不是一种更具可读性的方式,但它的性能有时会很糟糕,有时会完全正常。你需要考虑再做一点。我不是一个粉丝,但是你有没有考虑过插入Exec可读性不如性能重要,你同意吗?我不会将包含多种可能性的大型查询放在临时表中,只是为了确定从中选择什么。相反,我将创建一个参数化该查询,并在需要时将其嵌套在一个进程中?但说真的,将这个巨大的查询作为一个视图会将它移出存储过程。有些人不喜欢这种方法,但我看不出有什么问题:让它可读有什么问题?使用间距/注释使其更干净。您可以将较大的查询分离到它自己的SP中,并在temp db之外使用一个永久表,并将其命名为StagingSomething,但除非您在其他地方使用它,否则为什么