2009-06-24 22 views
21

Estoy tratando de cambiar la base de datos actual con una declaración SQL. me han tratado los siguientes, pero todos los intentos fallidos:sql use statement con la variable

  1. USO @DatabaseName
  2. EXEC sp_sqlexec @Sql - donde @Sql = 'USO [' + @DatabaseName + ']'

Para agregar un poco más de detalle.

EDITAR: Me gustaría realizar varias cosas en dos bases de datos separadas, donde ambas están configuradas con una variable. Algo como esto:

USE Database1 
SELECT * FROM Table1 

USE Database2 
SELECT * FROM Table2 
+1

Siguiendo Preet, tendrá que colocar todas las consultas para USE/SELECT en una sola llamada sp_sqlexec. El USE no sobrevivirá más allá de la llamada. –

+1

Conozco esta solución, pero es fea e ilegible. Tener un script que genere el SQL final también sería una opción. – Drejc

+0

Lo siento, pensé que solo estabas buscando una solución dentro del SQL. Dentro de SQL, solo tiene el enfoque sp_sqlexec; la otra opción es construir la secuencia SQL de USE/SELECT externamente. Aún necesitará construir el SQL a mano pero, en el lado positivo, su entorno de script/aplicación elegido será más fácil en la manipulación de cadenas y no se verá tan feo. –

Respuesta

9
exec sp_execsql @Sql 

El cambio DB sólo dura el tiempo necesario para completar @sql

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

+0

Como dije en la pregunta, esto no funciona. Por ejemplo, si ejecuto un comando SELECT después como: SELECCIONAR * FROM Table, se genera un error de nombre de objeto no válido – Drejc

+3

el seleccionar debe estar en @SQL - como dije, el uso es solo para la duración en el @sql –

+2

Es una especie de solución, pero inútil para mi propósito. – Drejc

6

El problema con el anterior es que lo que está haciendo es bastante USE 'myDB' que USE myDB. estás pasando una cadena; pero USE está buscando una referencia explícita.

El último ejemplo funciona para mí.

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

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

Preet es correcto con lo anterior. Aunque el USE funcionará para la instrucción @sql, no será un cambio permanente. Tener un USE paramterizado también presentaría todo tipo de implicaciones de rendimiento/compilación, y no veo ninguna alternativa de trabajo. - goodgai 0 secs ago [eliminar este comentario] –

-1

Uso exec sp_execsql @Sql

Ejemplo

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

? ... No lo entiendo – Drejc

2

probar esto:

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

Conozco esta solución, pero es inútil para mi propósito. – Drejc

-2

- Si utiliza una variable para el nombre de la base de datos.
- Pruebe algo como esto.

DECLARE @dbname varchar (50)
Set @dbname = 'database1'; /* < - Esto podría ser pasado por un parámetro.*/

IF (@dbname = 'database1')
Begin
      USO [database1];
      SELECT * DE Tabla1;
End

IF (@dbname = 'Database2')
Begin
      USO [Database2];
      SELECT * DE Tabla2;
End

IF (@dbname es null)
Begin
      USO [database1];
Fin

9

Tengo el mismo problema, lo superé con un conjunto feo pero útil de GOTOs.

La razón por la que llamo el "script runner" antes de todo es que quiero ocultar la complejidad y el enfoque feo de cualquier desarrollador que solo quiera trabajar con el script real. Al mismo tiempo, puedo asegurarme de que el script se ejecute en las dos bases de datos (extensibles a tres o más) de la misma manera.

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 este enfoque se llega a mantener sus variables y SQL Server no asuste si le toca ir a través de una instrucción DECLARE dos veces.

+0

Sé que estoy respondiendo preguntas de 2009, pero espero que alguien como yo encuentre aquí algo que puedan usar. – Alpha

+0

¡Esta solución es asombrosa ya que FUNCIONA REALMENTE! Puedo simplemente poner todos mis nombres de esquema en un procedimiento almacenado con esto y luego llamar a la declaración USE apropiada si hay una coincidencia. Brillante. (Incluso valida que están en un conjunto aprobado de nombres) –

+0

¡Acabo de ver esto !. ¡Buena respuesta! –

2

caso de que alguien que necesita una solución para esto, este es uno:

si se utiliza una sentencia USE dinámica toda la consulta tiene que ser dinámico, ya que tiene que ser todo en el mismo contexto.

Puede probar con SYNONYM, es básicamente un ALIAS a una tabla específica, este SYNONYM se inserta en el sistema.mesa de sinónimos para que tenga acceso a la misma desde cualquier contexto

Mira esta declaración estática:

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

Ahora dinámica:

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 

Ahora acaba de cambiar el valor de @CATALOG y podrá para hacer una lista de la misma tabla pero de un catálogo diferente.

1

Solo quería agradecer a KM por su valiosa solución. Lo implementé yo mismo para reducir la cantidad de líneas en una solicitud shrinkdatabase en SQLServer. Aquí es mi petición SQL si puede ayudar a cualquier persona:

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

Usted puede hacer esto:

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!} 

Esto significa que puede hacer un recursivo seleccionar el siguiente aspecto:

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, acabo de notar que esto es prácticamente lo mismo que ya se dijo! –