【问题标题】:Linked table insert without cursors没有游标的链接表插入
【发布时间】:2014-06-25 16:16:37
【问题描述】:

tl;dr

使用 SQLServer 2005(我们支持的最低版本),是否可以在不使用游标的情况下从链接表中复制数据?

详情

我有两张表,大致结构如下...

dbo.[ParentTable]
[ItemId]  [UserId]  [Details]
1         1         'One'
2         1         'Two'

dbo.[ChildTable]
[ChildId]  [ItemId]  [Details]
1          1         'One A'
2          1         'One B'
3          2         'Two A'
4          2         'Two B'

ParentTable.ItemId 是具有身份 (1,1) 的 PK
ChildTable.ChildId 是具有身份 (1,1) 的 PK
ChildTable.ItemIdParentTable.ItemId 的 FK

目前,如果我需要将UserId=1 的所有数据复制到UserId=2,我必须执行以下操作...

DECLARE @ItemId INT, @NewItemId INT

DECLARE [ParentCursor] CURSOR FOR
SELECT [ItemId]
FROM [ParentTable]
WHERE [UserId] = 1

OPEN [ParentCursor]
FETCH NEXT FROM [ParentCursor] INTO @ItemId
WHILE @@FETCH_STATUS = 0
BEGIN
  INSERT INTO [ParentTable] ([UserId], [Details])
  SELECT 2, [Details]
  FROM [ParentTable]
  WHERE [ItemId] = @ItemId

  SET @NewItemId = @@IDENTITY

  INSERT INTO [ChildTable] ([ItemId], [Details]
  SELECT @NewItemId, [Details]
  FROM [ChildTable]
  WHERE [ItemId] = @ItemId

  FETCH NEXT FROM [ParentCursor] INTO @ItemId
END
CLOSE [ParentCursor]
DEALLOCATE [ParentCursor]

这实现了...的预期结果

dbo.[ParentTable]
[ItemId]  [UserId]  [Details]
1         1         'One'
2         1         'Two'
3         2         'One'
4         2         'Two'

dbo.[ChildTable]
[ChildId]  [ItemId]  [Details]
1          1         'One A'
2          1         'One B'
3          2         'Two A'
4          2         'Two B'
5          3         'One A'
6          3         'One B'
7          4         'Two A'
8          4         'Two B'

有没有更简单的不使用光标的方法?

(注意,我已经尝试创建一个http://sqlfiddle.com,但我根本无法让它正确使用光标。与分隔符有关,但我无法弄清楚。)

【问题讨论】:

    标签: sql-server tsql sql-server-2005 cursor


    【解决方案1】:

    这样的……

    declare @olduser int = 1, @newuser int = 2
    set transaction isolation level serializable
    begin tran
    
        declare @max int 
        select @max = MAX(itemid) from ParentTable -- as a marker for new records
    
        -- insert all the parents
        insert ParentTable (userid, details) 
        select @newuser, details from ParentTable where userid=@olduser order by itemid
    
    
        insert ChildTable (itemid, details)             
        select newid, details from ChildTable child
            inner join 
        (
                -- join the old parents to the new parents
        select p2.itemid as oldid, p1.itemid as newid   
        from 
            (select *, ROW_NUMBER() over (order by itemid) rn from parenttable where itemid>@max) p1
            inner join 
            (select *, ROW_NUMBER() over (order by itemid) rn from parenttable where userid=@olduser and itemid<=@max) p2
                on p1.rn = p2.rn
        ) oldparents
            on child.itemid = oldparents.oldid
    commit tran
    

    【讨论】:

    • 哇——要带我把我比平均水平小的大脑包裹在那个周围!谢谢 podiluska
    • @freefaller 它依赖于 ParentTable 中的详细信息在用户中是唯一的。
    • 不幸的是,这无法保证......尽管 [Parent] 和 [Child] 表中的列更多。我要演戏
    • @freefaller 我已经改进了它,所以不再是这种情况了。
    猜你喜欢
    • 2017-02-09
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2023-03-28
    • 2013-11-30
    • 1970-01-01
    相关资源
    最近更新 更多