日期:2014-05-16  浏览次数:20581 次

数据迁移总结笔记
背景:周一网站评审结束的时候,我提出了一个小问题,前台的地域问题没解决好,是因为获得的数据库的数据有问题,然后领导让我带着他看了源数据库,地域有的没有,有的也有些不规范,点播了一些关于数据统一和有效性的建议,我二话没说,想着重新进行一次数据库的设计和数据迁移。经过将近三天的辛苦奋战,终于重构了一次数据库还有成功的去掉了数据库中的一些无效的数据,重复的数据,还有修正了地域字段,写了大量的sql语句,想着温故而知新,所以有了这边总结性的笔记。按照过程的先后顺序,记录下一些要点,算是对自己的提高。
1. 建中转库和表。
这里没什么可说的,我觉得比较有用的一点就是判断数据中是否存在数据库或者表,
--判断数据库是否存在,不存在就创建(默认路径下)然后切换到创建的数据库来
If not exists (select * from master.dbo.sysdababases where name=’数据库名’)
Create database 数据库名
Use  数据库名
--判断表是否存在,存在就删除然后重新创建
--注意这里的uniqueidentifier类型,可产生32位的不重复的字符串,一般用来标识列,--插入的时候用newID()方法
If exists (select * from sysobjects where id=object_id(‘表名’) and type=’u’)
Drop table 表名
Create table Provincial(pid  uniqueidentifier , province  varchar(50), primary key (pid) )
2.迁移数据的存储过程
    这里先要介绍下源数据库的结构,源数据库从最终目的来看主要存放的两个表的数据,但是为了某些目的,实际分成了很多表,其中有一个表,记录了这个实际的表存放的表名,比如说存放了A表和B表,现在我这么存放,把A的数据分成若干表,每个表存放1W条数据,有20张,A1,A2…,A20, 把B的数据分成若干表,每个表存放2W条数据,有10张,B1,B2…,B20,还有另外一张表AB,存放的是存放数据的表名(tb_name)。实际上我的迁移过程是通过分析这张表的结构来之后精心设计的。主要用到游标。
--思路:1,首先从AB中找出所有的同构表名。
--2,使用游标取出一个表名,通过字符串拼接的方法,拼接成一个数据迁移的sql语句,--然后执行sql语句。
--3.游标循环,执行所有表的数据迁移。
Go
Create procedure transferdata
As
Declare  mycursor cursor for
Select tb_name from AB where tb_name like ‘%A%’
Open  mycusor
Declare @tableStr varchar(100)
Delare @sourceDB varchar(100)
Set @sourceDB=’源数据库名.dbo.’
Delare @targetDB varchar(100)
Set @targetDB =’目标数据库名.dbo.A’
Declare @sql varchar(1000)
Fetch next from mycursor into @tableStr
While(@@fetch_status=0)
Begin
Set @sql=N’insert into ’+@targetDB+’ (id,name,sex,address)  select  newID(),tname,tsex,taddress from ’+@sourceDB+@tableStr
--执行文本的sql语句
Exec  sp_executesql  @sql
Fetch next from mycursor into @tableStr
End
Close mycursor
Deallocate  mycursor
Exec  transferdata
3.去掉无效的,重复的,修正地域字段的过程。
--去掉无效的数据(长度小于三的和含有数字或者字母的)
Delete from A where len(Ltrim(Rtrim(city)))<=3 or patindex(‘[A-Z,a-z,0-9]’,city)>0
--去掉重复的数据,只保留一条ID最小的,根据一个字段name来判断
Delete from A where  name in (select name from A group by name having count(name)>1) and id not in (select min(convert(varchar(50),id)) from A group by name having count(name)>1))
--去掉重复的数据,只保留id最大的一条,根据多个字段来判断。
Delete  A from A a
Where exists(select * from  A where name=a.name and address=a.address and id>a.id)
--修正地域字段,假设地域字段都有值,不过不规范,现在要做的事情就是把它们修正为规--范的省份或者城市,至于找不到的就修正为中国。
If exists (select * from dbo.sysobjects where id=object_id(‘modifyRegion’) and objectproperty(id,N’modifyRegion’)=1)
Drop  procedure modifyRegion
Go
Create procedure modifyRegion
As
Declare regioncursor cursor for
Select distinct city from A
Open regioncursor
Declare  @regionItem nvarchar(50)
Fetch next from regioncursor into @regionItem
While(@@fetch_status=0)
Begin
--先判断省份是为了处理省市同名的取大的一定对。
If exists(select provincial from Provincial where provincial like ‘%’+@regionItem+’%’ )
Update A set city=( select  min(provincial) from Provincial where provincial like ‘%’+@regionItem+’%’) where city=@regionItem

Else if exists (select city from City where city like ‘%’+@regionItem+’%’ )
Update A set city=( select  min(city) from City where city like ‘%’+@regionItem+’%’) where city=@regionItem

Else
Update A set city=’中国’ where city=@regionItem
Fetch next from regioncursor into @regionItem
end
close regioncursor
deallocate regioncursor
go
exec  modifyRegion
4.分享一个中国城市和省份的有用资料。
这是我无意中找到的,常用的资料,大家可以看看。
--省级   Provincial
--城市   City
create table Provincial(pid int,Provincial varchar(50),primary key (pid))
insert into Provincial values(1,'北京市')
insert into Provincial v