SQL - клонировать запись и ее потомков - PullRequest
6 голосов
/ 10 мая 2011

Я хотел бы иметь возможность клонировать запись и ее потомков в одной таблице.Примером моей таблицы может быть следующий:

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

но у меня возникают проблемы при попытке объединить два запроса для клонирования потомков 'Food'.Кроме того, я стараюсь избегать использования хранимых процедур, триггеров, curosrs и т. Д. Возможно ли то, что я пытаюсь сделать?Я видел некоторые примеры в Интернете, но не смог применить их к моим требованиям.

Ответы [ 2 ]

2 голосов
/ 10 мая 2011

Как предложил Мартин, вам нужно включить 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
0 голосов
/ 10 мая 2011

Предполагая, что ваш 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...