Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 创建数据库脚本中的变量声明_Sql Server_Variables_Sqlcmd - Fatal编程技术网

Sql server 创建数据库脚本中的变量声明

Sql server 创建数据库脚本中的变量声明,sql-server,variables,sqlcmd,Sql Server,Variables,Sqlcmd,我有一个大型数据库创建查询,其开头如下: 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 G

我有一个大型数据库创建查询,其开头如下:

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。这是我能做的吗?如果不是,你会建议我如何解决这个问题?

这个问题有点重复


简而言之,您不能有一个可变的数据库名称。您必须将T-SQL放入字符串/VARCHAR(MAX)中,进行查找和替换,然后执行它。

抱歉,但您不能这样做,因为SQL变量只有“batch”范围,而那些“GO”命令指示批的边界。因此,每次通过GO时,所有变量都会被删除(甚至不再声明它们)

有几种方法可以解决这个问题:

  • 摆脱围棋:这是我们在需要存储过程(不能有任何存储过程)时所做的 GOs)而不是脚本,但这是一系列相当复杂的复杂技巧,必须相互缠绕才能成功。您必须非常熟练地使用T-SQL

  • 使用#temp表保存您的值。这是因为#temp表具有会话作用域,而不是批处理作用域

  • 我相信您也可以使用和操作SQLCMD中的NTDOS环境变量,尽管我不太熟悉具体的操作方法

  • 如果你想了解其中任何一个,请告诉我哪一个,我可以用例子更详细地解释



    哎呀,我错过了其中的“变量数据库名称”部分。这也可以做到,但您必须将动态SQL添加到组合中。

    您有多个问题。。。
    GO
    结束当前批次。因此,您的变量不再可见。你需要移动申报单。此外,您不能
    删除DATABASE@MainDB
    ,必须使用动态查询。比如说,

    GO 
    DECLARE @MainDB VARCHAR(30) = 'MyDB';
    IF EXISTS(SELECT * FROM sys.sysdatabases where name = @MainDB)
    BEGIN
      EXECUTE ('DROP DATABASE '+@MainDB);
    END;
    

    您说您需要从命令行运行它,因此如果您有大量代码,这取决于您已经构建的结构,那么您可以执行以下操作:

  • 创建脚本的临时副本
  • 搜索@MainDB并将其替换为临时脚本中作为参数传入的DB名称
  • 使用sqlcmd工具运行临时脚本
  • 显然,如果您喜欢此选项,请从脚本中删除DECLARE@MainDB varchar(30)=NULL

    如果选择这种方法,则可以使用各种不同的技术(powershell、python、批处理文件、VBScript…)实现这三个步骤

    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运行它。

    找到了一种使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所需的DB名称


    感谢所有人的回复,他们都帮助我找到了正确的解决方案。

    另请参见,变量范围仅限于单个查询批处理(两个GO语句之间的所有内容)。仅供参考:LastCoder答案中的链接显示了如何执行上面的#1,这也适用于动态SQL要求。