在一个存储过程中有多个作业是一个好主意吗?

时间:2016-03-04 14:51:41

标签: sql sql-server stored-procedures

关于这种情况的最佳做法是什么?

我想对我的数据库中的单个实体执行多个DIFFERENT操作。我想插入数据,删除行等(仅限基本功能),我想知道在一个实体中执行所有操作是否是一个好主意使用如下标志参数的存储过程:

CREATE PROCEDURE usp_entity
    @flag INT
    @id AS INT = 0
    @field AS VARCHAR = NULL
AS
BEGIN
    IF @flag = 1
    INSERT INTO entity (field) VALUES (@field)
    ELSE IF @flag = 2
    DELETE FROM entity WHERE id = @id
END

或者,最好是创建不同的存储过程,例如ups_entity_insertusp_entity_delete来完成这些任务?

我问这个的原因是因为我们的老师之前做了第一种方法,我不确定这是不是正确的方法

3 个答案:

答案 0 :(得分:3)

  

我想在我的单个实体上做多个DIFFERENT操作   database.I想插入数据,删除行等(基本   仅我的功能)我想知道这是否是一个好主意   所有这些都在一个存储过程中使用flag参数,如下所示:

我不会这样做。对于那些继续执行代码的人来说,它实际上做的事情并不那么清楚。使适当命名的不同存储过程更容易维护,并且对其他人更具描述性。

  

始终将代码视为最终维护代码的人员   暴力的精神病患者谁知道你住在哪里。 - 马丁戈尔丁

安全是将它们分开的另一个原因。如果您在一个过程中放置​​多个操作,则它是一个全有或全无的方法。很多时候某些应用程序需要读取数据,但我不希望它们更新或插入。还有一些时候我需要删除数据,但我真的想控制谁可以访问它。

答案 1 :(得分:3)

在SQL Server中,这可能是一个坏主意。 SQL Server在第一次运行时编译存储过程中的所有查询。使用标志来区分不同的代码路径可能会导致剩余查询的执行计划效率低下。

当然,如果查询是相关的,那么在存储过程中有多个查询是良好的想法。通常,您希望将存储过程视为“执行某些操作”,通常会封装多个步骤。所以,你可能想:

  • 记录正在采取的行动
  • 将行插入一个表
  • 更新另一个表中的行

这些都是“一件事”,所以它们属于一体。

此外,在SQL Server中,如果没有长度参数,请不要使用varchar。默认值因上下文而异,这可能导致难以找到的错误。并且,不要将varchar与整数进行比较。混合类型让人类读者感到困惑,有时也会混淆优化器。

答案 2 :(得分:3)

通常这称为CRUD。对任何实体执行的基本操作:创建阅读更新删除。在您的示例中,您有两种情况:插入和删除;它也可能包括定期更新工作 - 我认为将这些操作放在一个SP中是完全可以的,因为它们都是:

  1. DML
  2. 根据特定的单一记录执行操作
  3. 不返回任何数据集。
  4. 包括读取操作我认为这是一个错误 - 然后SP有时会返回结果集 - 这显然是一种令人困惑的行为。

    其他选项是每个操作都有三个 SP(我在这里没有提到读取操作):一个用于插入,一个用于更新,一个用于删除。在您将实体数量相乘之前,这听起来并没有错。假设您有500个实体,这意味着您有1500个CrUD SP。或者只有500 CrUD SP。

    如果您有单独的SP用于插入/更新/删除,那么您可能必须复制并粘贴参数验证代码,调用日志记录和检查权限SP等。虽然仍然只有一个独特的陈述,其余的都是相似的。

    更新和删除通常在单个记录上执行,插入值没有选择部分,因此我没有看到执行计划或其他任何问题。请注意,如果我没有弄错的话,SQLSERVER可以重新编译单独的语句,而不是重新编译完整的SP,因为mssql2005。

    要使每个操作的SP也没问题,你可能遇到的唯一麻烦 - SP的数量。如果你使用代码生成工具或任何类型的ORM生成它们,那么这项工作就是自动化的(记住重构,包括一些“低级”工作,如日志/跟踪/安全/业务规则/验证),当然没有需要考虑SP的数量,并且在每个动作上单独使用SP可能会更加舒适。

    当然,如果您的SP非常智能,那么每个场景都有大量的代码然后,你可以自己理解,分开维护它们会更容易。因为否则就很难理解。

    而且,包括用于相当不同目的的代码是一个没有任何借口的可怕想法。