2009-06-24 19 views
21

Sto provando a cambiare il database corrente con un'istruzione SQL. Ho provato quanto segue, ma tutti i tentativi falliti:istruzione sql use con variabile

  1. USO @DatabaseName
  2. EXEC sp_sqlexec @sql - dove @sql = 'USO [' + @DatabaseName + ']'

Per aggiungere ulteriori dettagli.

MODIFICA: Vorrei eseguire diverse operazioni su due database separati, in cui entrambi sono configurati con una variabile. Qualcosa di simile a questo:

USE Database1 
SELECT * FROM Table1 

USE Database2 
SELECT * FROM Table2 
+1

seguito Le informazioni di Preet, dovrai inserire tutte le query per USE/SELECT in una singola chiamata sp_sqlexec. L'USO non sopravviverà oltre la chiamata. –

+1

Conosco questa soluzione, ma è brutta e illeggibile. Avere anche uno script che generi l'SQL finale sarebbe un'opzione. – Drejc

+0

Scusa pensavo che stavi cercando una soluzione all'interno di SQL stesso. All'interno di SQL, hai solo l'approccio sp_sqlexec; l'altra opzione è costruire la sequenza SQL di USE/SELECT esternamente. Avrai comunque bisogno di costruire manualmente l'SQL ma, sul lato positivo, l'ambiente di scripting/applicazione scelto sarà più semplice per la manipolazione delle stringhe e non sembrerà così brutto. –

risposta

9
exec sp_execsql @Sql 

Il cambiamento DB dura solo per il tempo necessario per completare @sql

http://blog.sqlauthority.com/2007/07/02/sql-server-2005-comparison-sp_executesql-vs-executeexec/

+0

Come detto nella domanda, questo non funziona. Ad esempio se eseguo un comando SELECT in seguito come: SELECT * FROM Table, viene generato un errore di nome oggetto non valido – Drejc

+3

la selezione deve essere nel @SQL - come ho detto l'uso è solo per la durata su @sql –

+2

È una specie di soluzione, ma inutile per il mio scopo. – Drejc

6

Il problema con l'ex è che quello che stai facendo è piuttosto USE 'myDB' di USE myDB. stai passando una stringa; ma USE sta cercando un riferimento esplicito.

Quest'ultimo esempio funziona per me.

declare @sql varchar(20) 
select @sql = 'USE myDb' 
EXEC sp_sqlexec @Sql 

-- also works 
select @sql = 'USE [myDb]' 
EXEC sp_sqlexec @Sql 
+1

Preimp è corretto con quanto sopra. Sebbene USE funzioni per l'istruzione @sql, non sarà un cambiamento permanente. Avere un USE paramterizzato presenterebbe anche ogni sorta di implicazioni sulle prestazioni/compilazione, e non vedo alcuna alternativa funzionante. - goodgai 0 secondi fa [elimina questo commento] –

-1

Usa exec sp_execsql @Sql

Esempio

DECLARE @sql as nvarchar(100) 
DECLARE @paraDOB datetime 
SET @paraDOB = '1/1/1981' 
SET @sql=N'SELECT * FROM EmpMast WHERE DOB >= @paraDOB' 
exec sp_executesql @sql,N'@paraDOB datetime',@paraDOB 
+0

? ... Non capisco. – Drejc

2

provare questo:

DECLARE @Query   varchar(1000) 
DECLARE @DatabaseName varchar(500) 

SET @DatabaseName='xyz' 
SET @Query='SELECT * FROM Server.'[email protected]+'.Owner.Table1' 
EXEC (@Query) 

SET @DatabaseName='abc' 
SET @Query='SELECT * FROM Server.'[email protected]+'.Owner.Table2' 
EXEC (@Query) 
+0

Sono a conoscenza di questa soluzione, ma è inutile per il mio scopo. – Drejc

-2

- Se si utilizza una variabile per il nome del database.
- Prova qualcosa del genere.

DECLARE @DBName varchar (50)
Set @DBName = 'Database1'; /* < - Potrebbe essere passato da un parametro.*/

IF (@dbname = 'Database1')
Begin
      USO [Database1];
      SELECT * DA Tabella1;
Fine

IF (@dbname = 'Database2')
Begin
      USO [Database2];
      SELECT * DA Tabella2;
Fine

IF (@dbname è nullo)
Begin
      USO [Database1];
Fine

9

Ho lo stesso problema, l'ho superato con un brutto - ma utile - set di GOTO.

Il motivo per cui io chiamo "script runner" prima di tutto è che voglio nascondere la complessità e l'approccio brutto di qualsiasi sviluppatore che voglia solo lavorare con lo script vero e proprio. Allo stesso tempo, posso assicurarmi che lo script venga eseguito nei due (estendibili a tre e più) database nello stesso identico modo.

GOTO ScriptRunner 

ScriptExecutes: 

--------------------ACTUAL SCRIPT-------------------- 
-------- Will be executed in DB1 and in DB2 --------- 
--TODO: Your script right here 

------------------ACTUAL SCRIPT ENDS----------------- 

GOTO ScriptReturns 

ScriptRunner: 
    USE DB1 
    GOTO ScriptExecutes 

ScriptReturns: 
    IF (db_name() = 'DB1') 
    BEGIN 
     USE DB2 
     GOTO ScriptExecutes 
    END 

Con questo approccio si arriva a mantenere le variabili e SQL Server non di matto se vi capita di andare oltre un'istruzione DECLARE due volte.

+0

So che sto rispondendo alle domande del 2009, ma spero che qualcuno come me troverà qui qualcosa che possono usare. – Alpha

+0

Questa soluzione è fantastica perché FUNZIONA REALMENTE !!! Posso semplicemente mettere tutti i nomi dei miei schemi in una procedura memorizzata con questo e poi chiamare l'istruzione USE appropriata se c'è una corrispondenza. Brillante. (Convalida anche che siano in un set di nomi approvato) –

+0

Ho appena individuato questo !. Buona risposta! –

2

caso io che qualcuno bisogno di una soluzione per questo, questo è uno:

se si utilizza un'istruzione USE dinamica tutta la vostra richiesta deve essere dinamico, perché hanno bisogno di essere tutto nello stesso contesto.

Puoi provare con SYNONYM, è fondamentalmente un ALIAS per una tabella specifica, questo SYNONYM è inserito nel sys.tavolo sinonimi in modo da avere accesso ad esso da qualsiasi contesto

Guardate questa dichiarazione statica:

CREATE SYNONYM MASTER_SCHEMACOLUMNS FOR Master.INFORMATION_SCHEMA.COLUMNS 
SELECT * FROM MASTER_SCHEMACOLUMNS 

Ora dinamica:

DECLARE @SQL VARCHAR(200) 
DECLARE @CATALOG VARCHAR(200) = 'Master' 

IF EXISTS(SELECT * FROM sys.synonyms s WHERE s.name = 'CURRENT_SCHEMACOLUMNS') 
BEGIN 
DROP SYNONYM CURRENT_SCHEMACOLUMNS 
END 

SELECT @SQL = 'CREATE SYNONYM CURRENT_SCHEMACOLUMNS FOR '+ @CATALOG +'.INFORMATION_SCHEMA.COLUMNS'; 
EXEC sp_sqlexec @SQL 

--Your not dynamic Code 
SELECT * FROM CURRENT_SCHEMACOLUMNS 

Ora basta modificare il valore di @CATALOG e si sarà in grado per elencare la stessa tabella ma da catalogo diverso.

1

Volevo solo ringraziare KM per la sua preziosa soluzione. L'ho implementato personalmente per ridurre la quantità di righe in una richiesta shrinkdatabase su SQLServer. Ecco la mia richiesta SQL se può aiutare chiunque:

-- Declare the variable to be used 
DECLARE @Query varchar (1000) 
DECLARE @MyDBN varchar(11); 
-- Initializing the @MyDBN variable (possible values : db1, db2, db3, ...) 
SET @MyDBN = 'db1'; 
-- Creating the request to execute 
SET @Query='use '+ @MyDBN +'; ALTER DATABASE '+ @MyDBN +' SET RECOVERY SIMPLE WITH NO_WAIT; DBCC SHRINKDATABASE ('+ @MyDBN +', 1, TRUNCATEONLY); ALTER DATABASE '+ @MyDBN +' SET RECOVERY FULL WITH NO_WAIT' 
-- 
EXEC (@Query) 
0

si può fare questo:

Declare @dbName nvarchar(max); 
SET @dbName = 'TESTDB'; 

Declare @SQL nvarchar(max); 
select @SQL = 'USE ' + @dbName +'; {can put command(s) here}'; 
EXEC (@SQL); 

{but not here!} 

Questo significa che si può fare un ricorsiva selezionare come il seguente:

Declare @dbName nvarchar(max); 
SET @dbName = 'TESTDB'; 
Declare @SQL nvarchar(max); 

SELECT @SQL = 'USE ' + @dbName + '; ' +(Select ... {query here} 
For XML Path(''),Type) 
.value('text()[1]','nvarchar(max)'); 

Exec (@SQL) 
+0

Woops, ho appena notato che è praticamente lo stesso di quanto già detto! –