Cómo cambiar dinámicamente la base de datos usando TSQL

11

Tengo problemas para intentar cambiar dinámicamente el contexto de SSMS a la base de datos especificada en SQL dinámico:

EXEC sys.sp_executesql N'USE db1 ' ;

Se ejecuta con éxito, sin embargo, el contexto de la base de datos de SSMS no cambia.

He intentado una ligera modificación a lo anterior así

DECLARE @sql NVARCHAR(100) DECLARE @db NVARCHAR(50)
SET @db = N'db1' SET @sql = N'Use ' + @db
EXEC sp_executesql @sql

Nuevamente, se ejecuta con éxito, pero la base de datos no cambia.

Mazhar
fuente
44
No puede cambiar el contexto dentro de un sp_executesql para la sesión que está utilizando en el SSMS. El contexto solo es válido durante su sesión dinámica de SQL, no para la sesión SSMS.
Lothar Kraner

Respuestas:

7

SSMS NO REPETIRÁ, NO CAMBIARÁ AL CONTEXTO DE UN COMANDO DE USO QUE USTED EJECUTE EN SQL DINÁMICO.

Si el objetivo final es ejecutar algún otro SQL dinámico dentro de la base de datos elegida, esto es bastante fácil:

DECLARE @db sysname = N'db1';

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'SELECT DB_NAME();';

EXEC @exec @sql;

Si necesita pasar parámetros, no hay problema:

DECLARE @db sysname = N'db1', @i int = 1;

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'SELECT DB_NAME(), @i;';

EXEC @exec @sql, N'@i int', @i;

Si el objetivo es ejecutar un SQL estático dentro de la base de datos elegida, tal vez debería considerar almacenar ese SQL estático en un procedimiento almacenado en cada base de datos y llamarlo dinámicamente de esta manera:

DECLARE @db sysname = N'db1';

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'EXEC dbo.procedurename;';

EXEC @exec @sql;

Y es de esperar que el objetivo final no sea ejecutar todo este código en SSMS solo para que SSMS esté ahora en el contexto de @db... A Daniel realmente le gustaría si declaro explícitamente que esto no es posible, como también dijo el comentario de @ Lothar.

Aaron Bertrand
fuente
Esto es genial, gracias Aaron Bertrand. Y no, el objetivo final no es ejecutar todo este código en SSMS solo para que SSMS esté ahora en el contexto de @db
Mazhar
2

El dynamicSQL no se ejecuta específicamente en línea con el resto del código, es una entidad separada (aunque se ejecuta como si estuviera en línea

Si ejecuta el código: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid' en el lugar de su conjunto actual, notará que los resultados que aparecen indican que ha movido la base de datos activa, pero que todavía se está ejecutando con la misma conexión.

Si desea cambiar la selección de la base de datos en línea, la mejor manera es hacer algo como esto:

IF @db = 'db1'
    USE db1
ELSE IF @db = 'db2'
    USE db2

No es agradable ni limpio y requiere dos líneas por base de datos potencial, pero hará el trabajo (no lo ejecute en SQL dinámico o aún terminará con el mismo problema de que el hilo principal no se cambia)

Sin embargo, tenga en cuenta que el uso de comandos USE está prohibido en procedimientos / funciones

Ste Bov
fuente