SQL - 克隆记录及其后代

发布于 2024-11-06 01:53:29 字数 1290 浏览 0 评论 0原文

我希望能够在同一个表中克隆记录及其后代。我的表的一个示例如下:

Table1

id | parentid | name
---------------------
 1 |    0     |  'Food'
 2 |    1     |  'Taste'
 3 |    1     |  'Price'
 4 |    2     |  'Taste Requirements'

“id”列是主键和自动增量。 “食物”记录(即 id = 1)下面有两个记录,称为“味道”和“价格”。 “品味”记录下面有一个名为“品味要求”的记录。我希望能够克隆“Food”记录,以便 Table1 如下所示:

Table1

id | parentid | name
---------------------
 1 |    0     |  'Food'
 2 |    1     |  'Taste'
 3 |    1     |  'Price'
 4 |    2     |  'Taste Requirements'
 5 |    0     |  'Cookies'
 6 |    5     |  'Taste'
 7 |    5     |  'Price'
 8 |    6     |  'Taste Requirements'

(其中“Cookies”是我要创建的新类别的名称)。我可以使用以下命令选择“Food”的所有后代:

with Table1_CTE( id, parentid, name )
as
(
  select t.id, t.parentid, t.name from Table1 t
    where t.id = 1
  union all
  select t.id, t.parentid,t. name from Table1 t
    inner join Table1_CTE as tc
      on t.parentid = tc.id
)
select id, parentid, name from Table1_CTE

并且可以使用以下命令仅克隆“Food”记录(即 id = 1):

insert into Table1 ( parentid, name )
  select ( parentid, 'Cookies' ) 
  from Table1 where id = 1

但我在尝试组合两个查询来克隆后代时遇到问题的“食物”。另外,我试图避免使用存储过程、触发器、curosrs 等。我想要做的事情可能吗?我在网上看到了一些例子,但无法将它们应用到我的要求。

I would like to be able to clone a record and its descendants in the same table. An example of my table would be the following:

Table1

id | parentid | name
---------------------
 1 |    0     |  'Food'
 2 |    1     |  'Taste'
 3 |    1     |  'Price'
 4 |    2     |  'Taste Requirements'

The "id" column is the primary key and auto-increments. The 'Food' record (i.e. where id = 1) has two records underneath it called 'Taste' and 'Price'. The 'Taste' record has a record underneath it called 'Taste Requirements'. I would like to be able to clone the 'Food' record so that Table1 would look like the following:

Table1

id | parentid | name
---------------------
 1 |    0     |  'Food'
 2 |    1     |  'Taste'
 3 |    1     |  'Price'
 4 |    2     |  'Taste Requirements'
 5 |    0     |  'Cookies'
 6 |    5     |  'Taste'
 7 |    5     |  'Price'
 8 |    6     |  'Taste Requirements'

(where 'Cookies' is the name of the new category that I want to create). I am able to select all the descendants of 'Food' using:

with Table1_CTE( id, parentid, name )
as
(
  select t.id, t.parentid, t.name from Table1 t
    where t.id = 1
  union all
  select t.id, t.parentid,t. name from Table1 t
    inner join Table1_CTE as tc
      on t.parentid = tc.id
)
select id, parentid, name from Table1_CTE

and I am able to clone just the 'Food' record (i.e. where id = 1) using:

insert into Table1 ( parentid, name )
  select ( parentid, 'Cookies' ) 
  from Table1 where id = 1

but I am having problems trying to combine the two queries to clone the descendants of 'Food'. Also, I am trying to avoid using stored procedures, triggers, curosrs, etc. Is what I am trying to do possible? I have seen some examples on the web but have been unable to apply them to my requirements.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美男兮 2024-11-13 01:53:29

正如 Martin 建议的那样,您需要启用 IDENTITY_INSERT 以便可以推送您自己的身份值。您可能还需要获取表锁以确保 Max( Id ) 返回正确的值。

If object_id('tempdb..#TestData') is not null
    Drop Table #TestData
GO
Create Table #TestData
    (
    Id int not null identity(1,1) Primary Key
    , ParentId int not null
    , Name varchar(50) not null
    )
GO
Set Identity_Insert #TestData On
GO  
Insert #TestData( Id, ParentId, Name )
Values( 1,0,'Food' )
    , ( 2,1,'Taste' )
    , ( 3,1,'Price' )
    , ( 4,2,'Taste Requirement' );


With Data As
    (
    Select Cast(MaxId.Id + 1 As int) As Id
        , T.ParentId
        , 'Copy Of ' + T.name As Name
        , T.Id As OldId
        , 0 As OldParentId
    From #TestData As T
        Cross Join( Select Max( id ) As Id From #TestData ) As MaxId
    Where T.Name = 'Food'
    Union All
    Select Cast(Parent.id + Row_Number() Over( Order By Child.Id ) + 1 As int)
        , Parent.Id
        , 'Copy of ' + Child.Name
        , Child.Id
        , Child.ParentId
    From Data As Parent
        Join #TestData As Child
            On Child.ParentId = Parent.OldId
    )
Insert #TestData( Id, ParentId, Name )
Select Id, ParentId, Name
From Data
GO
Set Identity_Insert #TestData Off
GO  

结果

id | parentid | name
-- | -------- | -----------------
1  | 0        | Food
2  | 1        | Taste
3  | 1        | Price
4  | 2        | Taste Requirement
5  | 0        | Copy Of Food
7  | 5        | Copy of Taste
8  | 5        | Copy of Price
9  | 7        | Copy of Taste Requirement

As Martin suggested, you need to enable IDENTITY_INSERT so that you can push your own identity values. You may also need to acquire a table lock to ensure that Max( Id ) returns the correct value.

If object_id('tempdb..#TestData') is not null
    Drop Table #TestData
GO
Create Table #TestData
    (
    Id int not null identity(1,1) Primary Key
    , ParentId int not null
    , Name varchar(50) not null
    )
GO
Set Identity_Insert #TestData On
GO  
Insert #TestData( Id, ParentId, Name )
Values( 1,0,'Food' )
    , ( 2,1,'Taste' )
    , ( 3,1,'Price' )
    , ( 4,2,'Taste Requirement' );


With Data As
    (
    Select Cast(MaxId.Id + 1 As int) As Id
        , T.ParentId
        , 'Copy Of ' + T.name As Name
        , T.Id As OldId
        , 0 As OldParentId
    From #TestData As T
        Cross Join( Select Max( id ) As Id From #TestData ) As MaxId
    Where T.Name = 'Food'
    Union All
    Select Cast(Parent.id + Row_Number() Over( Order By Child.Id ) + 1 As int)
        , Parent.Id
        , 'Copy of ' + Child.Name
        , Child.Id
        , Child.ParentId
    From Data As Parent
        Join #TestData As Child
            On Child.ParentId = Parent.OldId
    )
Insert #TestData( Id, ParentId, Name )
Select Id, ParentId, Name
From Data
GO
Set Identity_Insert #TestData Off
GO  

Results

id | parentid | name
-- | -------- | -----------------
1  | 0        | Food
2  | 1        | Taste
3  | 1        | Price
4  | 2        | Taste Requirement
5  | 0        | Copy Of Food
7  | 5        | Copy of Taste
8  | 5        | Copy of Price
9  | 7        | Copy of Taste Requirement
哎呦我呸! 2024-11-13 01:53:29

假设您的 CTE 选择根记录及其所有后代(当我使用上面的数据进行复制时似乎没有),那么您可以克隆所有选定的记录并像这样插入:

with Table1_CTE( id, parentid, name )
as
(
  select t.id, t.parentid, t.name from Table1 t
    where c.icategoryid = 1
  union all
  select t.id, t.parentid,t. name from Table1
    inner join Table1_CTE as tc
      on t.parentid = tc.id
)
insert into  dbo.testinsertheirarchy  ( parentid, name )  
select  parentid, name from Table1_CTE

Assuming your CTE picks a root record and all it's descendents (it didn't seem to when I reproduced using your data above), then you can clone all selected records and insert like this:

with Table1_CTE( id, parentid, name )
as
(
  select t.id, t.parentid, t.name from Table1 t
    where c.icategoryid = 1
  union all
  select t.id, t.parentid,t. name from Table1
    inner join Table1_CTE as tc
      on t.parentid = tc.id
)
insert into  dbo.testinsertheirarchy  ( parentid, name )  
select  parentid, name from Table1_CTE
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文