【问题标题】:Using CASE Statement in Stored Procedure在存储过程中使用 CASE 语句
【发布时间】:2018-10-24 08:51:39
【问题描述】:

我有一个存储过程,它根据指定的输入参数调用其他存储过程。

看起来是这样的:

CREATE PROCEDURE dbo.usp_SPCaller
@Input_Param1 NVARCHAR(100) = NULL,
@Input_Param2 NVARCHAR(100) = NULL

AS
BEGIN
SET NOCOUNT ON    

IF ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NOT NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam1And2
   END 

IF ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam1Only
   END

IF ((@Input_Param1 IS NULL) AND (@Input_Param2 IS NOT NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam2Only
   END

IF ((@Input_Param1 IS NULL) AND (@Input_Param2 IS NULL))
   BEGIN
       EXEC dbo.usp_SPWithoutParam1And2
   END

在向我们的主管介绍此内容后,他建议我改用 CASE STATEMENTS,因为使用 IF STATEMENTS 是个坏主意。

我尝试到处搜索如何以与上面相同的格式使用 CASE STATEMENTS,但无济于事。我发现只是将 CASE STATEMENTS 与 UPDATE 一起使用。

我的问题

如何在 SQL SERVER 中以类似于上面的方式使用 CASE STATEMENTS?

【问题讨论】:

  • CASE 语句用于选择/返回数据,不用于执行存储过程。但是,您最好使用 IF ELSE IF 而不是实际代码。
  • 刚才最好的猜测被作者删掉了:没有人要求OP将代码分成几个SP并发明spCaller(闻起来很糟糕,让我想起了初学者的风格),一切都可以而且应该在一个 SP 中完成,并将 CASE 语句应用于它应该应用于的任何内容(我猜是 WHERE 子句中的谓词)。因此,这段代码应该消失了,新的 SP 可能只有一条 T-SQL 语句。
  • 我曾经在一个 SP 中为所有 SP 做所有的逻辑,但是当我展示它时,我被告知每个 SP 都应该遵循单一责任原则,所以我将它们全部拆分,因为它们每个人做不同的事情。这是否意味着在创建存储过程时,您应该将所有存储过程合并为一个,而不是像编写编程语言那样做?
  • “单一责任”原则并没有说wake up and create spCaller proc now! 我们应该如何知道这些sps 中发生了什么或从哪里调用这个外部proc?在这里你再猜测一下:外部 proc 一定不存在,调用者必须直接调用特定的 proc。您的问题是如此模糊和抽象,以至于任何人都可以分享十几个可能的场景如何重新设计它。和你谈谈领导。渴望he is wrong! 的答案是不行的。
  • 我不是在要求“他错了”的答案。我要说的是,我将每个存储过程分开,因为它们做不同的事情。根据我对单一职责的理解,一个班级必须单独做一件事和一件事。并且像我之前所做的那样将它们全部放入一个 SP 中,我违反了这一原则。我来这里是为了回答我的问题,仅此而已。

标签: sql sql-server tsql stored-procedures


【解决方案1】:

试试这个代码.. 在这里,我将过程名称(将要执行)存储在一个名为 @sql 的变量中,最后使用 sp_executesql 执行这个变量

CREATE PROCEDURE dbo.usp_SPCaller 
@Input_Param1 NVARCHAR(100) = NULL,
@Input_Param2 NVARCHAR(100) = NULL

AS
BEGIN
SET NOCOUNT ON

DECLARE @sql AS NVARCHAR(MAX)

set @sql = case 
   when ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NOT NULL))
   then 'dbo.usp_SPWithParam1And2'

   when ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NULL))
   then 'dbo.usp_SPWithParam1Only'

   when((@Input_Param1 IS NULL) AND (@Input_Param2 IS NOT NULL))
   then 'dbo.usp_SPWithParam2Only'

   when ((@Input_Param1 IS NULL) AND (@Input_Param2 IS NULL))
   then 'dbo.usp_SPWithoutParam1And2'

   END

   print @sql
   EXEC sp_executesql @sql
end

【讨论】:

  • sp_executesql 在这里不是必需的。 SP 按名称调用是通过exec @spname 完成的
  • 这很有趣。答案he is wron!! 被双倍赞成并接受,而答案字面上(几乎)给出了被问到的内容 - 被否决了。
【解决方案2】:

恐怕你的组长错了。

引用MSDN

CASE 表达式不能用于控制执行流程 Transact-SQL 语句、语句块、用户定义的函数和 存储过程。有关流控制方法的列表,请参阅 流控制语言 (Transact-SQL)。

Transact-SQL 流控制语言关键字是(没有CASE):

 - BEGIN...END
 - RETURN
 - BREAK
 - TRY...CATCH
 - CONTINUE
 - WAITFOR
 - GOTO label
 - WHILE
 - IF...ELSE

另一方面,您的查询可以改进(如果满足条件,则无需检查另一个IF(s)

CREATE PROCEDURE dbo.usp_SPCaller
@Input_Param1 NVARCHAR(100) = NULL,
@Input_Param2 NVARCHAR(100) = NULL

AS
BEGIN
SET NOCOUNT ON    

IF ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NOT NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam1And2
   END 
ELSE IF ((@Input_Param1 IS NOT NULL) AND (@Input_Param2 IS NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam1Only
   END
ELSE IF ((@Input_Param1 IS NULL) AND (@Input_Param2 IS NOT NULL))
   BEGIN
       EXEC dbo.usp_SPWithParam2Only
   END  
ELSE IF ((@Input_Param1 IS NULL) AND (@Input_Param2 IS NULL))
   BEGIN
       EXEC dbo.usp_SPWithoutParam1And2
   END

编辑 - 由于动态查询CASE

总而言之,有一种方法可以通过动态查询来强制 CASE 行为,就像 Sushil Sharma 发布的那样。

有一个问题!使用动态查询,当不需要时,将通过SQL Injection 给任何潜在的附加者一个攻击向量,所以在我看来,最好使用一个简单的解决方案IF ... ELSE IF 执行已经预定义的程序。

【讨论】:

    【解决方案3】:

    你的线索是错误的。事实上,SQL Server 中没有case statement 这样的东西,它是case expression

    “CASE 表达式不能用于控制 Transact-SQL 语句、语句块、用户定义函数和存储过程的执行流程。”

    Reference

    【讨论】:

      【解决方案4】:

      告诉你的领导他错了(也许以更礼貌的方式)。 T-SQL 中没有 CASE 语句,只有一个 case 表达式。因此,如果您现在拥有它们,请继续使用它们。

      【讨论】:

        猜你喜欢
        • 2011-04-29
        • 2019-07-23
        • 1970-01-01
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-02
        • 2015-07-26
        相关资源
        最近更新 更多