【问题标题】:update table using cursor?使用游标更新表?
【发布时间】:2011-06-18 20:46:43
【问题描述】:

更新

本练习的目的是消除再次传递@RegModifiedDateTime 我想要的是我应该能够通过传递Id 来阅读ModifiedDateTime

示例:如果我通过 Id = 564 那么我应该能够阅读

`schoold_Id and ModifiedDateTime`

结束更新

这是我的表在 SchoolRegistration 中的样子:

school_id       id     active        modifydatetime
--------------------------------------------------
432        564       1               2008-12-14 13:15:38.750
342        564       1              2008-12-14 14:15:50.470
353        564       1              2008-12-14 14:19:46.703

结束更新

如何循环更新我的 SchoolRegistration 表? id 在 SchoolRegistration 中可能有 1 行或多行,但问题是 RegModifiedDateTime 是唯一用于并发目的的,我应该循环获取该 id 的正确修改日期时间。

alter procedure [dbo].[del_schoolRegistration]
    @Id bigint, 
    @RegModifiedDateTime datetime
as
begin  
    declare @rowsAffected int
    begin tran 


        --registration
        update SchoolRegistration
                   set Active = 0,
                    ModifiedDateTime = getdate()            
        where (Id = @Id and RegModifiedDateTime = @RegModifiedDateTime or @RegModifiedDateTime is null )


    if (@rowsAffected < 1) begin
        rollback tran
    end
    else begin
        commit tran
    end

    return @rowsAffected

end 

【问题讨论】:

  • 为什么你需要在CURSOR 上做这个UPDATE?,你不能只做一个UPDATE 吗?另外,我相信您的条件OR @RegModifiedDateTime is null 是错误的,因为当该列为空时,它会更新您的整个表,而不仅仅是@id
  • RegModifiedDateTime 是唯一的并发目的,它应该循环获取该 id 的正确 modifydatetime。
  • @Abu Hamzah “对于并发目的是独一无二的”,您将不得不解释这一点。 getdate() 上的解决方案也会给你带来问题
  • @Abu。我不明白什么样的系统需要具有唯一约束的 modifydatetime 字段。
  • @Abu Hamzah 乐观并发不需要这个。为什么会这样?

标签: sql sql-server-2008


【解决方案1】:

我最终使用 curor:

USE AdventureWorks
GO
DECLARE @ProductID INT
DECLARE @getProductID CURSOR
SET @getProductID = CURSOR FOR
SELECT ProductID
FROM Production.Product
OPEN @getProductID
FETCH NEXT
FROM @getProductID INTO @ProductID
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @ProductID
FETCH NEXT
FROM @getProductID INTO @ProductID
END
CLOSE @getProductID
DEALLOCATE @getProductID
GO

【讨论】:

    【解决方案2】:
       --registration
        ;with tmp as (
            select *, rn=ROW_NUMBER() over (partition by ID order by RegModifiedDateTime desc)
            from SchoolRegistration
            where (Id = @Id and RegModifiedDateTime = @RegModifiedDateTime or @RegModifiedDateTime is null ))
        update tmp
                   set Active = 0,
                    ModifiedDateTime = getdate()            
        WHERE rn=1
    

    这里发生的情况是,如果您不知道您正在寻找的 RegModifiedDateTime(通过将 @RegModifiedDateTime 传递为 NULL),查询将捕获它们所有的 ID,因为 @RegModifiedDateTime is null,但仅更新基于最新的 RegModifiedDateTime在 row_numbering 和 CTE 表定义上。

    编辑

    上面的查询保留了直接传递@RegModifiedDateTime 的选项,如果记录不是最近需要更新的记录。要始终只更新最新的,请完全删除针对 @RegModifiedDateTime 的 WHERE 过滤器

       --registration
        ;with tmp as (
            select *, rn=ROW_NUMBER() over (partition by ID order by RegModifiedDateTime desc)
            from SchoolRegistration
            where Id = @Id)
        update tmp
                   set Active = 0,
                    ModifiedDateTime = getdate()            
        WHERE rn=1
    

    【讨论】:

    • @Cyber​​Kiwi:这个练习的目的是消除通过@RegModifiedDateTime 使用上面的代码我没有看到任何好处......我再次想要的是我应该能够阅读RegModifiedDateTime 通过传递Id,例如:如果我传递 Id = 564,则 ni 应该能够读取 schoold_Id and ModifiedDateTime
    • @cyberkiwi 除非我完全误解,否则 OP 正在寻找一种解决方案,为每条记录生成唯一的 ModidifedDateTimes
    • @Conrad Frix 我试过了,但我不明白 OP 想要做什么。
    • @cyberkiwi: 当我执行 jsut 这段代码;with tmp as ( select *, rn=ROW_NUMBER() over (partition by ID order by RegModifiedDateTime desc) from SchoolRegistration where Id = @Id) 我得到这个错误Incorrect syntax near ')'.
    • @abu,你 cannot 独自运行。 WITH 设置了一个公共表表达式,你需要使用它来做一些事情,比如它后面的 UPDATE 语句
    猜你喜欢
    • 2020-09-14
    • 1970-01-01
    • 2016-10-08
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多