下面是我当前存储过程的伪代码。首先,我有一个创建临时表的巨大查询。然后,在存储过程中还有其他查询正在查询该临时表。
我的目标是使存储过程更具可读性。巨大的查询使它变得困难,因为它占用了太多空间。我尝试为此庞大的查询创建一个单独的存储过程以创建一个临时表,但是无法在该其他存储过程之外访问该临时表。
有人知道编写此代码的可读性更高的方法吗?如果我的问题没有道理,那么我将重述一下。谢谢。
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
)
答案 0 :(得分:2)
使您庞大的查询成为一个视图
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
答案 1 :(得分:1)
您提到了这一点
我的目标是使存储过程更具可读性。巨大的查询使它变得困难,因为它占用了太多空间。我曾尝试为这个庞大的查询创建一个单独的存储过程以创建一个临时表,但是无法在该其他存储过程之外访问该临时表。
根据您的查询是否有参数,我可能会将该查询包装到视图或内联表值函数中以进行隔离。
因此,您的存储过程实际上会变得和现在一样短:
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;
您不能修改函数以接受参数吗? :)
CREATE FUNCTION fn_myFunction(@myLocalVar DATE)
RETURNS TABLE
AS
RETURN (
SELECT *
FROM HugeQuery
WHERE SomeColumn = @myLocalVar
);
然后可以简单地调用函数调用:
SELECT *
FROM dbo.fn_myFunction('2019-01-10');
答案 2 :(得分:0)
您可以使用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
需要返回可以插入到临时表中的正确的列数和正确的数据类型。如果临时表定义或存储的proc中的select语句发生了变化,直到运行时失败,您才知道。
答案 3 :(得分:0)
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