Sql server 在sql查询中运行.sql文件

Sql server 在sql查询中运行.sql文件,sql-server,tsql,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 --等等 我在网上查阅了很多资料,发现了

我有一个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执行类似操作的方法,但它不起作用,我也不知道如何以这种方式切换数据库

非常感谢


Ben

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

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

  • 将输出设置为文件
  • 生成要执行的命令
  • 将输出设置为标准输出
  • 执行该文件
  • 删除临时文件
在本例中,我假设script.sql文件存在于
c:\temp
中。请注意,
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

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

如果要运行一组静态数据库,请使用以下命令:

@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
@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
)
如果您有一组可查询的动态数据库,请使用以下方法:

@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
@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将为每个数据库提供不同的输出文件,如下所示:

结果数据库1_db.txt
结果数据库2_db.txt


其他说明:

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

  • 如果要在类似于
语句的
语句中搜索下划线,请将其括在方括号中,否则它是一个单字符通配符(有时在技术上仍然有效,但也可能与其他字符匹配):
[\u]


    感谢所有参与的人!以下内容看起来可能有用(基于@srutzky的答案)

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

    通过使用cmd提示符而不是SSMS,我缺少的一点是,我不认为我可以编写游标来循环遍历以“\u db”结尾的每个数据库,然后针对该数据库执行操作。。。这是我拥有的SQL,但我只需要能够将指向SQL文件的链接放入执行

    如果我将发布脚本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
    

    再次感谢

    我最后把两件事结合起来。我制作了一个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
    

    谢谢大家

    这不管用吗?是因为你的屏幕没有打开吗?可能是重复的,请将此作为问题的更新发布。这不是一个答案;这只是关于这个问题的更多细节。它应该放在那里,这个答案应该被删除。@user1588449好吧,这不是你问的问题。动态发现要在其上运行的数据库与使用静态列表非常不同。这需要在问题中提到,因为它完全使Filip De Vos的答案无效,因为这在SQLCMD模式下是不可能的。我更新了我的答案,展示了如何使用一组动态数据库来实现这一点。我制作了一个SQL脚本,它创建一个游标来查找数据库,然后为CMD提示符打印命令列表。然后,我在命令提示符下运行该方法。不幸的是,鉴于数据库名称必须从查询中派生的更新要求,此方法无效。我更新了答案,使之与新问题相匹配。你为什么要这样做。。。这是3个步骤,其中2个需要手动执行,而我建议的1个步骤可以完全自动化。。这种方法的好处是什么。。你看到我更新的答案了吗。。我解释了为什么应该使用
    (本地)
    而不是
    localhost