UPDATE命令SET @return = [int_a] = [int_a] + auto_increment WHERE <clause> </clause>

时间:2014-08-11 18:02:27

标签: sql sql-server tsql

我们有很多C#程序和SQL存储过程调用一个可怕写的SQL存储过程(320多行包含许多类似的IF已被复制和粘贴多年),我需要最终清理和加速起来。

注意:

  • 此存储过程每小时执行1,000次。
  • 这个问题是关于这个存储过程,而不是如何引用或更改引用。

我们有一个具有这种结构的表:

  • type(VARCHAR)
  • 上次更新(DATETIME)
  • counter(INT)
  • auto_increment flag(INT,0或1)

(即:递增的客户#123456,以及非递增的结算周期#1001)

执行时:

  • 客户#:将123456增加到123457,last_updated = now,&amp;返回新的123457。
  • 结算周期:返回值1001.

我的老板希望只有一个命令能够击中表格。我已经设法用这个片段完成了这个:

DECLARE
    @return_value INT,
    @parmtype VARCHAR(10),

SET @parmtype = 'CUSTOMER'

UPDATE [system_numbers]                  -- 1 hit
SET @return_value = current_number = current_number + auto_increment,
    last_updated_on = 
        CASE auto_increment
            WHEN 1 THEN GETDATE()
            ELSE last_updated_on
        END
    WHERE [type] = @parmtype

我的问题是,对于非递增的[type],我的命令不必要地更新表,写入日志,并且比SELECT慢。

我的问题是...... 我可以使用哪个命令删除此示例的两个匹配到桌面?

DECLARE
    @return_value INT,                    -- actually an OUTPUT param in my SP
    @autoincrement INT,
    @parmtype VARCHAR(10)

SET @parmtype = 'CUSTOMER'

SELECT @autoincrement = auto_increment    -- 1st hit
FROM [system_numbers]
WHERE [type] = @parmtype

IF (@autoincrement = 1)
BEGIN
    UPDATE [system_numbers]               -- 2nd hit here - or -
    SET @return_value = current_number = current_number + auto_increment,
        last_updated_on = GETDATE()
        WHERE [type] = @parmtype
END
ELSE
BEGIN
    SELECT @return_value = current_number -- 2nd hit here
    FROM [system_numbers]
    WHERE [type] = @parmtype
END

3 个答案:

答案 0 :(得分:1)

我认为这会简化一些事情

DECLARE
@return_value INT,                    -- actually an OUTPUT param in my SP
@autoincrement INT,
@parmtype VARCHAR(10)

SET @parmtype = 'CUSTOMER'

SELECT @autoincrement = auto_increment, @return_value = auto_increment + current_number    -- 1st hit
FROM [system_numbers]
WHERE [type] = UPPER(@parmtype)

IF (@autoincrement = 1)
BEGIN
UPDATE [system_numbers]               -- 2nd hit here - or -
SET current_number = @return_value,
    last_updated_on = GETDATE()
    WHERE [type] = UPPER(@parmtype)
END

答案 1 :(得分:1)

我可能会考虑以下方法:

...

UPDATE dbo.system_numbers
SET @return_value = current_number = current_number + auto_increment,
    last_updated_on = GETDATE()
WHERE [type] = @parmtype
  AND auto_increment = 1
;
IF @@ROWCOUNT = 0
  SELECT @return_value = current_number
  FROM dbo.system_numbers
  WHERE [type] = @parmtype
;

第一个语句仅在恰好是递增值时更新值,并且还将更新后的值存储在@return_value中。

如果第一个语句没有更新任何行,则仅执行第二个语句。它只是将(当前)值分配给@return_value

所以,只有当值是递增值时才会出现这种情况。当它不递增时,涉及第二次命中,但在这种情况下也没有任何更新,只读。

答案 2 :(得分:0)

我们认为IF EXISTS()命令很快,可以满足我们的需求。

奖励是,如果它返回true,我们知道@parmtype是自动递增的,我们不再需要变量@autoincrement,这样可以使代码更清晰。

DECLARE
    @return_value INT,       -- OUTPUT param
    @parmtype VARCHAR(10)

SET @parmtype = 'CUSTOMER'

IF EXISTS ( SELECT * FROM [table] WHERE [type]=@parmtype AND auto_increment=1 )
BEGIN
    UPDATE [table]
    SET @return_value = current_number = current_number + auto_increment,
        last_updated_on = GETDATE()
    WHERE [type] = @parmtype
END
ELSE
BEGIN
    SELECT @return_value = current_number
    FROM [table]
    WHERE [type] = @parmtype
END