在SQL查询中运行.sql文件

时间:2015-02-04 21:07:54

标签: sql-server tsql

我有一个SQL脚本,我需要在大约20个不同的数据库上运行。

我基本上只需要能够运行一些SQL,然后从磁盘加载并运行文件,执行更多SQL,再次运行相同的脚本等。

我希望创建一个基本上看起来像这样的SQL脚本:

use database1
go
exec c:\release.sql
go

use database2
go
exec c:\release.sql
go

use database3
go
exec c:\release.sql
go

- 等...

我已经在网上看了一堆,找到了一种在sqlcmd的批处理文件中做类似事情的方法,但是它没有工作,我也不知道如何以这种方式切换数据库,要么

非常感谢!

4 个答案:

答案 0 :(得分:5)

您可以将management studio切换到sqlcmd模式(查询菜单),然后使用:r script.sql

运行脚本

要在动态生成的数据库列表中执行此操作,您必须执行一些sqlcmd技巧:

  • 将输出设置为文件
  • 生成执行命令
  • 将输出设置为stdout
  • 执行文件
  • 删除临时文件

我假设在这个例子中,c:\temp中存在script.sql文件。请注意,GO语句在脚本中很重要,否则sqlcmd解析器会混淆。

:OUT $(TEMP)\db.sql
declare @script nvarchar(max)
select @script = isnull(@script, '') 
               + 'use ' + name + char(13) + char(10) 
               + ':r c:\temp\script.sql' + char(13) + char(10) 
  from sys.databases
 where name like N'%[_]db'
print @script

GO

:OUT stdout
:r $(TEMP)\db.sql

GO

!!del $(TEMP)\db.sql /s /q

答案 1 :(得分:1)

您不需要在SSMS中执行此操作。您只需要创建一个CMD脚本。

IF 您有一组要运行的静态数据库,请使用以下内容:

@ECHO OFF

SET MyServer="(local)"
SET MyScript="c:\release.sql"

SQLCMD -S %MyServer% -E -i %MyScript% -d database1
SQLCMD -S %MyServer% -E -i %MyScript% -d database2
...
SQLCMD -S %MyServer% -E -i %MyScript% -d database20

IF 您有一组可以查询的动态数据库,请使用以下内容:

@ECHO OFF

SET MyServer="(local)"
SET MyScript="c:\release.sql"
SET MyQuery="SET NOCOUNT ON; SELECT [Name] FROM [sys].[databases] sd WHERE sd.[name] LIKE N'%%[_]db' ORDER BY sd.[name];"

FOR /F %%B IN ('SQLCMD -h -1 -S %MyServer% -E -Q %MyQuery%') DO (
    REM remove the "echo" from the next line to run the scripts
    echo SQLCMD -S %MyServer% -E -i %MyScript% -d %%B -o results-%%B.txt
)

在输出文件名中使用%%B将为每个数据库提供不同的输出文件,如:

  

结果的database1_db.txt
  结果,database2_db.txt
  ...


其他说明:

  • 连接到本地默认实例时使用(local)而不是localhost,因为它在localhost强制TCP连接时使用共享内存。

  • 如果您在LIKE语句中搜索下划线,请将其括在方括号中,否则它是单字符外卡(有时在技术上仍有效,但也可以与其他字符匹配) :[_]

答案 2 :(得分:1)

谢谢大家投入!以下似乎可能有效(基于@ srutzky的回答)

  

sqlcmd -S" localhost" -E -i" c:\ release.sql" -d database1 -o results.txt

我使用cmd提示而不是SSMS而遗漏的是,我不认为我可以编写游标来循环遍历以" _db"结尾的每个数据库。然后对此执行...这是我的SQL,但我只需要能够将链接放到要执行的SQL文件中。

link

如果我将发布脚本SQL放入@text变量中,它就不起作用,因为它会破坏我在release.sql文件中的每个GO语句。

declare @text as nvarchar(max)
set @text = N'
-- GET AND RUN SCRIPT FROM DISK!
'

declare C_CURSOR CURSOR FOR 
    select  [Name] from sys.databases 
    where   name like '%_db' 
    order by name

declare @runtext as nvarchar(max)
declare @DB_Name as nvarchar(200)

OPEN C_CURSOR
fetch next from C_CURSOR INTO @DB_Name
WHILE(@@FETCH_STATUS = 0)
BEGIN

    print @DB_Name
    set @runtext = 'select ''' + @DB_Name + ''' as DatabaseName
        use ' + @DB_Name + N'
    ' + @text

    exec sp_executesql  @runtext

    fetch next from C_CURSOR INTO @DB_Name
END

CLOSE C_CURSOR
DEALLOCATE C_CURSOR

再次感谢!

答案 3 :(得分:0)

我最终结合了两件事。我创建了一个SQL脚本,它创建一个游标来查找数据库,然后打印一个CMD提示命令列表。然后我在命令提示符下运行它。下面是我们用sql脚本输出的内容,然后另存为我们运行的.bat文件。它工作得很好!

该脚本基本上是使用以下SQL脚本创建的:

/*** GET DATABASES IN THE CURSOR QUERY BELOW! */
declare C_CURSOR CURSOR FOR 
        select  [Name] from sys.databases 
        where   name like '%_db' 
        order by name

/* THIS IS WHERE THE CURSOR STARTS*/
declare @DB_Name as nvarchar(200)

OPEN C_CURSOR
fetch next from C_CURSOR INTO @DB_Name
WHILE(@@FETCH_STATUS = 0)
BEGIN

    print 'SQLCMD -S "localhost" -E -i "C:\release.sql" -d ' +  @DB_Name + ' -o ' +  @DB_Name + '_results.txt'

    fetch next from C_CURSOR INTO @DB_Name
END

CLOSE C_CURSOR
DEALLOCATE C_CURSOR

输出以下内容,然后在.bat文件中运行

SQLCMD -S "localhost" -E -i "C:\release.sql" -d database1 -o database1_results.txt
SQLCMD -S "localhost" -E -i "C:\release.sql" -d database2 -o database2_results.txt
SQLCMD -S "localhost" -E -i "C:\release.sql" -d database3 -o database3_results.txt

谢谢大家!