2011-05-09 8 views
6

मैं एक ही तालिका में एक रिकॉर्ड और इसके वंशजों को क्लोन करने में सक्षम होना चाहता हूं। मेरी मेज का एक उदाहरण निम्नलिखित होगा:एसक्यूएल - एक रिकॉर्ड क्लोन करें और इसके वंशज

Table1

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

"आईडी" स्तंभ प्राथमिक कुंजी और ऑटो वेतन वृद्धि है। 'खाद्य' रिकॉर्ड (यानी जहां आईडी = 1) के पास दो स्वाद हैं जिन्हें 'स्वाद' और 'मूल्य' कहा जाता है। 'स्वाद' रिकॉर्ड में 'स्वाद आवश्यकता' नामक एक रिकॉर्ड है। मैं 'खाद्य' रिकॉर्ड क्लोन बना लिया जाएगा चाहते हैं ताकि 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' 

(जहां 'कुकी' नई श्रेणी का नाम है कि मैं चाहता हूँ सर्जन करना)। मैं का उपयोग कर 'खाद्य' के सभी सन्तान का चयन करने में सक्षम हूँ:

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 

और मैं सिर्फ 'खाद्य' रिकॉर्ड क्लोन करने के लिए कर रहा हूँ (यानी जहां आईडी = 1) का उपयोग करते हुए:

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

लेकिन मुझे 'खाद्य' के वंशजों को क्लोन करने के लिए दो प्रश्नों को गठबंधन करने की कोशिश करने में समस्याएं आ रही हैं। इसके अलावा, मैं संग्रहित प्रक्रियाओं, ट्रिगर, curosrs, आदि का उपयोग करने से बचने की कोशिश कर रहा हूँ क्या मैं संभव करने की कोशिश कर रहा हूँ? मैंने वेब पर कुछ उदाहरण देखे हैं लेकिन मेरी आवश्यकताओं के लिए उन्हें लागू करने में असमर्थ रहे हैं।

+0

के रूप में 'id' एक' identity' स्तंभ मुझे लगता है कि अपने ही विकल्प के रूप में वहाँ पदानुक्रम में स्तर हैं के रूप में कई 'insert' संचालन करते हैं और कब्जा नव डाला करने के लिए कर रहे हैं 'आउटपुट' क्लॉज के साथ आईडी या किसी समवर्ती डालने के प्रयासों को अवरुद्ध करने के लिए, 'id' मानों को स्वयं गणना करें, फिर उन्हें' identity_insert' के साथ एक ऑपरेशन में डालें। –

+0

मुझे आश्चर्य है कि क्या आप एक सम्मिलित ट्रिगर का उपयोग कर सकते हैं? –

+0

यदि नाम अद्वितीय होने की गारंटी नहीं है, तो आप पदानुक्रम में * पंक्तियां * के रूप में कार्य कर सकते हैं, जब तक कि आप मेर्ज का उपयोग न करें, जो आपको स्रोत के बीच संबंधों को याद करते हुए सेट में पूरे स्तर को सम्मिलित करने की अनुमति देता है और लक्ष्य। आप तकनीक [यहां] के बारे में और अधिक पढ़ सकते हैं (http://stackoverflow.com/questions/5365629/using-merge-output-to-get-mapping-between-source-id-and-target-id)। –

उत्तर

2

जैसा कि मार्टिन ने सुझाव दिया था, आपको IDENTITY_INSERT को सक्षम करने की आवश्यकता है ताकि आप अपनी पहचान मानों को धक्का दे सकें। यह सुनिश्चित करने के लिए कि अधिकतम (आईडी) सही मान देता है, आपको टेबल लॉक भी प्राप्त करने की आवश्यकता हो सकती है।

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

मानते हुए अपने CTE एक रूट रिकॉर्ड उठाता है और सभी यह वंशज है (यह जब मैं ऊपर अपने डेटा का उपयोग कर reproduced नहीं लगता था), तो आप सभी चयनित रिकॉर्ड क्लोन और इस तरह सम्मिलित कर सकते हैं:

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 
संबंधित मुद्दे