Movendo tabelas para outro banco de dados SQL2008 (incluindo índices, gatilhos, etc.)

16

Eu preciso mover um monte (100+) de tabelas grandes (milhões de linhas) de um banco de dados SQL2008 para outro.

Originalmente, usei apenas o Assistente de Importação / Exportação, mas todas as tabelas de destino estavam ausentes, chaves primárias e estrangeiras, índices, restrições, gatilhos etc. (As colunas de identidade também foram convertidas em INTs simples, mas acho que perdi uma caixa de seleção na Mago.)

Qual é o caminho certo para fazer isso?

Se fossem apenas algumas tabelas, eu retornaria à fonte, criaria um script para a definição da tabela (com todos os índices, etc.) e depois executaria as partes de criação de índice do script no destino. Mas com tantas tabelas, isso parece impraticável.

Se não houvesse tantos dados, eu poderia usar o assistente "Criar scripts ..." para criar um script da fonte, incluindo dados, mas um script de linha de 72m simplesmente não parece uma boa idéia!

BradC
fonte
E não são todas as tabelas no banco de dados?
thursdaysgeek
@thursdaysgeek: São quase todas as tabelas, mas o banco de dados de destino já possui mais de 100 tabelas. Portanto, apenas restaurar do backup com um nome diferente não é uma opção. Pense nisso como basicamente "mesclar esses dois grandes bancos de dados".
BradC

Respostas:

14

Criar um script das tabelas e usar o SSIS para transferir os dados seria a maneira mais confiável e eficaz de mover os dados para o novo banco de dados.

Mrdenny
fonte
9

Na verdade, fizemos isso usando muitos scripts manuais em conjunto com o assistente de Importação, mas nesta manhã encontrei uma resposta melhor, cortesia do artigo do blog de Tibor Karaszi .

Parte de nossa frustração aqui foi que o "Assistente de Importação / Exportação DTS" do SQL 2000 torna isso quase trivialmente fácil, selecionando "Copiar objetos e dados":

Assistente de Importação de DTS

Essa terceira opção é a que contém a capacidade de incluir índices / gatilhos, etc:

Opções avançadas

Esta opção foi REMOVIDA no Assistente de Importação do SQL 2005/2008 . Por quê? Nenhuma idéia:

Assistente de Importação 2008

Em 2005/2008, você aparentemente precisa criar manualmente um pacote SSIS no BIDS e usar a tarefa Transferir objetos do SQL Server , que contém todas as mesmas opções do assistente de 2000:

Tarefa de transferência de objetos do SQL Server do SSIS

BradC
fonte
Só queria postar que eu usei esse método SSIS para outra tarefa semelhante e funcionou muito bem!
BradC 7/02
8

Eu consideraria criar um script para a tabela ou usar ferramentas de comparação (por exemplo, Red Gate) para gerar as tabelas no banco de dados de destino. Sem índices ou restrições ainda.

Então, eu consideraria restaurar o banco de dados com um nome diferente no mesmo servidor e fazer

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

.. para cada tabela, com SET IDENTITY INSERT ON se necessário

Então eu adicionaria índices e restrições após carregar os dados.

Depende do seu nível de conforto com o SSIS (resposta de Mrdenny) ou se você prefere SQL bruto.

gbn
fonte
6

Eu acrescentaria à resposta do Sr. Denny: escreva o esquema das tabelas e use o BCP para mover os dados. Se você não estiver familiarizado com o SSIS, será fácil usar o BCP e os lotes. Para milhões de linhas, nada supera o BCP (inserção em massa) :).

Marian
fonte
4

Sou eu quem está completamente desconfortável com o SSIS.

Quando as tabelas de origem não possuem colunas de identidade

  1. crie um banco de dados vazio no servidor de destino
  2. crie um servidor vinculado ao servidor de origem no servidor de destino
  3. execute o script abaixo no banco de dados de origem para gerar as instruções select * into ...
  4. execute o script gerado a partir do banco de dados de destino
  5. chaves primárias de script, índices, gatilhos, funções e procedimentos do banco de dados de origem
  6. crie esses objetos pelo script gerado

Agora o T-SQL para gerar as instruções Select * em ...

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

Isso gera uma linha para cada tabela copiar como

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

Caso as tabelas contenham colunas de identidade, escrevo as tabelas, incluindo a propriedade de identidade e as chaves primárias.

Eu não uso a inserção em ... selecione ... usando um servidor vinculado nesse caso, pois essa não é uma técnica em massa. Estou trabalhando em alguns scripts do PowerShell semelhantes a [esta questão SO 1 , mas ainda estou trabalhando no tratamento de erros. Tabelas realmente grandes podem causar erros de falta de memória, pois uma tabela inteira é carregada na memória antes de ser enviada via SQLBulkCopy para o banco de dados.

A recriação de índices etc. é semelhante ao caso acima. Desta vez, posso pular a recriação das chaves primárias.

bernd_k
fonte
Caso as tabelas contenham colunas de identidade, você pode fazer o mesmo nesta pergunta . Isso poupará algum trabalho manual. Ainda prefiro lotes de inserção em massa / SSIS, o servidor vinculado pode não ser uma boa solução em uma ampla rede.
Marian
1
@ Marian Dê uma olhada em dba.stackexchange.com/questions/297/… se você deseja promover o SSIS. Não tentei o SSIS, mas o Assistente para Importação e Exportação também falhou (além do servidor vinculado).
22411 bernd_k
Eu teria ajudado com prazer, mas não tenho nenhuma caixa do Oracle disponível para mim. De qualquer forma, pelo que eu consegui ler, não há fornecedores que irão apoiar a Oracle CLOB ..
Marian
Estou com você nisso - às vezes migro dados, mas nunca uso o SSIS.
AK
2

Você pode usar ferramentas de comparação que comparam dados e esquemas de banco de dados e primeiro sincronize um esquema de banco de dados em branco com o banco de dados original, para criar todas as tabelas.

Em seguida, sincronize os dados do banco de dados original com o novo (todas as tabelas estão lá, mas estão todas vazias) para inserir os registros nas tabelas

Eu uso o ApexSQL Diff e o ApexSQL Data Diff para isso, mas existem outras ferramentas semelhantes.

A coisa boa desse processo é que você não precisa sincronizar os bancos de dados usando a ferramenta, pois isso pode ser bastante doloroso para milhões de linhas.

Você pode simplesmente criar um script INSERT INTO SQL (não se surpreenda se houver vários shows) e executá-lo.

Como scripts grandes não podem ser abertos no SQL Server Management Studio, eu uso sqlcmd ou osql

Carol Baker West
fonte
1

Como @mrdenny mencionou -

  1. escreva as tabelas primeiro com todos os índices, FKs, etc. e crie tabelas em branco no banco de dados de destino.

Em vez de usar o SSIS, use o BCP para inserir dados

  1. bcp os dados usando o script abaixo. defina o SSMS no modo de texto e copie a saída gerada pelo script abaixo em um arquivo 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. Execute o arquivo bat que irá gerar os arquivos .dat na pasta que você especificou.

  3. Execute o script abaixo no

    --- 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. Execute a saída usando o SSMS para inserir dados novamente nas tabelas.

Este é um método bcp muito rápido, pois usa o modo nativo.

Kin Shah
fonte