将表移动到另一个SQL2008数据库(包括索引,触发器等)


16

我需要将一大堆(100多个)大型(数百万行)表从一个SQL2008数据库移动到另一个数据库。

我最初只是使用导入/导出向导,但是所有目标表都缺少主键和外键,索引,约束,触发器等。(标识列也被转换为普通INT,但是我想我只是错过了向导。)

什么是正确的方法?

如果这只是几个表,我将回到源头,编写表定义的脚本(包括所有索引,等等),然后在目标上运行脚本的索引创建部分。但是,有这么多表,这似乎是不切实际的。

如果没有太多数据,我可以使用“创建脚本...”向导来编写包括数据在内的源脚本,但是72m行脚本似乎不是一个好主意!


这不是数据库中的所有表吗?
thursdaysgeek

@thursdaysgeek:它几乎是所有表,但是目标数据库已经有100多个表。因此,仅可以使用其他名称从备份中还原是不可行的。认为这基本上是“将这两个大型数据库合并在一起”。
BradC 2011年

Answers:


14

编写表格脚本,然后使用SSIS传输数据将是将数据移至新数据库的最可靠,最有效的方法。


9

实际上,我们结合使用了许多手动脚本和导入向导来完成此操作,但是今天早晨,我发现更好的答案是Tibor Karaszi的博客文章

令我们沮丧的部分原因是,通过选择“复制对象和数据” ,SQL 2000 “ DTS导入/导出向导”实际上使此操作变得非常简单:

DTS导入向导

第三个选项是包含索引/触发等功能的选项:

高级选项

SQL 2005/2008导入向导中删除了此选项。为什么?不知道:

2008导入向导

在2005/2008中,您显然必须在BIDS中手动创建一个SSIS包,并使用Transfer SQL Server Objects Task,其中包含与2000向导相同的所有选项:

SSIS传输SQL Server对象任务


只是想发布我使用此SSIS方法完成另一项类似的任务,并且效果很好!
BradC 2011年

8

我会考虑用脚本编写表格,或者使用比较工具(例如Red Gate)在目标数据库中生成表格。还没有索引或约束。

然后,我考虑在同一台服务器上使用其他名称还原数据库,然后执行

 INSERT newdb.dbo.newtable SELECT * FROM olddb.dbo.oldtable

..对于每个表,如果需要,将SET IDENTITY INSERT ON设置为ON

然后在加载数据后添加索引和约束。

这取决于您对SSIS的满意程度(对mrdenny的回答)或您是否喜欢原始SQL。


6

我会在Denny先生的答案中添加一个内容:编写表模式的脚本,然后使用BCP移动数据。如果您不熟悉SSIS,那么使用BCP和批处理应该很容易。对于数百万行,没有什么比BCP(批量插入):)好了。


4

我是对SSIS完全不满意的人。

当源表没有标识列时

  1. 在目标服务器上创建一个空数据库
  2. 在目标服务器上创建到源服务器的链接服务器
  3. 在源数据库上运行以下脚本以生成select * into ...语句
  4. 从目标数据库运行生成的脚本
  5. 源数据库中的脚本主键,索引,触发器,函数和过程
  6. 通过生成的脚本创建这些对象

现在,T-SQL生成Select * into ...语句

SET NOCOUNT ON

declare @name sysname
declare @sql varchar(255)

declare db_cursor cursor for
select name from sys.tables order by 1
open db_cursor

fetch next from db_cursor into @name
while @@FETCH_STATUS = 0
begin
    Set @sql = 'select * into [' + @name + '] from [linked_server].[source_db].[dbo].[' + @name + '];'
    print @sql

    fetch next from db_cursor into @name
end

close db_cursor
deallocate db_cursor

这为每个表生成一行以进行复制,例如

select * into [Table1] from [linked_server].[source_db].[dbo].[Table1];

如果表包含标识列,我将编写脚本,包括标识属性和主键。

在这种情况下,我不使用链接服务器插入...选择...,因为这不是批量技术。我正在处理一些类似于[此问题1的 PowerShell脚本,但是我仍在进行错误处理。真正的大表可能会导致内存不足错误,因为整个表在通过SQLBulkCopy发送到数据库之前已加载到内存中。

索引等的增加与上述情况类似。这次,我可以跳过重新创建主键的操作。


如果表包含标识列,则可以在此问题中进行操作。它将节省您一些体力劳动。我仍然更喜欢批量插入批处理/ SSIS,在广泛的网络上,链接服务器可能不是一个好的解决方案。
玛丽安

1
@Marian 如果要推广SSIS,请查看dba.stackexchange.com/questions/297/…。我没有尝试SSIS,但是“导入导出向导”也失败了(链接服务器除外)。
bernd_k 2011年

我会很乐意帮助的,但是我没有可用的Oracle盒子。无论如何,从我设法阅读的内容来看,没有任何提供程序将支持Oracle CLOB。–
Marian

我同意您的意见-有时会迁移数据,但从不使用SSIS。
AK

2

您可以使用比较工具比较数据库架构和数据,并首先将空白数据库架构与原始db 同步,以创建所有表。

然后,将原始数据库中的数据与新数据库同步(所有表都在其中,但是它们都为空)以将记录插入表中

我为此使用ApexSQL DiffApexSQL Data Diff,但是还有其他类似的工具。

此过程的好处是,您不必使用该工具实际同步数据库,因为这对于数百万行可能会非常痛苦。

您可以只创建一个INSERT INTO SQL脚本(如果是几次演出就不要惊讶)并执行它。

由于无法在SQL Server Management Studio中打开如此大的脚本,因此我使用sqlcmdosql


1

正如@mrdenny提到的-

  1. 首先使用所有索引,FK等对表进行脚本编写,然后在目标数据库中创建空白表。

代替使用SSIS,使用BCP插入数据

  1. 使用以下脚本bcp输出数据。在文本模式下设置SSMS,并将以下脚本生成的输出复制到bat文件中。

    -- save below output in a bat file by executing below in SSMS in TEXT mode
    
    -- clean up: create a bat file with this command --> del D:\BCP\*.dat 
    
    select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" ' /* path to BCP.exe */
        +  QUOTENAME(DB_NAME())+ '.' /* Current Database */
        +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
        +  QUOTENAME(name)  
        +  ' out D:\BCP\'  /* Path where BCP out files will be stored */
        +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
        +  REPLACE(name,' ','') 
        + '.dat -T -E -SServerName\Instance -n' /* ServerName, -E will take care of Identity, -n is for Native Format */
    from sys.tables
    where is_ms_shipped = 0 and name <> 'sysdiagrams'                       /* sysdiagrams is classified my MS as UserTable and we dont want it */
    /*and schema_name(schema_id) <> 'unwantedschema'    */                             /* Optional to exclude any schema  */
    order by schema_name(schema_id)
  2. 运行bat文件,该文件将在您指定的文件夹中生成.dat文件。

  3. 在以下脚本上运行

    --- Execute this on the destination server.database from SSMS.
    
    --- Make sure the change the @Destdbname and the bcp out path as per your environment.
    
    declare @Destdbname sysname
    set @Destdbname = 'destinationDB' /* Destination Database Name where you want to Bulk Insert in */
    select 'BULK INSERT ' 
    /*Remember Tables must be present on destination database */ 
    + QUOTENAME(@Destdbname) + '.' 
    + QUOTENAME(SCHEMA_NAME(SCHEMA_ID)) 
    + '.' + QUOTENAME(name) 
    + ' from ''D:\BCP\' /* Change here for bcp out path */ 
    + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') 
    + '.dat'' with ( KEEPIDENTITY, DATAFILETYPE = ''native'', TABLOCK )' 
    + char(10) 
    + 'print ''Bulk insert for ' + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') + ' is done... ''' 
    + char(10) + 'go'
       from sys.tables
       where is_ms_shipped = 0
    and name <> 'sysdiagrams' /* sysdiagrams is classified my MS as UserTable and we dont want it */
    and schema_name(schema_id) <> 'unwantedschema' /* Optional to exclude any schema */
        order by schema_name(schema_id) 
  4. 使用SSMS运行输出以将数据重新插入表中。

这是非常快速的bcp方法,因为它使用纯模式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.