2012-05-17 19 views
6

Questo è probabilmente uno scenario limitato ma prezioso. Ho un database di SQL Server 2008 con una tabella con milioni di record. Sembra che ci sia un problema intermittente con diversi record. Sto cercando di riprodurre il problema. Nel tentativo di farlo, ho finalmente ottenuto l'ID di un disco offensivo. Vorrei generare una dichiarazione INSERT associata a questo singolo record nel mio database PROD. Quindi posso facilmente migrarlo nel mio database di TEST nel tentativo di riprodurre e risolvere il problema.Generazione di script per record specifici in SQL Server

Fondamentalmente, ho bisogno di generare una singola istruzione INSERT per un singolo record da una singola tabella in cui conosco il valore della chiave primaria del record.

Qualcuno ha qualche idea su come posso realizzare questo? In sostanza, voglio generare istruzioni di inserimento su base condizionale.

Grazie!

+1

schema tabella? condizioni? ci sono persone abbastanza intelligenti qui ma nessuno di loro è profeta: P –

+0

Ho appena aggiornato la domanda. Grazie. – user70192

risposta

4

Primo tentativo di ricreare ciò che si desidera inserire con un'istruzione SELECT.

Dopo di che è possibile inserire nella tabella con un INSERT INTO come questo:

INSERT INTO tablename 
SELECT .... 

Se sono su server diversi, è possibile utilizzare INSERT in questo modo:

INSERT INTO tablename VALUES (...) 

utilizzando i valori dati dal SELECT nell'altro server riempiono i valori nell'inserto.

+0

Se si trovano su server diversi, ciò richiederà un server collegato.Mi piace l'idea migliore, ma penso che l'OP stia cercando di generare una stringa statica con valori da copiare, incollare ed eseguire altrove. –

+0

@AaronBertrand vero! Ho modificato per aggiungere quell'informazione. –

+0

Eccellente signore! risposta molto preziosa. –

5

Nel vostro caso specifico credo che si può fare questo:

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 

Quindi cerchiamo di provarlo:

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' 

Se c'è una colonna IDENTITY potrebbe essere necessario impostare SET_IDENTITY_INSERT ON per la tabella TEST e verificare che non ci sia collisione. Probabilmente circa 500 avvertimenti Devo dire, non ho ancora testato tutti i tipi di dati, ecc

Tuttavia, nel caso più generale c'è un molto più ad esso che questo. Vyas K ha una piuttosto robusto stored procedure che dovrebbero dimostrare come si può ottenere complicato:

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

Sei probabilmente molto meglio utilizzando uno strumento come Red-Gate's SQL Data Compare di scegliere una riga specifica e generare un inserto per voi. As I've blogged about, pagare per uno strumento non è solo una questione di soldi, si tratta delle ore di risoluzione dei problemi e di risoluzione dei bug che qualcun altro ha già fatto per te.

+0

Avevo bisogno di apportare alcune modifiche al codice che hai scritto sopra (grazie btw). Era un grosso problema per un commento e non ero sicuro dell'etichetta sul modificare il codice nel tuo post, quindi l'ho aggiunto di seguito. – RobRolls

2

Aaron, Mi è piaciuto il tuo codice, ha risolto un problema per me. Mi sono imbattuto in alcuni problemi che lo usavano (come hai detto tu) con null e il tipo di testo, quindi ho apportato alcune modifiche per risolvere questi problemi.

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 
Problemi correlati