在sql中的行的级联副本

时间:2011-07-18 01:10:35

标签: sql sql-server-2008

我在这里找到了这个帖子:http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=16836 我有完全一样的问题。引用:

  
    

Rob Pearmain写道:“我有3个表格存在问题。

  
     

表1:问题

     

字段:ID(唯一)字段:名称(文本)

     

表2:问题文本(参考表1-ID)

     

字段:ID(唯一)字段:QuestionID(表1 ID的整数引用)   字段:文字

     

表3:选项

     

字段:ID(唯一)字段:QuestionTextID(表2 ID的整数引用)   字段:文字

     

比如说,我创建了一个带有2个问题文本记录的问题   5个选项记录。如果我想将该问题复制到新问题   问题,并将问题文本记录复制到新ID,以及所有   相关的选项,我怎么能这么容易做到(作为重复   问题将有一个新的ID,每个重复的问题文本   会有每个选项的新ID。“

建议的解决方案是:

create procedure CopyQuestion
@idtocopy int
AS
declare @tempquestionid
declare @tempquestiontextid
declare @questiontextid

insert into question (name)
     select name from question where id = @idtocopy

select @tempquestionid = @@identity

declare question_cursor cursor for
     select id from [question text] where id = @idtocopy
open question_cursor
fetch next from question_cursor into @questiontextid
while @@fetch_status = 0
begin
   insert into [question text] (questionid, text)
      select @tempquestionid, text from [question text] where id = @questiontextid
   select @tempquestiontextid = @@identity
      insert into [options] (questiontextid, text)
   select @tempquestiontextid, text from [options] where questiontextid = @questiontextid
   fetch next from question_cursor into @questiontextid
end
close question_cursor
deallocate question_cursor

这个问题有更好的解决方案吗?我将使用插入触发器。 谢谢!

2 个答案:

答案 0 :(得分:4)

您可以将merge语句与output子句一起使用,以在questionText中获取旧ID和新ID之间的匹配项。这个问题在Using merge..output to get mapping between source.id and target.id中进行了描述。

在您的情况下,代码看起来像这样。代码未经过测试,因此可能存在任何数量的拼写错误,但它显示了您可以执行的操作。

create procedure CopyQuestion
  @idtocopy int
as

declare @QuestionID int

insert into question
select Name 
from question 
where ID = @idtocopy

select @QuestionID = scope_identity() 

declare @IDs table (NewQID int, OldQID int)

merge questionText as T
using (select ID, @QuestionID as QuestionID, Field
       from questionText
       where QuestionID = @idtocopy) as S
on 0=1
when not matched then
  insert (QuestionID, Field) values (QuestionID, Field)
output inserted.ID, S.ID   into @IDs;       

insert into options
select 
    I.NewQID,
    O.Field
from options O
  inner join @IDs as I
    on O.QuestionTextID = I.OldQID

答案 1 :(得分:0)

这是另一种方法,可以根据设置做同样的事情。在下面的示例中,我使用临时表来映射两个新表之间的ID。另外,请从表名中删除空格(仅仅因为你的意思不应该这样)。

CREATE PROCEDURE udf_COPY_QUESTION 
@ID_TO_COPY int
 as 
BEGIN TRANSACTION
BEGIN TRY
DECLARE @NEW_QUESTION_ID INT, @MAX_ID INT
insert into question (name)
     select name from question where id = @ID_TO_COPY
SET @NEW_QUESTION_ID = SCOPE_IDENTITY()
SET @MAX_ID =IDENT_CURRENT( 'question text' )
select @NEW_QUESTION_ID AS questionid,
       Text,
       ROW_NUMBER() OVER (ORDER NAME) + @MAX_ID as new_text_id, 
       id as old_text_id
 INTO  #TEMP  from [question text] 
      where questionid = @ID_TO_COPY         
insert into [question text] (QuestionID,Text)
      select questionid,Text from #TEMP 
      order by new_text_id
insert into Options  (questiontextid, text) 
      select t.new_text_id,o.Text from options o
      inner join #temp t on t.old_text_id = o.questiontextid
COMMIT TRANSACTION
END TRY
BEGIN CATCH
    RAISERROR('COPY FAILED',10,1)
    ROLLBACK TRANSACTION 
END CATCH