我有一个大型数据库创建查询,其开头如下:
USE Master
GO
IF EXISTS(SELECT * FROM sys.sysdatabases where name = 'MyDatabase')
DROP DATABASE MyDatabase
GO
CREATE DATABASE MyDatabase
GO
USE MyDatabase
GO
我想在开头声明一个变量,如下所示:
DECLARE @MainDB VARCHAR(30) = NULL
USE Master
GO
IF EXISTS(SELECT * FROM sys.sysdatabases where name = @MainDB)
DROP DATABASE @MainDB
GO
CREATE DATABASE @MainDB
GO
USE @MainDB
GO
我将从命令行执行此查询,并使用sqlcmd工具分配新的数据库名称。但是sql告诉我没有声明变量@MainDB。这是我能做的吗?如果不是,你会如何推荐我解决这个问题?
答案 0 :(得分:0)
这个问题是一种改变。
How to use a variable for the database name in T-SQL?
简短的回答是你不能拥有可变数据库名称。你必须把你的T-SQL放到一个字符串/ VARCHAR(MAX)中,进行查找和替换,然后执行它。
答案 1 :(得分:0)
很抱歉,但你不能这样做,因为SQL变量只有“batch”-scope,而那些“GO”命令表示批次的边界。因此,每次你通过GO,你的所有变量都会被消灭(它们甚至不再被声明)。
有几种解决方法:
摆脱GO:这就是我们需要存储过程时所做的事情(不能有任何存储过程) 进入它而不是脚本,但它是一个相当复杂的一系列复杂的技巧,必须相互缠绕,以便将它拉下来。你必须非常熟悉T-SQL才能使用它。
使用#temp表来保存您的值。这是有效的,因为#temp表具有会话范围而不是批处理范围。
我相信你也可以使用和操作来自SQLCMD的NTDOS环境变量,虽然我不知道如何做到这一点。
如果您想要了解其中任何一项,请告诉我哪一个,我可以通过示例更详细地解释。
糟糕,我错过了“变量数据库名称”部分。这也可以,但你必须添加动态SQL。
答案 2 :(得分:0)
你有多个问题......
GO
结束当前批次。所以你的变量不再可见了。你需要移动声明。此外,您不能DROP DATABASE @MainDB
,您必须使用动态查询。例如,
GO
DECLARE @MainDB VARCHAR(30) = 'MyDB';
IF EXISTS(SELECT * FROM sys.sysdatabases where name = @MainDB)
BEGIN
EXECUTE ('DROP DATABASE '+@MainDB);
END;
答案 3 :(得分:0)
你说你需要从命令行运行它,所以如果你有很多代码依赖于你已经构建的结构,你可以执行以下操作:
显然,如果您喜欢此选项,请从脚本中删除DECLARE @MainDB varchar(30)= NULL。
如果选择这种方法,可以使用各种不同的技术(powershell,python,批处理文件,VBScript ......)实现3个步骤。
VBScript文件方法:
set obj = CreateObject("Scriptlet.TypeLib")
tempsqlfile = obj.GUID & ".sql" 'get a new name for your sql file
set fso = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(tempsqlfile, ForReading) 'open the template file
strSQLText = objFile.ReadAll
objFile.Close
strNewSQLText = Replace(strSQLText, "@MainDB", Wscript.Arguments(1)) 'replace the db name
Set objFile = objFSO.OpenTextFile(tempsqlfile, ForWriting)
objFile.WriteLine strNewText 'write the new file
objFile.Close
Set Shell = WScript.CreateObject("WScript.Shell")
commandLine = "osql -E -i " & Wscript.Arguments(0) & -o " & tempsqlfile & ".rpt"
Set oExec = Shell.Exec(commandLine)
为变量名称道歉 - 我从各个地方剪切并粘贴了点点滴滴,但你应该得到要点。
(另外 - 为所有这些选项中的VBScript选择道歉,并注意没有错误检查缺少参数)
如上所述,如果您将该脚本保存为'runmystuff.vbs',那么您可以这样做:
runmystuff.vbs sqlfile.sql MagicNewDB
这将在脚本中的所有地方用MagicNewDB替换@MainDB,然后使用osql运行它。
答案 4 :(得分:0)
找到一种方法使cmdline变量等于t-sql变量
USE master
GO
DECLARE @Mydb VARCHAR(30) = "$(mydb)"
IF EXISTS(SELECT * FROM sys.sysdatabases where name = @Mydb)
print @Mydb
Execute('create database ' + @Mydb)
我运行的批处理文件如下所示。
sqlcmd -S %1 -i CreateDatabases.sql -v mydb="%2"
我现在可以从sqlcmd运行并输入%1的服务器和%2的所需数据库名称。
感谢大家的回复,他们都帮助我找到了正确的解决方案。