2016-04-28 12 views
11

Ho questo codice MSSQL SQLCMD, che può accedere al database e in thisjust fare una dichiarazione SELECT:modo più intelligente per utilizzare SQLCMD con dinamica chiamando

:CONNECT czasql-001 
    SELECT * FROM [Lps_Hepper_Cz].[config].[LpsPlant] 
    GO 

    :CONNECT LS_Hepper_DK 

    SELECT * FROM [LPS_Hepper_NY].[config].[LpsPlant] 

    :CONNECT LS_Hepper_DK 
    SELECT * FROM [LPS_Hepper_DK].[config].[LpsPlant] 

    :CONNECT LS_Hepper_DK 
    SELECT * FROM [LPS_Hepper_SUPPLIER].[config].[LpsPlant] 
    GO 

      :CONNECT LS_Hepper_372 
    SELECT * FROM [LPS_Hepper_MO].[config].[LpsPlant] 
    GO 

      :CONNECT LS_Hepper_678 
    SELECT * FROM [LPS_Hepper_678].[config].[LpsPlant] 
    GO 

Questa soluzione funziona bene, ma mi richiede di copiare incollare il copia più volte per cambiare il nome del database. Ma qualcuno può aiutarmi a migliorare questo usando invece un ciclo. Ho provato usando una tabella temporanea. In questo modo:

declare @tbl table (ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0)) 
insert into @tbl (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]') 
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]') 
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]') 
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]') 
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]') 
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]') 

Ma Non riesco a capire per fare la logica per iterate attraverso il database di connettersi al server e impostare il nome del database, quando i dati che ho è come un nvarchar? Qualcuno ha un suggerimento?

UPDATE: Lo userò solo per INSERT/UPDATE o DELETE. Quindi non sto usando una procedura memorizzata. Mi piace usare questo per aggiornare i dati su tutti i nostri database. Ecco perché userò solo la tabella temporanea che dovrebbe far parte dello script.

I nomi dei nomi dei server e dei database verranno dalla tabella temporanea in alto. I nomi delle tabelle sono gli stessi su tutti i database, poiché abbiamo copie del database in tutto il mondo per limitare il download dei dati, necessario per assicurarmi che quando aggiorno uno, aggiorni anche il resto.

Aggiornamento 2: ho cercato di giocare con essa, ma continuo stallo, con il non essere in grado di utilizzare i valori nella tabella temporanea. Il che significa che non posso usare il: SETVAR per impostare il nome del server:

declare @tbl table (ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0)) 
    insert into @tbl (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]') 
    insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]') 
    insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]') 
    insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]') 
    insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]') 
    insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]') 

     WHILE (SELECT COUNT(*) FROM @tbl WHERE IsDone = 0) > 0 
     BEGIN 

     DECLARE @selectedRow INT = (SELECT TOP 1 Id FROM @tbl WHERE IsDone = 0) 
     --DECLARE @ServerName NVARCHAR(50)= (SELECT ServerName FROM @tbl WHERE Id = @selectedRow) 
     --DECLARE @DatabaseName NVARCHAR(50) = (SELECT DbName FROM @tbl WHERE Id = @selectedRow) 
     DECLARE @ServerName sysname= (SELECT ServerName FROM @tbl WHERE Id = @selectedRow) 
     DECLARE @DatabaseName sysname = (SELECT DbName FROM @tbl WHERE Id = @selectedRow) 

     :SETVAR DatabaseName @DatabaseName 
     :SETVAR ServerName @ServerName 
     SELECT ServerName --This looks correctly 
     print CONVERT(NVARCHAR(100),@selectedRow) 
     :CONNECT ServerName 

      USE @DatabaseName 
      GO 
      SELECT * FROM [config].[LpsPlant] 
     GO 

     UPDATE @tbl SET IsDone = 1 WHERE Id = @selectedRow 
    END; 
+1

Provare a chiamare 'sqlcmd' da Powershell. PS ha l'istruzione 'foreach' http://sqlvariant.com/2011/01/powershell-week-at-sql-university-post-5/ ed è facile da fare. –

+0

'SELECT *' è l'istruzione effettiva che è necessario eseguire o solo un esempio? se hai bisogno di esportare i dati, 'bcp' è una scelta migliore (e può anche essere eseguita da PowerShell, secondo il suggerimento di Ilya). –

+0

Presumo che non venga chiamato da un ambiente di programmazione esterno come .NET perché è possibile creare facilmente ciascun comando in tale scenario. Pertanto, dobbiamo sapere: 1) stai usando una procedura memorizzata e 2) come si determinano i nomi di server e tabelle? (Esse sono passate alla procedura memorizzata? È determinato in fase di esecuzione? È possibile impostare una tabella permanente con queste informazioni?) –

risposta

1

Sto solo andando a utilizzare questo per INSERT/UPDATE o DELETE. Quindi non sto usando una procedura memorizzata. Mi piace usare questo per l'aggiornamento dei dati su tutti i nostri database

Se è il caso si potrebbe considerare l'utilizzo di Registered Servers:

vantaggi di Server registrati

Con Server registrati voi can:

  • Registrare i server per conservare le informazioni di connessione.

  • Determinare se un server registrato è in esecuzione.

  • Collega facilmente Object Explorer e Query Editor a un server registrato.

  • Modificare o eliminare le informazioni di registrazione per un server registrato.

  • Creare gruppi di server.

  • Fornire nomi user-friendly per i server registrati fornendo un valore nella casella Nome server registrato diverso dall'elenco dei nomi dei server .

  • Fornire descrizioni dettagliate per i server registrati.

  • Fornire descrizioni dettagliate dei gruppi di server registrati.

  • Esporta gruppi di server registrati.

  • Importa gruppi di server registrati.

  • Visualizza i file di log di SQL Server per le istanze online o offline di SQL Server

  • Execute Statements Against Multiple Servers Simultaneously

Si potrebbe creare più gruppi in base a: Server/database/ambiente (DEV/prod/QA).

Un'altra possibilità è quella di esportare i server registrati su file, inserire il sistema di controllo del codice sorgente (SVN/Git) e condividerli con altri sviluppatori.

Utilizzando SSMS, fai clic su nuova query in base al gruppo di server ed esegui la stessa query su più database contemporaneamente.

enter image description here

Immagine da: http://sqlmag.com/site-files/sqlmag.com/files/archive/sqlmag.com/content/content/142469/Greenwood-SQL2331-Fig5-sm.jpg

+0

Il motivo per cui non posso usarlo è che voglio essere in grado di inviare lo script a un db guy che può eseguirlo senza essere sicuro di avere server registrati! – mortenstarck

+0

@mortenstarck Come ho detto prima c'è la possibilità molto semplice di esportare la configurazione dei server registrati. Il carico di lavoro è molto semplice: esportazione conf, mettere in sistema di controllo o inviare via email, importare ed eseguire query. [Importa ed esporta server SQL registrati su altre macchine] (https://www.mssqltips.com/sqlservertip/2015/import-and-export-registered-sql-servers-to-other-machines/) – lad2025

1

effettuare le seguenti operazioni:

1) Creare link server.

2) Eseguire sotto lo script ho modificato il codice snip-it

IF OBJECT_ID('tempdb..##Results') IS NOT NULL 
    Truncate TABLE ##Results 
else 
    CREATE TABLE ##Results 
    (id int identity ,ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0)) 
     -- populat link server name and db name 
    insert into ##Results (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]') 
    insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]') 
    insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]') 
    insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]') 
    insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]') 
    insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]') 

     WHILE (SELECT COUNT(*) FROM ##Results WHERE IsDone = 0) > 0 
     BEGIN 

     DECLARE @selectedRow INT = (SELECT TOP 1 Id FROM ##Results WHERE IsDone = 0) 
     DECLARE @sq1 varchar (100) ='SELECT * FROM ' ; -- 
     DECLARE @sql varchar (8000) = ''; 
     DECLARE @FROM varchar (100) ='[config].[LpsPlant]' ; 
       select @sql = @sq1 + ServerName + '.'+ DbName+ @FROM FROM ##Results WHERE Id = @selectedRow 

     print @sql 
     exec @sql 

     UPDATE ##Results SET IsDone = 1 WHERE Id = @selectedRow 
    END; 
1

utilizzando un cursore, potrebbe essere:

CREATE TABLE #TEMP (ServerName nvarchar(50), DbName nvarchar(50)) 
insert into #TEMP (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]') 
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]') 
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]') 
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]') 
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]') 
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]') 

DECLARE @ServerName VARCHAR(100), 
@DatabaseName VARCHAR(100); 

DECLARE CRS CURSOR LOCAL 
FOR SELECT * FROM #TEMP 

FETCH NEXT FROM CRS INTO @ServerName, @DatabaseName; 

WHILE @@FETCH_STATUS=0 
BEGIN 
    print CONVERT(NVARCHAR(100),@selectedRow) 

    :CONNECT @ServerName 
    GO 
    USE @DatabaseName 
    GO 
    SELECT * FROM [config].[LpsPlant] 
    GO 

    FETCH NEXT FROM CRS INTO @ServerName, @DatabaseName; 
END 

DROP TABLE #TEMP 
1

non ho eseguito il codice, ma vedo un possibile problema nell'utilizzo della parola GO, che non è una parola chiave SQL, ma una parola chiave SQL Server/SqlCmd che significa "qui termina un blocco di script, esegui tutto in esso e attendi tutte le conseguenze". Non sono sicuro che possa funzionare all'interno di un ciclo WHILE a causa di ciò.

poi vedo che si sta tentando

:CONNECT ServerName 

ma nel documentation per questo vedo la sintassi di essere

:CONNECT $(ServerName) 

C'è anche la questione del ciclo. SQL Server non garantisce l'ordine di un'istruzione SELECT se non si utilizza ORDER BY. Se non ti interessa l'ordine in cui esegui le istruzioni, allora è OK, altrimenti devi cambiarlo con un cursore o almeno aggiungere una colonna numerica e ordinare da esso quando selezioni TOP 1.

Problemi correlati