Sql server 带变量的sql use语句

Sql server 带变量的sql use语句,sql-server,sql-server-2005,dynamic-sql,Sql Server,Sql Server 2005,Dynamic Sql,我试图用SQL语句切换当前数据库。 我尝试了以下操作,但所有尝试均失败: 使用@DatabaseName EXEC sp_sqlexec@Sql-其中@Sql='使用['+@DatabaseName+'] 再加一点细节 编辑:我想在两个单独的数据库上执行一些操作,其中两个数据库都配置了一个变量。大概是这样的: USE Database1 SELECT * FROM Table1 USE Database2 SELECT * FROM Table2 数据库更改只会持续到@sql完成的时间 前者

我试图用SQL语句切换当前数据库。 我尝试了以下操作,但所有尝试均失败:

使用@DatabaseName EXEC sp_sqlexec@Sql-其中@Sql='使用['+@DatabaseName+'] 再加一点细节

编辑:我想在两个单独的数据库上执行一些操作,其中两个数据库都配置了一个变量。大概是这样的:

USE Database1
SELECT * FROM Table1

USE Database2
SELECT * FROM Table2
数据库更改只会持续到@sql完成的时间


前者的问题是,您所做的是使用“myDB”,而不是使用myDB。 你在传递一根绳子;但是USE正在寻找一个明确的引用

后一个例子适用于我

declare @sql varchar(20)
select @sql = 'USE myDb'
EXEC sp_sqlexec @Sql

-- also works
select @sql = 'USE [myDb]'
EXEC sp_sqlexec @Sql
使用exec sp_execsql@Sql

范例

DECLARE @sql as nvarchar(100)  
DECLARE @paraDOB datetime  
SET @paraDOB = '1/1/1981'  
SET @sql=N'SELECT * FROM EmpMast WHERE DOB >= @paraDOB'  
exec sp_executesql @sql,N'@paraDOB datetime',@paraDOB
试试这个:

DECLARE @Query         varchar(1000)
DECLARE @DatabaseName  varchar(500)

SET @DatabaseName='xyz'
SET @Query='SELECT * FROM Server.'+@DatabaseName+'.Owner.Table1'
EXEC (@Query)

SET @DatabaseName='abc'
SET @Query='SELECT * FROM Server.'+@DatabaseName+'.Owner.Table2'
EXEC (@Query)

如果SQLCMD是一个选项,那么它支持的脚本变量超出了straight T-SQL的功能范围。例如:

我也有同样的问题,我用一套难看但有用的goto来克服它

我之所以先调用脚本运行程序,是因为我想对任何只想使用实际脚本的开发人员隐藏复杂性和丑陋的方法。同时,我可以确保脚本以完全相同的方式在两个可扩展到三个或更多数据库中运行

GOTO ScriptRunner

ScriptExecutes:

--------------------ACTUAL SCRIPT--------------------
-------- Will be executed in DB1 and in DB2 ---------
--TODO: Your script right here

------------------ACTUAL SCRIPT ENDS-----------------

GOTO ScriptReturns

ScriptRunner:
    USE DB1
    GOTO ScriptExecutes

ScriptReturns:
    IF (db_name() = 'DB1')
    BEGIN
        USE DB2
        GOTO ScriptExecutes
    END

使用这种方法,您可以保留变量,如果您碰巧两次检查DECLARE语句,SQL Server也不会崩溃。

如果有人需要解决此问题,这是一个:

如果使用动态use语句,则所有查询都需要是动态的,因为它需要是同一上下文中的所有内容

您可以尝试使用同义词,它基本上是特定表的别名,此同义词插入sys.synonyms表中,因此您可以从任何上下文访问它

看看这个静态语句:

CREATE SYNONYM MASTER_SCHEMACOLUMNS FOR Master.INFORMATION_SCHEMA.COLUMNS
SELECT * FROM MASTER_SCHEMACOLUMNS
现在动态:

DECLARE @SQL VARCHAR(200)
DECLARE @CATALOG VARCHAR(200) = 'Master'

IF EXISTS(SELECT * FROM  sys.synonyms s WHERE s.name = 'CURRENT_SCHEMACOLUMNS')
BEGIN
DROP SYNONYM CURRENT_SCHEMACOLUMNS
END

SELECT @SQL = 'CREATE SYNONYM CURRENT_SCHEMACOLUMNS FOR '+ @CATALOG +'.INFORMATION_SCHEMA.COLUMNS';
EXEC sp_sqlexec @SQL

--Your not dynamic Code
SELECT * FROM CURRENT_SCHEMACOLUMNS

现在只需更改@CATALOG的值,您就可以列出相同的表,但来自不同的目录。

只想感谢KM提供了宝贵的解决方案。 我自己实现了它,以减少SQLServer上shrinkdatabase请求中的行数。 以下是我的SQL请求,如果它可以帮助任何人:

-- Declare the variable to be used
DECLARE @Query varchar (1000)
DECLARE @MyDBN varchar(11);
-- Initializing the @MyDBN variable (possible values : db1, db2, db3, ...)
SET @MyDBN = 'db1';
-- Creating the request to execute
SET @Query='use '+ @MyDBN +'; ALTER DATABASE '+ @MyDBN +' SET RECOVERY SIMPLE WITH NO_WAIT; DBCC SHRINKDATABASE ('+ @MyDBN +', 1, TRUNCATEONLY); ALTER DATABASE '+ @MyDBN +' SET RECOVERY FULL WITH NO_WAIT'
-- 
EXEC (@Query)
您可以这样做:

Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';

Declare @SQL nvarchar(max);
select @SQL = 'USE ' + @dbName +'; {can put command(s) here}';
EXEC (@SQL);

{but not here!}
这意味着您可以执行如下递归选择:

Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';
Declare @SQL nvarchar(max);

SELECT @SQL = 'USE ' + @dbName + '; ' +(Select ... {query here}
For XML Path(''),Type)
.value('text()[1]','nvarchar(max)');

Exec (@SQL)

普里特的上述观点是正确的。尽管@sql语句可以使用,但它不会是永久性的更改。参数化的使用也会带来各种性能/编译方面的影响,我看不到任何替代方案goodgai 0秒前[删除此评论]虽然成功,但正如问题中所述,此操作无法转换数据库。此操作不起作用。例如,如果我在之后运行SELECT命令,如:SELECT*FROM Table,则会出现无效的对象名称错误SELECT必须位于@SQL中-正如我所说的,仅在@sqlIt上使用。这是一种解决方案,但对我的目的无效。以下是Preet的信息,您必须将USE/SELECT的所有查询放在一个sp_sqlexec调用中。我知道这个解决方案,但它既丑陋又不可读。有一个脚本生成最终的SQL也是一个选择。很抱歉,我以为您只是在SQL本身中寻找解决方案。在SQL中,只有sp_sqlexec方法;另一个选项是构造外部使用/选择的SQL序列。您仍然需要手动构造SQL,但从有利的方面来看,您选择的脚本/应用程序环境将更易于字符串操作,并且看起来不会那么难看。我知道这个解决方案,但它是usless用于我的目的。我知道我正在回答2009年的问题,但希望像我这样的人能在这里找到一些他们可以使用的东西。这个解决方案非常棒,因为它确实有效!!!我可以将所有的模式名与此一起放入一个存储过程中,如果存在匹配项,则调用相应的USE语句。明亮的它甚至可以验证它们是否在一组已批准的名称中。我刚刚发现了这个!。回答得好!不幸的是,当数据库存在于不同的服务器上时,这似乎不起作用。PROD_SVR.PROD_DB、UAT_SVR.UAT_DB、IT_SVR.IT_DB等。SSMS似乎会验证脚本中所有USE语句的数据库是否存在,即使这些行没有执行。我尝试了一种变体:IF@SERVERNAME='UAT\u Server'BEGIN USE UAT\u Database GOTO Script END我认为只有动态SQL在这种情况下才有效。虽然它在某些情况下有效,但它仍然不能提供动态数据库更改的方法。即,如果数据库表中存储了活动数据库名称,并且希望在活动数据库上应用特定脚本。这不是批评,只是用户应该意识到限制。Woops,只是注意到这实际上与之前所说的一样!如何访问表的内容?
Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';

Declare @SQL nvarchar(max);
select @SQL = 'USE ' + @dbName +'; {can put command(s) here}';
EXEC (@SQL);

{but not here!}
Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';
Declare @SQL nvarchar(max);

SELECT @SQL = 'USE ' + @dbName + '; ' +(Select ... {query here}
For XML Path(''),Type)
.value('text()[1]','nvarchar(max)');

Exec (@SQL)