【问题标题】:Dynamic stored procedure to update a table更新表的动态存储过程
【发布时间】:2019-06-12 17:37:23
【问题描述】:

应用程序开发人员要求我创建三个不同的存储过程来更新同一个表。每个存储过程更新不同的列,并在其应用程序的不同点调用。我知道必须有一种方法可以创建一个可以完成工作的组合存储过程。

起初,我尝试创建一个带有“switch”参数的存储过程,该参数会根据 switch 参数更新每个存储过程中的列。

CREATE PROCEDURE dbo.[Upd_table1] 
    (@switch INT, @ID INT, 
     @col1 INT, @col2 INT, @col3 INT, @col4 INT, @col5 INT,
     @col6 INT, @col7 INT, @col8 INT, @col9 INT)
AS
BEGIN
    IF (@switch = 1)
        UPDATE dbo.table1
        SET col1 = @col1, col4 = @col4, col5 = @col5, col6 = @col6
        WHERE ID = @ID
    ELSE IF (@switch = 2)
        UPDATE dbo.table1
        SET col2 = @col2, col9 = @col9
        WHERE ID = @ID
    ELSE IF (@switch = 3)
        UPDATE dbo.table1
        SET col3 = @col3, col7 = @col7, col8 = @col8
        WHERE ID = @ID
END

这按预期工作,但我想知道是否有办法移除开关并使用提供的任何参数更新表。

【问题讨论】:

  • 你有没有尝试使用CASE表达式?
  • 有,但不如使用开关高效。您可以将更新写为UPDATE dbo.table1 SET col1 = ISNULL(@col1, col1), col2=ISNULL(@col2, col2), ..., col9 = ISNULL(@col9, col9) WHERE ID = @ID。这会产生相当多的开销,并且不会处理有人不小心为不应针对此特定情况更新的参数传递非 NULL 值的情况。
  • @LaughingVergil 这是我的一个想法,但想知道是否有更好的方法;似乎没有?感谢您的帮助

标签: sql-server tsql sql-server-2012


【解决方案1】:

我会使用 COALESCE:返回第一个非空参数。

SET COL1 = COALESCE(@Col1, Col1) = 如果 @Col1 为 NULL,则取 col1 的当前值。 然后,您可以在一次操作中更新所有字段。

UPDATE dbo.table1
        SET col1 = COALESCE(@col1,col1), col2=COALESCE(@col2,col2), col3=COALESCE(@col3,col3), etc...
        WHERE ID = @ID

【讨论】:

  • 正如我在上面的评论中指出的,这确实增加了程序的开销,并允许不正确的更新。
  • @LaughingVergil 是的,但是如果构建应用程序以防止那些不正确的更新,这可能是一个解决方案。我同意在大多数情况下,OP 同事可能是对的:每个不同的情况都有一个存储过程。
  • @Bestter 老实说,我想知道我是否通过尝试创建一个可以更新他们指定的任何列的过程来过度思考它。最初的转换想法是否可行且不会产生大量开销?
  • 这不会按预期工作,因为您正在检查 NULL 而 OP 需要检查 @Switch 变量的值并根据它更新表。
  • @Sami - 重新阅读 OP 的问题。他问是否可以在不传递开关值的情况下完成此操作。
【解决方案2】:

有一种方法可以根据开关之间没有重叠列更新的事实来模拟开关功能。

CREATE PROCEDURE dbo.[Upd_table1] (@switch INT, @ID INT, @col1 INT, @col2 INT, @col3 INT, @col4 INT, @col5 INT, @col6 INT, @col7 INT, @col8 INT, @col9 INT )
AS
BEGIN
    IF @Col1 IS NOT NULL AND @Col2 IS NULL AND @Col3 IS NULL -- switch = 1 equivalent
        UPDATE dbo.table1
            SET col1 = @col1, col4 = @col4, col5 = @col5, col6 = @col6
        WHERE ID = @ID
    ELSE IF @Col2 IS NOT NULL AND @Col1 IS NULL and @Col3 IS NULL -- switch = 2 equivalent
        UPDATE dbo.table1
            SET col2 = @col2, col9 = @col9
        WHERE ID = @ID
    ELSE IF @Col3 IS NOT NULL AND @Col1 IS NULL and @Col2 IS NULL -- switch = 2 equivalent
        UPDATE dbo.table1
            SET col3 = @col3, col7 = @col7, col8 = @col8
        WHERE ID = @ID
    ELSE
    -- Handle error case of incorrect parameters here
        RAISERROR('Incorrect Parameters passed to [Upd_table1]', 16, 1) -- sample error handler
END

【讨论】:

  • @Bestter - 我并没有说它更好,只是它执行了相同的任务而没有传入开关值,并且它完全按照开关的作用(不更新传入的无关值)并在检查的键值中传入不正确的值时调用。
猜你喜欢
  • 2019-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
相关资源
最近更新 更多