在sql server中将记录从现有版本复制到新版本

时间:2015-01-16 19:52:31

标签: sql-server sql-server-2012

我有一个表格,其中有一些版本号为1的行,这些行都有     相应的父ID如果父ID为null,则它是其他父项     具有父ID的子,我想写查询来复制所有行     从版本号1到2并插入具有新的相应parentid的新行。     下面是我的表和一些数据脚本。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Menu](
[MenuId] [bigint] IDENTITY(1,1) NOT NULL,
[MenuName] [nvarchar](50) NULL,
[ParentId] [bigint] NULL,
[VersionNumber] [bigint] NULL,
CONSTRAINT [PK_Menu] PRIMARY KEY CLUSTERED 
(
[MenuId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Menu] ON 

INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber])     VALUES (1, N'Customer', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (2, N'Home', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (3, N'About', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (4, N'Add Customer', 1, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (5, N'Administration', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (6, N'Edit Customer', 1, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (7, N'Tenant', 5, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (8, N'Manage Contact', 5, 1)
 INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (9, N'Users', 5, 1)
 INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (10, N'Customer List', 1, 1)
 INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (11, N'Contact', NULL, 1)`enter code here`
   SET IDENTITY_INSERT [dbo].[Menu] OFF

提前致谢。

2 个答案:

答案 0 :(得分:0)

我觉得这个问题还有更多我正在阅读的内容,但是如果您只想复制数据并将版本号从1更改为2,那么这将有效。

INSERT  INTO dbo.Menu
        ( MenuName,
          ParentId,
          VersionNumber )
        SELECT  m.MenuName,
                m.ParentId,
                2
        FROM    Menu AS m
        WHERE   m.VersionNumber = 1

答案 1 :(得分:0)

这个有点棘手。

但下面是一个有效的解决方案。

带有输出值和原始值的“MERGE”(将两种类型的值都放入#Holder表中)就是诀窍。

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Menu' and TABLE_TYPE = N'BASE TABLE' ) 
BEGIN 
DROP TABLE [dbo].[Menu] 
END 
GO



CREATE TABLE [dbo].[Menu](
[MenuId] [bigint] IDENTITY(1,1) NOT NULL,
[MenuName] [nvarchar](50) NULL,
[ParentId] [bigint] NULL,
[VersionNumber] [bigint] NULL,
CONSTRAINT [PK_Menu] PRIMARY KEY CLUSTERED 
(
[MenuId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Menu] ON 

INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber])     VALUES (1, N'Customer', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (2, N'Home', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (3, N'About', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (4, N'Add Customer', 1, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (5, N'Administration', NULL, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (6, N'Edit Customer', 1, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (7, N'Tenant', 5, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (8, N'Manage Contact', 5, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (9, N'Users', 5, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (10, N'Customer List', 1, 1)
INSERT [dbo].[Menu] ([MenuId], [MenuName], [ParentId], [VersionNumber]) VALUES (11, N'Contact', NULL, 1)


   SET IDENTITY_INSERT [dbo].[Menu] OFF

   select * from [dbo].[Menu] 


    IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
    begin
            drop table #Holder
    end

    /* The "mapping values" holder/tracking table */
    CREATE TABLE #Holder
    ( 
    --SurrogateKeyIDENTITY int not null IDENTITY (1,1) , 
    OriginalMenuId [bigint]  NULL,
    OriginalParentId [bigint] NULL,
    NewMenuSurrogateKey int null ,
    NewParentIdSurrogateKey int null
    )


/* This is the key trick.  You need to do the INSERT and keep track of old and new surrogate keys.  The MERGE trick is the only way to get values into the #holder...combining "output" values and original values */
MERGE INTO [dbo].[Menu] pc
USING [dbo].[Menu] AS sourceTable 
ON  1 = 0 
WHEN NOT MATCHED THEN
  INSERT([MenuName], [VersionNumber])
   Values([MenuName] , [VersionNumber] + 1 ) /* Here is your "plus one" for the Version */
Output sourceTable.MenuId , sourceTable.ParentId , inserted.MenuID INTO 
  #Holder (OriginalMenuId , [OriginalParentId] , NewMenuSurrogateKey );

Select 'Before the NewParentIdSurrogateKey is Updated Values' as Lab1 ,  * from #Holder


Update holderAsParent Set NewParentIdSurrogateKey = holderAsChild.NewMenuSurrogateKey
/* You can comment out the previous update and uncomment the next select statement to see what the update is trying to do */
/* Select 'Here1' as Lab1 ,  holderAsChild.NewMenuSurrogateKey, '----' as Sep1, holderAsChild.* , '----' as Sep2 , holderAsParent.* */
from
#Holder holderAsChild 
join #Holder holderAsParent on holderAsChild.OriginalMenuId = holderAsParent.OriginalParentId


Select 'ShouldHaveAllTheMappingValuesInTheHolderNow' as Lab1 ,  * from #Holder


Update dbo.Menu Set [ParentId] = holder.NewParentIdSurrogateKey
from 
dbo.Menu men join #Holder holder on men.MenuId = holder.NewMenuSurrogateKey
where holder.NewParentIdSurrogateKey iS NOT NULL

Select 'Final Results' as Lab1 ,  * from dbo.Menu


IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
        drop table #Holder
end

/* Sanity Check */


Select COALESCE(parent.MenuName + ' -- ', '') + child.MenuName as ParentThenChildMenuName, child.VersionNumber
from
    [dbo].[Menu] child
    left join
    [dbo].[Menu] parent
    on child.ParentId = parent.MenuId
where child.VersionNumber = 1
order by parent.MenuName , child.MenuName



Select COALESCE(parent.MenuName + ' -- ', '') + child.MenuName as ParentThenChildMenuName, child.VersionNumber
from
    [dbo].[Menu] child
    left join
    [dbo].[Menu] parent
    on child.ParentId = parent.MenuId
where child.VersionNumber = 2
order by parent.MenuName , child.MenuName

以下是参考资料。对于这种特殊情况,这是导致在“from_table_name”中使用MERGE的一点点提示。

http://msdn.microsoft.com/en-us/library/ms177564.aspx “from_table_name” 是一个列前缀,用于指定DELETE,UPDATE或MERGE语句的FROM子句中包含的表,该语句用于指定要更新或删除的行。