如何使用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会话无效。
Lothar Kraner

Answers:


7

SSMS不会,我再说一遍,不会切换到一个USE命令您运行动态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。如果我明确声明这是不可能的,Daniel会非常喜欢,就像@Lothar的评论中所述。


太好了,谢谢亚伦·伯特兰(Aaron Bertrand)。而且,不,最终目标不是只是在SSMS中运行所有这些代码,以使SSMS现在处于@db的上下文中
Mazhar

2

实际上,dynamicSQL并未真正与您的代码其余部分特别地以内联方式执行,而是以一个单独的实体(即使它以内联方式运行)

如果运行代码:SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'在当前集的一部分中,您会注意到返回的结果表明您已经移动了活动数据库,但仍在同一连接下运行。

如果要更改嵌入式数据库选择,最好的方法是执行以下操作:

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

它不是很好,也不干净,每个潜在的数据库需要两行,但可以完成工作(不要在动态SQL中运行它,否则最终会遇到相同的问题,即主线程未更改)

请注意,尽管在过程/功能中禁止使用USE命令

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.