Як динамічно змінювати базу даних за допомогою TSQL


11

У мене виникають проблеми з спробою динамічно змінити контекст SSMS до бази даних, визначеної в динамічному SQL:

EXEC sys.sp_executesql N'USE db1 ' ;

Вона успішно виконується, проте контекст бази даних SSMS не змінюється.

Я спробував незначну модифікацію вищезазначеного, як це

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

Знову ж, він виконується успішно, але база даних не змінюється.


4
Ви не можете змінити контекст у sp_executesql для сеансу, який ви використовуєте в SSMS. Контекст дійсний лише під час вашого динамічного сеансу SQL - не для сеансу SSMS.
Лотар Кранер

Відповіді:


7

SSMS НЕ БУДУТЬ, Я ПОВТОРЮЮ, НЕ БУДУТЬ ПЕРЕКЛЮЧАТИ ДО КОНТЕКСТУ ВИКОРИСТАННЯ, КОМАНДУЙТЕ ВИ ДИНАМИЧНИМ SQL.

Якщо кінцевою метою є виконання деякого іншого динамічного SQL всередині обраної бази даних, це досить просто:

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;

Якщо вам потрібно передати параметри, немає проблем:

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;

Якщо мета полягає у виконанні деякого статичного SQL всередині обраної бази даних, можливо, вам слід розглянути можливість зберігання цього статичного SQL у збереженій процедурі у кожній базі даних та викликати його динамічно так:

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;

І, сподіваємось, кінцевою метою є не запускати весь цей код у SSMS просто так, щоб SSMS зараз знаходився в контексті @db... Даніелу дуже сподобалося, якщо я прямо заявлю, що це неможливо, як також зазначав коментар @ Lothar.


Це чудово, дякую Аарону Бертранду. І немає, кінцева мета полягає в тому, щоб не запустити весь цей код в SSMS просто так , що SSMS тепер в контексті @db
Mazhar

2

Динамічний SQL насправді не виконується конкретно в рядку з рештою коду, його окремою сутністю (навіть якщо він функціонує так, ніби він знаходиться в рядку

Якщо ви запускаєте код: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'у вашому поточному наборі ви помітите, що результати, що повертаються, вказують на те, що ви перемістили активну базу даних, але ви все ще працюєте під тим самим підключенням.

Якщо ви хочете змінити вибір баз даних у мережі, найкращим способом є щось подібне:

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

Це не приємно чи чисто і вимагає двох рядків на потенційну базу даних, але вона виконає роботу (не запускайте її в динамічному SQL, інакше ви все одно закінчите те, що головний потік не змінюється)

Зауважте, що використання команд USE заборонено в процедурах / функціях

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.