我有一个表格,其中有一些版本号为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
提前致谢。
答案 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子句中包含的表,该语句用于指定要更新或删除的行。