在导出一些比较恶心的表设计的数据时,比如几张表,每个表都有和上一个表的父子级对应关系,当从一个环境导出到另一个环境时,id不一定相同,那么如果要保持它们之间的对应关系该如何搞定。其实有一个非常好用的办法。
比如我们有一张表,system_stack_space
1 CREATE TABLE [dbo].[system_stack_space] ( 2 [space_id] int NOT NULL, 3 [space_name] varchar(500) NULL, 4 [parent_id] int NULL, 5 [tstamp] datetime NULL, 6 CONSTRAINT [PK_system_stack_space] PRIMARY KEY([space_id]) 7 ) 8 GO
这张表中,记录了很多的空间,每个空间有自己的父级空间或者下面的子空间,如何我们想要把任意其中某一个*空间(即没有父级空间的空间)下面的所有子空间都按照其原有的关系复制并且生成出一份全新的空间,可以这么去搞:
创建临时表变量来存储需要处理的原有数据,注意这里面除了原有的space_id,还添加了一个id,并且是自增长的,后面会很重要
1 if exists(select * from tempdb..sysobjects where id=object_id('tempdb..#system_stack_space')) 2 begin 3 drop table #system_stack_space 4 end 5 CREATE TABLE #system_stack_space ( 6 [id] int identity(1,1) not null, 7 [space_id] int NOT NULL, 8 [space_name] varchar(500) NOT NULL, 9 [parent_id] int NOT NULL, 10 [tstamp] datetime NOT NULL 11 ) 12 if exists(select * from tempdb..sysobjects where id=object_id('tempdb..#system_stack_space2')) 13 begin 14 drop table #system_stack_space2 15 end 16 CREATE TABLE #system_stack_space2 ( 17 [id] int identity(1,1) not null, 18 [space_id] int NOT NULL, 19 [space_name] varchar(500) NOT NULL, 20 [parent_id] int NOT NULL, 21 [tstamp] datetime NOT NULL 22 )
首先把需要添加的新空间的第一级的名字插入到数据库中,这级比较简单,因为他是最高的一级,不涉及复杂的父子关系,别人跟着他的id走即可
1 declare @new_space_id int 2 select @new_space_id=max(space_id)+1 from system_stack_space 3 insert into system_stack_space values(@new_space_id,'New Space Name',0,0,getutcdate())
接着,把需要复制的老空间的第一级的id,根据name查出来
1 declare @copy_space_id int 2 select @copy_space_id=space_id from system_stack_space where parent_id=0 and space_name=@copy_space_name
把需要复制的老空间的第二级数据,根据其父级id(就是上面查出来的id),查出来并插入到临时表 #system_stack_space中,这级的数据也比较简单,因为其的父级id虽然是新添加的,但是在上上步的语句能够知道它的父级id,
1 insert into #system_stack_space select space_id,space_name,parent_id,getutcdate() from system_stack_space where parent_id=@copy_space_id
比较重要的是这一步的空间,因为它的上下级的id都变化了,且根据原有数据不同,id是动态的
这里把system_stack_space表,即原始数据中,所有父级id在#system_stack_space这个临时表中的子空间查出来,并且注意#system_stack_space中的id(即创建临时表中提到的自增长id),作为了这里的parentid,而不是原始数据中的parentid,最终插入到了#system_stack_space2中;其实对于新数据来说,它的父级id已经变化了,当然不用了
1 insert into #system_stack_space2 select a.space_id,a.space_name,b.id,getutcdate() from system_stack_space a inner join #system_stack_space b on a.parent_id=b.space_id
下面最后,也是最关键的两段
1 declare @current_space_id int 2 select @current_space_id=max(space_id) from system_stack_space 3 insert into system_stack_space select (@current_space_id+id),space_name,@new_space_id,tstamp from #system_stack_space 4 5 declare @current_space_id2 int 6 select @current_space_id2=max(space_id) from system_stack_space 7 insert into system_stack_space select @current_space_id2+id,space_name,(@current_space_id+parent_id),tstamp from #system_stack_space
这里首先,我们获取当前库中system_stack_space这个表真正的最大id取出来
然后从临时表#system_stack_space中查出数据,并把他的自增长id加上当前最大的id作为其最终的id,并把第三段sql中的new_space_id作为他的父级id,最后插入到数据库中
对于第二个临时表,我们同样获取当前库中system_stack_space这个表真正的最大id取出来(这时候的最大id已经和上一步不一样了,他应该是上一步的最大id 加上 临时表#system_stack_space中的最大id),所以我们还是要取当前最大id加上临时表#system_stack_space2的id,来作为这批数据的最终id,而这里的父级id,应该是第一次插入数据时的最大id加上临时表#system_stack_space2的父级id(这里就相当于是临时表#system_stack_space的id),那么等同于对于到其上一级的id,这样父子级关系也就清楚了。