如何在 T-SQL 中使用变量作为数据库名称?

How to use a variable for the database name in T-SQL?

提问人:Erick Sasse 提问时间:4/8/2009 最后编辑:Peter MortensenErick Sasse 更新时间:12/15/2016 访问量:243948

问:

我在脚本中的多个位置使用了数据库名称,并且我希望能够快速更改它,因此我正在寻找类似以下内容的内容:

DECLARE @DBNAME VARCHAR(50)
SET @DBNAME = 'TEST'

CREATE DATABASE @DBNAME
GO
ALTER DATABASE @DBNAME SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE @DBNAME SET RECOVERY SIMPLE 
GO

但它不起作用。那么编写这段代码的正确方法是什么呢?

sql-服务器

评论

0赞 Wai Ha Lee 6/24/2021
强烈相关:我怎样才能做这样的事情:使用@databaseName

答:

5赞 Andrew Hare 4/8/2009 #1

不能在 create table 语句中使用变量。我能建议的最好的事情是将整个查询编写为字符串并执行它。

尝试这样的事情:

declare @query varchar(max);
set @query = 'create database TEST...';

exec (@query);
13赞 Dillie-O 4/8/2009 #2

遗憾的是,您不能使用该格式的变量声明数据库名称。

对于您要完成的任务,您需要将语句包装在 EXEC() 语句中。所以你会有类似的东西:

DECLARE @Sql varchar(max) ='CREATE DATABASE ' + @DBNAME

然后调用

EXECUTE(@Sql) or sp_executesql(@Sql)

执行 SQL 字符串。

评论

0赞 Bob Blogge 7/19/2013
EXEC查找存储过程。在这种情况下,是需要的。EXECUTE
2赞 Bob Blogge 7/19/2013
其实我需要道歉。事实证明,这是一样的。我是在失败和成功后发表的声明。虽然显然我真正的问题与两者都无关。EXECEXECUTEEXECEXECUTE
2赞 Magic Octopus Urn 9/16/2017
不要在生产中这样做......曾。
0赞 Harsh Shankar 11/9/2018
@MagicOctopusUrn改变旧帖子和非常评论,但我很好奇,知道为什么不呢?它不应该是特定于需求的吗??
0赞 Isaac Reefman 5/23/2019
@MagicOctopusUrn 那是因为注射的潜力吗?
146赞 John Saunders 4/8/2009 #3

将整个脚本放入模板字符串中,并带有 {SERVERNAME} 占位符。然后使用以下命令编辑字符串:

SET @SQL_SCRIPT = REPLACE(@TEMPLATE, '{SERVERNAME}', @DBNAME)

然后用

EXECUTE (@SQL_SCRIPT)

很难相信,在三年的时间里,没有人注意到我的代码不起作用

不能进行多个批次。 是批处理分隔符,而不是 T-SQL 语句。有必要构建三个单独的字符串,然后在替换后构建每个字符串。EXECGOEXEC

我想人们可以做一些“聪明”的事情,通过将单个模板字符串拆分为多行来拆分;我已经在 ADO.NET 代码中做到了这一点。GO

我从哪里得到“SERVERNAME”这个词?

以下是我刚刚测试的一些代码(并且有效):

DECLARE @DBNAME VARCHAR(255)
SET @DBNAME = 'TestDB'

DECLARE @CREATE_TEMPLATE VARCHAR(MAX)
DECLARE @COMPAT_TEMPLATE VARCHAR(MAX)
DECLARE @RECOVERY_TEMPLATE VARCHAR(MAX)

SET @CREATE_TEMPLATE = 'CREATE DATABASE {DBNAME}'
SET @COMPAT_TEMPLATE='ALTER DATABASE {DBNAME} SET COMPATIBILITY_LEVEL = 90'
SET @RECOVERY_TEMPLATE='ALTER DATABASE {DBNAME} SET RECOVERY SIMPLE'

DECLARE @SQL_SCRIPT VARCHAR(MAX)

SET @SQL_SCRIPT = REPLACE(@CREATE_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

SET @SQL_SCRIPT = REPLACE(@COMPAT_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

SET @SQL_SCRIPT = REPLACE(@RECOVERY_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

评论

2赞 reSPAWNed 9/15/2011
+1 非常好的方法...你刚刚把我从大量的工作中解救出来,谢谢......虽然它应该是 EXECUTE(@SQL_SCRIPT),或者至少这对我有用。
2赞 usr 5/29/2013
不过,逃跑时需要小心。
4赞 Martin Smith 11/14/2013
SYSNAME将是一个更合适的数据类型,而不是应该用于处理所有可能的数据库名称(并且可能根据名称的来源来防止 SQL 注入)VARCHAR(255)QUOTENAME
1赞 Bomberlt 6/26/2015
如果我想在其他数据库中使用,则不起作用。架构在错误的数据库中创建;/CREATE SCHEMAUSE {DBNAME}
110赞 Martin Smith 2/11/2012 #4

还可以为此使用 sqlcmd 模式(在 Management Studio 的“查询”菜单上启用此功能)。

:setvar dbname "TEST" 

CREATE DATABASE $(dbname)
GO
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE 
GO

编辑:

查看此 MSDN 文章,了解如何通过 SQLCMD 工具设置参数。

评论

1赞 syclee 4/14/2015
此方法如何使用已声明的变量?您可以添加@dbName而不是“TEST”吗?我试过了,但没有成功
2赞 Martin Smith 4/14/2015
@syclee TSQL 变量?否,sqlcmd 替换是在将脚本发送到服务器之前执行的。
0赞 Kunal Kakkad 12/29/2015
@MartinSmith 嘿,我想要数据库名称作为 OUTPUT 命令。那么我如何使用SQLCMD来拥有它呢?