(1)将现有的数据库脱机ALTERDATABASEDB1SETOFFLINEWITHROLLBACKIMMEDIATE;(2)将数据库文件移到新的位置文件复制完成以后需要:右键-属性-安全-在组或用户名处添加AuthenticatedUsers-更改该组权限为完全权限,否则接下来的操作会报中间可能存在的问题:消息5120,级别16,状态101,第17行无法打开物理文件“D:\MSSQL\DATA\testdb.mdf”。操作系统错误5:“5(拒绝访问。)”。消息5120,级别16,状态101,第17行无法打开物理文件“D:\MSSQL\DATA\testdb_log.ldf”。操作系统错误5:“5(拒绝访问。)”。消息5181,级别16,状态5,第17行无法重新启动数据库“ctrip”。将恢复到以前的状态。消息5069,级别16,状态1,第17行ALTERDATABASE语句失败。(3)修改数据库关联文件的指向ALTERDATABASEDB1MODIFYFILE(NAME=DB1,FILENAME=X:\SQLServer\DB1.mdf);ALTERDATABASEDB1MODIFYFILE(NAME=DB1_Log,FILENAME=X:\SQLServer\DB1_Log.ldf);(4)将数据库进行联机ALTERDATABASEDB1SETONLINE;
在线修改文件位置,但也需要服务重启才能生效,或者offline=>online
(1)分离
EXECsp_detach_db'test'
(2)复制文件到自己想要的位置
(3)附加
EXECsp_attach_db@dbname=test',@filename1=@data_file,@filename2=@log_file
EXECsp_attach_db@dbname=test',@filename1='d:\test\test_data.mdf',@filename2='d:\test\test_log.mdf'
restoremove,withmove恢复数据库
USE[master]RESTOREDATABASE[test]FROMDISK=N'D:\DBBackup\testfull.bak'WITHFILE=1,MOVEN'test'TON'D:\MSSQL\test.mdf',MOVEN'test_log'TON'D:\MSSQL\test_log.ldf',NOUNLOAD,NORECOVERY,STATS=5
正文:
sqlserver迁移数据(文件组之间的互相迁移与文件组内文件的互相迁移)
每个物理文件(数据文件)对应一个文件组的情况(一对一)
如果我把数据移到另一个文件组了,不想要这个已经清空的文件组了,怎麽做?
删除原有聚集索引,创建新的聚集索引到迁移的文件组
当你移动数据到文件组[FG_Test_Id_02]上时,这时候文件组[FG_Test_Id_01]里面已经没有数据了使用下面的脚本查看
使用下面的SQL语句移除文件组[FG_Test_Id_01]就可以了
--9.移除FG_Test_Id_01文件组ALTERDATABASETESTREMOVEFILEFG_TestUnique_Id_01_data
注意:如果不使用聚集索引来移动文件组[FG_Test_Id_01]上的数据到文件组[FG_Test_Id_02]
--4.创建表,这个表的数据存放在[FG_Test_Id_01]文件组上CREATETABLEaa(idINT,cnameNVARCHAR(4000))ON[FG_Test_Id_01]GO
直接使用下面SQL语句来收缩文件会报错
--收缩一下FG_Test_Id_01文件组文件DBCCSHRINKFILE(FG_TestUnique_Id_01_data,EMPTYFILE)
报错内容
DBCCSHRINKFILE:无法移动堆页3:515。消息2555,级别16,状态1,第1行无法将文件"FG_TestUnique_Id_01_data"的所有内容移到其他位置,以完成清空文件操作。语句已终止。DBCC执行完毕。如果DBCC输出了错误信息,请与系统管理员联系。消息1105,级别17,状态2,第1行无法为数据库'Test'中的对象'dbo.aa'分配空间,因为'FG_Test_Id_01'文件组已满。请删除不需要的文件、删除文件组中的对象、将其他文件添加到文件组或为文件组中的现有文件启用自动增长,以便增加可用磁盘空间。
因为文件组[FG_Test_Id_01]里还有数据,不能清空
两个物理文件(数据文件)对应一个文件组的情况(一对多)
上面的情况是每个物理文件(数据文件)对应一个文件组的情况
下面这种情况是两个物理文件(数据文件)对于一个文件组的情况
一对一的情况使用聚集索引里移动数据,而一对多的情况使用DBCCSHRINKFILE
创建数据库
test1和test2这两个数据文件归属于主文件组primary,而数据文件test1最大大小为6MB初始大小为5MB
test2数据文件最大大小没有限制
使用下面脚本添加数据到主文件组
--1.创建表,这个表的数据存放在主文件组上CREATETABLEaa(idINT,cnameNVARCHAR(4000))GO--2.插入数据INSERTINTO[dbo].[aa]SELECT1,REPLICATE('s',3000)GO600--3.查询数据SELECT*FROM[dbo].[aa]--4.我们查看一下文件组的逻辑文件名EXEC[sys].[sp_helpdb]@dbname=TEST1--sysnameSELECTDB_NAME(database_id)ASDatabaseName,NameASLogical_Name,Physical_Name,(size*8)/1024SizeMBFROMsys.master_filesWHEREDB_NAME(database_id)='Test1'
因为第一个数据文件的最大大小限制,所以有一部分数据插入到了test2.ndf
现在修改test1数据文件的最大大小限制为20MB
执行下面的SQL语句
--5.收缩文件DBCCSHRINKFILE(test2,EMPTYFILE)--6.移除test2数据文件test2.ndfALTERDATABASETEST1REMOVEFILEtest2
在执行第五条语句的时候,执行下面脚本
数据都移动到了test1.mdf里去了
执行第六条SQL语句,删除test2.ndf文件
数据没有丢失
这里关键在于EMPTYFILE参数:DBCCSHRINKFILE(test2,EMPTYFILE)
总结
这里要根据是一对多还是一对一来选择移动数据的方法
如果是一对多:使用DBCCSHRINKFILE(要移动数据的数据文件,EMPTYFILE)
如果是一对一:创建聚集索引
大家可以做一下实验
对于同一个文件组里的多个数据文件(不一定是主文件组),
比如有有个文件组叫[FG_Test_01],里面有两个数据文件test3.ndf和test4.ndf
test3.ndf和test4.ndf都有数据
如果我运行DBCCSHRINKFILE(test4,EMPTYFILE),test4.ndf里的数据是否会移动到test3.ndf还是会移动到test1.mdf???
这个实验留给大家o(∩_∩)o
2014-1-14补充:
这个实验的测试脚本和结果
答案:
FG_TestUnique_Id_02_data.ndf里的数据会移动到FG_TestUnique_Id_01_data.ndf,不会移动到Test.mdf
因为DBCCSHRINKFILE只能在同一文件组内移动数据,而mdf只能属于主文件组primary
直接使用【1】中的迁移办法即可;
如果我们的ldf在一个不太好的磁盘里,而业务又正在允许不停机,那么用这个办法还是不错的。
(1)新增一个日志文件到其他的盘符
--(1.1)创建日志文件ALTERDATABASE[test]ADDLOGFILE(NAME='test_log1',FILENAME='D:\programfiles\sqlserver2017\sqlserverworkspace\E_Market_log1.ldf',SIZE=5MB,FILEGROWTH=0)--(1.2)把原来的日志文件停用,通过禁止自动增长的方式,代码如下,也可以用SSMS操作USE[test]GODBCCSHRINKFILE(N'test_Log',64)--这里的值是其当前ldf大小,也可以不用收缩GOUSE[master]GOALTERDATABASE[Db_Logs]MODIFYFILE(NAME=N'Db_Logs_Log',MAXSIZE=UNLIMITED,FILEGROWTH=0)--这才是核心GO--注意,只能把原日志停用,但不能删除!做完这个之后也不能随意收缩了
参考代码:在建库的时候创建多个数据与日志文件
GOCREATEDATABASEE_MarketONPRIMARY--主文件组(NAME='E_Market_data',FILENAME='D:\programfiles\sqlserver2017\sqlserverworkspace\E_Market_data.mdf',SIZE=10MB,MAXSIZE=500MB,FILEGROWTH=10%),--第一个文件组结束FILEGROUPFG--第二个文件组(NAME='FG_E_Market_data',FILENAME='D:\programfiles\sqlserver2017\sqlserverworkspace\FG_E_Market_data.ndf',SIZE=10MB,FILEGROWTH=0)--日志文件不属于任何文件组LOGON(NAME='E_Market_log',FILENAME='D:\programfiles\sqlserver2017\sqlserverworkspace\E_Market_log.ldf',SIZE=5MB,FILEGROWTH=0),--日志2的具体描述(NAME='E_Market_log1',FILENAME='D:\programfiles\sqlserver2017\sqlserverworkspace\E_Market_log1.ldf',SIZE=5MB,FILEGROWTH=0)GO