web-dev-qa-db-fra.com

Comment changer dynamiquement la base de données à l'aide de TSQL

J'ai du mal à essayer de changer dynamiquement le contexte de SSMS en base de données spécifiée en SQL dynamique:

EXEC sys.sp_executesql N'USE db1 ' ;

Il s'exécute avec succès mais le contexte de base de données de SSMS ne change pas.

J'ai essayé une légère modification de ce qui précède comme ça

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

Encore une fois, il s'exécute avec succès, mais la base de données ne change pas.

11
Mazhar

SSMS NE SERA PAS, JE RÉPÉTE, NE SERA PAS PASSEZ AU CONTEXTE D'UNE COMMANDE D'UTILISATION QUE VOUS EXÉCUTEZ EN DYNAMIC SQL.

Si le but ultime est d'exécuter un autre SQL dynamique dans la base de données choisie, c'est assez simple:

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 vous devez passer des paramètres, pas de problème:

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 le but est d'exécuter du SQL statique dans la base de données choisie, vous devriez peut-être envisager de stocker ce SQL statique dans une procédure stockée dans chaque base de données, et de l'appeler dynamiquement comme ceci:

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;

Et j'espère que le but ultime n'est pas d'exécuter tout ce code dans SSMS juste pour que SSMS soit maintenant dans le contexte de @db... Daniel aimerait vraiment que je déclare explicitement que ce n'est pas possible, comme l'a également déclaré le commentaire de @ Lothar.

7
Aaron Bertrand

Le dynamicSQL n'est pas réellement exécuté spécifiquement en ligne avec le reste de votre code, c'est une entité distincte (même s'il est exécuté comme s'il était en ligne

Si vous exécutez le code: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid' à la place de votre ensemble actuel, vous remarquerez que les résultats qui reviennent indiquent que vous avez déplacé la base de données active, mais que vous exécutez toujours sous la même connexion.

Si vous souhaitez modifier la sélection de la base de données en ligne, la meilleure façon est de faire quelque chose comme ceci:

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

Ce n'est ni agréable ni propre et nécessite deux lignes par base de données potentielle, mais cela fera le travail (ne l'exécutez pas en SQL dynamique ou vous vous retrouverez toujours avec le même problème de thread principal non modifié)

Notez cependant que l'utilisation des commandes USE est interdite dans les procédures/fonctions

2
Ste Bov