SQL - 克隆记录及其后代

标签 sql sql-server tsql sql-server-2008

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

表1

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

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

表1

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

我可以使用以下方法克隆“食物”记录(即 id = 1):

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

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

最佳答案

正如 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

关于SQL - 克隆记录及其后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5943691/

相关文章:

mysql - 在 MYSQL 查询中将 REGEXP 转换为 LIKE

sql-server - localhost和(LocalDb)/MSSQLLocalDB的sql区别

对不相关或具有主键的两个表进行 SQL 联接

sql - 按 IN 子句的顺序选择记录

sql-server - 如何重命名物理数据库文件

sql - 为什么有人要使用 JDBC 而不是 korma 之类的库?

java - 如何通过java代码执行Oracle sql脚本

mysql - 检查列中的多个值并返回值 1 或 0

sql - 查找具有匹配行的组

tsql - 选择具有最大值的记录