Sea*_*anR 9 sql-server dynamic-sql sql-server-2008-r2
我有一个涉及在多个数据库之间执行各种命令的过程 - 但是,当我使用动态 SQL 通过“使用 @var”更改数据库时,它实际上并没有更改数据库。
在 [test_db] 中执行:
declare @currentDB varchar(max)
declare @sql varchar(max)
set @currentDB = DB_NAME()
set @sql = 'use [' + @currentDB +']'
use master
exec(@sql)
select DB_NAME()
Run Code Online (Sandbox Code Playgroud)
返回 [Master] 作为当前数据库名称 - 如果我将其use [test_db]作为命令而不是动态放置,则它返回正确的名称。
有没有办法做到这一点,可以在数据库之间正确切换?
Mis*_*goo 16
当然,有办法——总有办法……
如果您声明变量并将数据库和要运行的过程存储在其中,则可以使用参数执行它。
例子
use tempdb;
select db_name();
declare @db sysname = 'master.sys.sp_executesql';
exec @db N'select db_name()';
set @db = 'msdb.sys.sp_executesql';
exec @db N'select db_name()';
Run Code Online (Sandbox Code Playgroud)
然后传递带有参数的查询以在任何数据库中运行是微不足道的
declare @proc sysname, @sql nvarchar(max), @params nvarchar(max);
select
@proc = 'ssc.sys.sp_executesql'
, @sql = N'select top 10 name from sys.tables where name like @table order by name;'
, @params = N'@table sysname';
exec @proc @sql, @params, @table = 'Tally%'
Run Code Online (Sandbox Code Playgroud)
我知道这不会改变主查询中的数据库上下文,但想演示如何以安全的参数化方式方便地在另一个数据库中工作,而不会造成太多麻烦。
Sol*_*zky 11
当该子流程结束时,在子流程(即EXEC/ sp_executesql)中进行的会话级更改将消失。这涵盖了USE和SET语句以及在该子流程中创建的任何本地临时表。全局临时表的创建将在子进程中继续存在,对子进程启动之前存在的本地临时表所做的修改以及对CONTEXT_INFO(我相信)的任何更改也将继续存在。
所以不,您不能动态更改当前数据库。如果您需要执行此类操作,您将需要在该动态 SQL 中执行依赖于新数据库上下文的任何后续语句。