Como alterar dinamicamente o banco de dados usando TSQL

11

Estou tendo problemas ao tentar alterar dinamicamente o contexto do SSMS para o banco de dados especificado no SQL dinâmico:

EXEC sys.sp_executesql N'USE db1 ' ;

Ele é executado com sucesso, porém o contexto do banco de dados do SSMS não muda.

Eu tentei uma ligeira modificação para o acima mencionado assim

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

Novamente, ele é executado com êxito, mas o banco de dados não muda.

Mazhar
fonte
4
Você não pode alterar o contexto em um sp_executesql para a sessão que está usando no SSMS. O contexto é válido apenas durante sua sessão dinâmica do SQL - não para a sessão do SSMS.
Lothar Kraner

Respostas:

7

O SSMS NÃO REPETIRÁ, NÃO MUDARÁ AO CONTEXTO DE UM COMANDO DE USO QUE VOCÊ EXECUTAR NO SQL DINÂMICO.

Se o objetivo final é executar alguma outra SQL dinâmica dentro do banco de dados escolhido, isso é 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;

Se você precisar passar parâmetros, não há 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;

Se o objetivo é executar algum SQL estático dentro do banco de dados escolhido, talvez você deva considerar armazenar esse SQL estático em um procedimento armazenado em cada banco de dados e chamá-lo dinamicamente assim:

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;

E, esperançosamente, o objetivo final não é executar todo esse código no SSMS, apenas para que o SSMS esteja agora no contexto de @db... Daniel realmente gostaria se eu declarasse explicitamente que isso não é possível, como também afirmou o comentário de @ Lothar.

Aaron Bertrand
fonte
Isso é ótimo, obrigado Aaron Bertrand. E não, o objetivo final não é executar todo esse código no SSMS, apenas para que o SSMS esteja agora no contexto de @db
Mazhar
2

O dynamicSQL não é realmente executado especificamente em linha com o restante do seu código, é uma entidade separada (mesmo que seja executado como se estivesse em linha

Se você executar o código: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'no lugar do seu conjunto atual, notará que os resultados retornados indicam que você moveu o banco de dados ativo, mas ainda está executando na mesma conexão.

Se você deseja alterar a seleção do banco de dados em linha, a melhor maneira é fazer algo assim:

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

Não é bom ou limpo e requer duas linhas por banco de dados em potencial, mas ele fará o trabalho (não execute-o no SQL dinâmico ou você ainda terá o mesmo problema do thread principal que não está sendo alterado)

Observe que o uso de comandos USE é proibido nos procedimentos / funções

Ste Bov
fonte