Mover tablas a otra base de datos SQL2008 (incluidos índices, desencadenantes, etc.)

16

Necesito mover un montón (100+) de tablas grandes (millones de filas) de una base de datos SQL2008 a otra.

Originalmente solo utilicé el Asistente de importación / exportación, pero a todas las tablas de destino les faltaban claves primarias y externas, índices, restricciones, desencadenantes, etc. (Las columnas de identidad también se convirtieron en INT simples, pero creo que acabo de omitir una casilla en la casilla mago.)

¿Cuál es la forma correcta de hacer esto?

Si esto fuera solo un par de tablas, volvería a la fuente, escribiría la definición de la tabla (con todos los índices, etc.) y luego ejecutaría las porciones de creación de índice de la secuencia de comandos en el destino. Pero con tantas tablas, esto parece poco práctico.

Si no hubiera tanta información, podría usar el asistente "Crear secuencias de comandos ..." para escribir la fuente, incluidos los datos, ¡pero una secuencia de comandos de 72m no parece una buena idea!

BradC
fuente
¿Y no son todas las tablas de la base de datos?
jueves
@thursdaysgeek: son casi todas las tablas, pero la base de datos de destino ya tiene más de 100 tablas. Por lo tanto, solo restaurar desde una copia de seguridad con un nombre diferente no es una opción. Piense en esto básicamente como "fusionar estas dos grandes bases de datos".
BradC

Respuestas:

14

Crear una secuencia de comandos de las tablas y luego usar SSIS para transferir los datos sería la forma más confiable y efectiva de mover los datos a la nueva base de datos.

mrdenny
fuente
9

De hecho, lo hicimos utilizando muchas secuencias de comandos manuales junto con el asistente de importación, pero esta mañana encontré una mejor respuesta, cortesía del artículo del blog de Tibor Karaszi .

Parte de nuestra frustración aquí fue que el "Asistente de importación / exportación DTS" de SQL 2000 en realidad lo hace casi trivialmente fácil seleccionando "Copiar objetos y datos":

Asistente de importación DTS

Esta tercera opción es la que contiene la capacidad de incluir índices / disparadores, etc.

Opciones avanzadas

Esta opción se eliminó del Asistente de importación SQL 2005/2008 . ¿Por qué? Ni idea:

Asistente de importación 2008

En 2005/2008, aparentemente tiene que crear manualmente un paquete SSIS en BIDS y usar la tarea Transferir objetos de SQL Server , que contiene las mismas opciones que estaban en el asistente 2000:

Tarea SSIS Transferir objetos de SQL Server

BradC
fuente
Solo quería publicar que usé este método SSIS para otra tarea similar, ¡y funcionó muy bien!
BradC
8

Consideraría crear una secuencia de comandos para la tabla, o usar una herramienta de comparación (por ejemplo, Red Gate) para generar las tablas en la base de datos de destino. Sin índices o restricciones todavía.

Luego consideraría restaurar la base de datos con un nombre diferente en el mismo servidor y hacer

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

.. para cada tabla, con SET IDENTITY INSERT ON si se requiere

Luego agregaría índices y restricciones después de cargar los datos.

Depende de su nivel de comodidad con SSIS (respuesta de mrdenny) o si prefiere SQL sin formato.

gbn
fuente
6

Agregaría a la respuesta del Sr. Denny: escriba el esquema de las tablas y luego use BCP para mover los datos. Si no está familiarizado con SSIS, usar BCP y lotes debería ser fácil de hacer. Para millones de filas, nada supera a BCP (inserción masiva) :).

Mariana
fuente
4

Soy quien está completamente incómodo con SSIS.

Cuando las tablas de origen no tienen columnas de identidad

  1. crear una base de datos vacía en el servidor de destino
  2. crear un servidor vinculado al servidor de origen en el servidor de destino
  3. ejecute el script a continuación en la base de datos de origen para generar sentencias select * into ...
  4. ejecutar el script generado desde la base de datos de destino
  5. escritura de claves primarias, índices, disparadores, funciones y procedimientos de la base de datos fuente
  6. crear estos objetos por el script generado

Ahora el T-SQL para generar el Select * en ... declaraciones

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

Esto genera una línea para cada tabla para copiar como

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

En caso de que las tablas contengan columnas de identidad, escribo las tablas incluyendo la propiedad de identidad y las claves primarias.

No uso insertar en ... seleccionar ... usando un servidor vinculado en este caso, ya que esta no es una técnica masiva. Estoy trabajando en algunos scripts de PowerShell similares a [esta pregunta SO 1 , pero todavía estoy trabajando en el manejo de errores. Las tablas realmente grandes pueden causar errores de falta de memoria, ya que una tabla completa se carga en la memoria, antes de enviarse a través de SQLBulkCopy a la base de datos.

La recreación de índices, etc., es similar al caso anterior. Esta vez puedo omitir la recreación de las claves primarias.

bernd_k
fuente
En caso de que las tablas contengan columnas de identidad, puede hacer lo mismo en esta pregunta . Le ahorrará algo de trabajo manual. Todavía prefiero lotes de inserción masiva / SSIS, el servidor vinculado puede no ser una buena solución en una red amplia.
Marian
1
@Marian Por favor, eche un vistazo a dba.stackexchange.com/questions/297/… si desea promocionar SSIS. No probé SSIS, pero el Asistente de importación y exportación también falló (además del servidor vinculado).
bernd_k
Hubiera ayudado con placer, pero no tengo ninguna caja de Oracle disponible para mí. De todos modos, por lo que he logrado leer, no hay proveedores que admitan Oracle CLOB ..
Marian
Estoy con usted en esto: a veces migro datos, pero nunca uso SSIS.
AK
2

Puede usar herramientas de comparación que comparen esquemas y datos de bases de datos y primero sincronizar un esquema de base de datos en blanco con el db original, para crear todas las tablas.

Luego, sincronice los datos de la base de datos original con la nueva (todas las tablas están allí, pero todas están vacías) para insertar los registros en las tablas

Utilizo ApexSQL Diff y ApexSQL Data Diff para esto, pero hay otras herramientas similares.

Lo bueno de este proceso es que no tiene que sincronizar las bases de datos con la herramienta, ya que esto puede ser bastante doloroso para millones de filas.

Simplemente puede crear un script INSERT INTO SQL (no se sorprenda si son varios conciertos) y ejecutarlo.

Como tantas grandes guiones ni siquiera pueden ser abiertos en SQL Server Management Studio, utilizo sqlcmd o osql

Carol Baker West
fuente
1

Como @mrdenny mencionó:

  1. primero escriba las tablas con todos los índices, FK, etc. y cree tablas en blanco en la base de datos de destino.

En lugar de usar SSIS, use BCP para insertar datos

  1. bcp fuera de los datos utilizando el siguiente script. configure SSMS en modo de texto y copie la salida generada por el siguiente script en un archivo 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. Ejecute el archivo bat que generará los archivos .dat en la carpeta que ha especificado.

  3. Ejecutar debajo del script en el

    --- 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. Ejecute la salida utilizando SSMS para insertar datos nuevamente en las tablas.

Este es un método bcp muy rápido, ya que utiliza el modo nativo.

Kin Shah
fuente