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


123

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

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

但这是行不通的。那么编写此代码的正确方法是什么?

Answers:


135

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

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

然后用

EXECUTE (@SQL_SCRIPT)

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

您不能EXEC多个批次。GO是批处理分隔符,而不是T-SQL语句。必须构建三个单独的字符串,然后EXEC替换后再构建每个字符串。

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

我从哪里得到“ 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
+1非常好用的方法...您刚刚从大量工作中救了我,谢谢...尽管它应该是EXECUTE(@SQL_SCRIPT),否则至少对我有用。
2011年

2
不过,在转义时需要小心。
usr

4
SYSNAME会比处理所有可能的数据库名称(并可能根据名称来源防止SQL注入)VARCHAR(255)使用的数据类型更合适QUOTENAME
Martin Smith

1
如果我想CREATE SCHEMA在其他数据库中使用,则无效USE {DBNAME}。模式在错误的数据库中创建; /
Bomberlt

103

您也可以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
该方法如何使用已经声明的变量?您可以添加@dbName代替“ TEST”吗?我尝试了但没有工作
syclee 2015年

1
@syclee一个TSQL变量?在脚本甚至发送到服务器之前,不执行任何sqlcmd替换。
马丁·史密斯

@MartinSmith嘿,我希望将数据库名称作为OUTPUT命令。那么,如何使用SQLCMD拥有它呢?
Kunal Kakkad 2015年

12

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

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

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

然后打电话

EXECUTE(@Sql) or sp_executesql(@Sql)

执行sql字符串。


EXEC寻找一个存储过程。在这种情况下EXECUTE是必需的。
Bob Blogge

2
其实我要道歉 原来,EXECEXECUTE是相同的。我失败后所作的发言EXEC,并与随后的EXECUTE。虽然显然我的真正问题与任何一个都不相关。
Bob Blogge

2
永远不要在生产中这样做。
Magic Octopus Urn's

@MagicOctopusUrn不同的旧帖子和非常评论,但我很好奇,为什么不呢?应该不是特定于需求的吗?
严苛的

@MagicOctopusUrn那是因为有注射的潜力吗?
艾萨克·里夫曼

5

您不能在create table语句中使用变量。我可以建议的最好的办法是将整个查询编写为字符串,然后执行该字符串。

尝试这样的事情:

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

exec (@query);
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.