2012-05-17 8 views
6

Probablemente este sea un escenario limitado pero valioso. Tengo una base de datos de SQL Server 2008 con una tabla que tiene millones de registros. Parece que hay un problema intermitente con varios de los registros. Estoy tratando de reproducir el problema. En un esfuerzo por hacer esto, finalmente obtuve el ID de un registro ofensivo. Me gustaría generar una declaración INSERT asociada con este único registro en mi base de datos PROD. Luego, puedo migrarlo fácilmente a mi base de datos de PRUEBAS en un esfuerzo por reproducir y resolver el problema.Generación de scripts para registros específicos en SQL Server

Básicamente, necesito generar una sola instrucción INSERT para un solo registro de una sola tabla donde conozco el valor de clave principal del registro.

¿Alguien tiene alguna idea de cómo puedo lograr esto? Esencialmente, quiero generar declaraciones de inserción en una base condicional.

¡Gracias!

+1

table schema? condiciones? hay personas bastante inteligentes aquí, pero ninguno de ellos son profetas: P –

+0

Acabo de actualizar la pregunta. Gracias. – user70192

Respuesta

4

Primero intente recrear lo que desea insertar con una instrucción SELECT.

Después de que se puede insertar en la tabla con un INSERT INTO así:

INSERT INTO tablename 
SELECT .... 

Si están en diferentes servidores, puede utilizar INSERT de este modo:

INSERT INTO tablename VALUES (...) 

usando los valores dados por SELECT en el otro servidor llenan los valores en el inserto.

+0

Si se encuentran en servidores diferentes, esto requerirá un servidor vinculado.Me gusta más esta idea, pero creo que OP está intentando generar una cadena estática con valores para copiar, pegar y ejecutar en otro lugar. –

+0

@AaronBertrand cierto eso! He editado para agregar esa información. –

+0

¡Excelente señor! una respuesta muy valiosa –

5

En su caso concreto creo que se puede hacer esto:

CREATE PROCEDURE dbo.GenerateSingleInsert 
    @table  NVARCHAR(511), -- expects schema.table notation 
    @pk_column SYSNAME,  -- column that is primary key 
    @pk_value INT   -- change data type accordingly 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @cols NVARCHAR(MAX), @vals NVARCHAR(MAX), 
      @valOut NVARCHAR(MAX), @valSQL NVARCHAR(MAX); 

    SELECT @cols = N'', @vals = N''; 

    SELECT @cols = @cols + ',' + QUOTENAME(name), 
      @vals = @vals + ' + ' + REPLICATE(CHAR(39),3) + ',' 
      + REPLICATE(CHAR(39),3) + ' + ' + REPLICATE(CHAR(39),2) + '+' 
      + 'RTRIM(' + CASE WHEN system_type_id IN (40,41,42,43,58,61) THEN 
      'CONVERT(CHAR(8), ' + QUOTENAME(name) + ', 112) + '' '' 
      + CONVERT(CHAR(14), ' + QUOTENAME(name) + ', 14)' 
      ELSE 'REPLACE(' + QUOTENAME(name) + ','''''''','''''''''''')' END + ') 
      + ' + REPLICATE(CHAR(39),2) 
     FROM sys.columns WHERE [object_id] = OBJECT_ID(@table) 
     AND system_type_id <> 189 -- can't insert rowversion 
     AND is_computed = 0;  -- can't insert computed columns 

    SELECT @cols = STUFF(@cols, 1, 1, ''), 
      @vals = REPLICATE(CHAR(39), 4) + ' + ' + STUFF(@vals, 1, 13, '') 
      + REPLICATE(CHAR(39), 2); 

    SELECT @valSQL = N'SELECT @valOut = ' + @vals + ' FROM ' + @table + ' WHERE ' 
     + QUOTENAME(@pk_column) + ' = ''' + RTRIM(@pk_value) + ''';'; 

    EXEC sp_executesql @valSQL, N'@valOut NVARCHAR(MAX) OUTPUT', @valOut OUTPUT; 

    SELECT SQL = 'INSERT ' + @table + '(' + @cols + ') SELECT ' + @valOut; 
END 
GO 

Así que vamos a probarlo:

CREATE TABLE dbo.splunge 
(
    ID INT, dt DATETIME, rv ROWVERSION, t NVARCHAR(MAX) 
); 

INSERT dbo.splunge(ID, dt, t) 
      SELECT 1, GETDATE(), 'foo' 
    UNION ALL SELECT 2, GETDATE(), 'bar' 
    UNION ALL SELECT 3, GETDATE(), 'O''Brien'; 

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 1; 

SQL 
------------- 
INSERT dbo.splunge([ID],[dt],[t]) SELECT '1','20120517 10:07:07:330','foo' 

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 2; 

SQL 
------------- 
INSERT dbo.splunge([ID],[dt],[t]) SELECT '2','20120517 10:07:07:330','bar' 

EXEC dbo.GenerateSingleInsert N'dbo.splunge', N'ID', 3; 

SQL 
------------- 
INSERT dbo.splunge([ID],[dt],[t]) SELECT '3','20120517 10:07:07:330','O''Brien' 

Si hay una columna IDENTITY puede que tenga que configurar SET_IDENTITY_INSERT ON para la tabla de PRUEBA y verificar que no haya colisión. Probablemente cerca de 500 advertencias que debo mencionar, no he probado todos los tipos de datos, etc.

Sin embargo, en el caso más general hay un lote más que esto. Vyas K tiene un procedimiento bastante robusta almacenado que debe demostrar lo complicado que puede llegar:

http://vyaskn.tripod.com/code/generate_inserts_2005.txt

Usted es probablemente mucho mejor usar una herramienta como Red-Gate's SQL Data Compare para recoger una fila específica y generar un inserto para usted. As I've blogged about, pagar por una herramienta no se trata solo de dinero, sino también de las horas de solución de problemas y corrección de errores que alguien más ya ha hecho por usted.

+0

Necesitaba hacer algunos cambios al código que escribió arriba (gracias por cierto). Fue un gran comentario y no estaba seguro de la etiqueta en la edición del código en su publicación, así que lo agregué a continuación. – RobRolls

2

Aaron, Me gustó tu código, me solucionó un problema. Me encontré con algunos problemas al usarlo (como dijiste que haría) con valores nulos y el tipo de texto, así que hice algunos cambios para solucionar esos problemas.

ALTER PROCEDURE dbo.GenerateSingleInsert 
@table  NVARCHAR(511), -- expects schema.table notation 
@pk_column SYSNAME,  -- column that is primary key 
@pk_value INT   -- change data type accordingly 
AS 
BEGIN 
SET NOCOUNT ON; 

DECLARE @cols NVARCHAR(MAX), @vals NVARCHAR(MAX), 
     @valOut NVARCHAR(MAX), @valSQL NVARCHAR(MAX); 

SELECT @cols = N'', @vals = N''; 

SELECT @cols = @cols + ',' + QUOTENAME(name), 
     @vals = @vals + ' + '','' + ' + 'ISNULL('+REPLICATE(CHAR(39),4)+'+RTRIM(' + 
             CASE WHEN system_type_id IN (40,41,42,43,58,61) -- datetime types 
             THEN 
              'CONVERT(CHAR(8), ' + QUOTENAME(name) + ', 112) + '' ''+ CONVERT(CHAR(14), ' + QUOTENAME(name) + ', 14)' 
             WHEN system_type_id IN (35) -- text type NOTE: can overflow 
             THEN 
              'REPLACE(CAST(' + QUOTENAME(name) + 'as nvarchar(MAX)),'+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')' 
             ELSE 
              'REPLACE(' + QUOTENAME(name) + ','+REPLICATE(CHAR(39),4)+','+REPLICATE(CHAR(39),6)+')' 
             END 
           + ')+' + REPLICATE(CHAR(39),4) + ',''null'') + ' 

    FROM sys.columns WHERE [object_id] = OBJECT_ID(@table) 
    AND system_type_id <> 189 -- can't insert rowversion 
    AND is_computed = 0;  -- can't insert computed columns 

SELECT @cols = STUFF(@cols, 1, 1, ''), 
     @vals = REPLICATE(CHAR(39),2) + STUFF(@vals, 1, 6, '') + REPLICATE(CHAR(39),2) ; 

SELECT @valSQL = N'SELECT @valOut = ' + @vals + ' FROM ' + @table + ' WHERE ' 
    + QUOTENAME(@pk_column) + ' = ''' + RTRIM(@pk_value) + ''';'; 

EXEC sp_executesql @valSQL, N'@valOut NVARCHAR(MAX) OUTPUT', @valOut OUTPUT; 

SELECT SQL = 'INSERT ' + @table + '(' + @cols + ') SELECT ' + @valOut; 
END 
Cuestiones relacionadas