在多个数据库上执行SQL查询

时间:2016-09-05 18:47:11

标签: sql sql-server database

我知道我的帖子与这个论坛中的其他帖子非常相似,但我找不到我需要的答案。

这是我的问题,我在Windows Server上运行了一个SQL Server。在我的SQL Server中,我有大约30个数据库。它们都具有相同的表和相同的存储过程。

现在,问题是,我需要在所有这些数据库中运行这个庞大的脚本。我希望我只能对所有数据库进行一次。

我尝试了一些事情,比如去“查看”>>注册服务器>>本地服务器组>>新服务器注册。但是这个解决方案适用于许多服务器,而不是很多数据库。

我知道我可以通过输入数据库名称来实现,但查询真的很大,所以在所有数据库中运行都需要很长时间。

有没有人知道这是否可能?

8 个答案:

答案 0 :(得分:7)

ApexSQL Propagate是可以在这种情况下提供帮助的工具。它用于在多个数据库,甚至多个服务器上执行单个或多个脚本。您应该做的只是选择该脚本,然后选择要对其执行该脚本的所有数据库:

select databases

加载脚本和数据库时,只需单击“执行”按钮并等待结果:

click the execute button

答案 1 :(得分:3)

考虑从SSMS(查询 - SQLCMD模式)运行SQLCMD Mode中的脚本。这样,您可以将脚本保存到文件中,并在每个所需数据库的上下文中轻松运行:

USE DB1;
:r C:\SqlScript\YourLargeScript.sql
GO
USE DB2;
:r C:\SqlScript\YourLargeScript.sql
GO
USE DB3;
:r C:\SqlScript\YourLargeScript.sql
GO

答案 2 :(得分:2)

您可以对所有数据库名称使用WHILE循环,并在EXECUTE内循环执行查询。我认为该语句SET @dbname = ...可能会更好,但这也可以。

DECLARE @rn INT = 1, @dbname varchar(MAX) = '';
WHILE @dbname IS NOT NULL 
BEGIN
    SET @dbname = (SELECT name FROM (SELECT name, ROW_NUMBER() OVER (ORDER BY name) rn 
        FROM sys.databases WHERE name NOT IN('master','tempdb')) t WHERE rn = @rn);

    IF @dbname <> '' AND @dbname IS NOT NULL
        EXECUTE ('use ['+@dbname+'];

            /* Your script code here */
            UPDATE some_table SET ... ;

        ');
    SET @rn = @rn + 1;
END;

答案 3 :(得分:1)

这是执行此操作的常规方法:

假设您要对数据库DBOther进行选择而不是:

select * from DBOther..TableName

同时检查表或视图是否在dbo架构上,如果不是,你也应该添加架构:请注意我现在只使用一个点数据库名称

select * from DBOther.dbo.ViewName

如果任何数据库位于另一台计算机上的另一台服务器上,请确保数据库位于链接服务器中 然后,您可以通过以下方式访问该数据库上的表或视图:

SELECT * FROM [AnotherServerName].[DB].[dbo].[Table]

以下是另一种不需要输入数据库名称的方法:

use DB1
go

select * from table1
go

use DB2
go

select * from table1
go

请注意,这仅适用于每个数据库上的表和字段完全相同的情况

答案 4 :(得分:1)

你可以写这样的剧本

DECLARE CURSOR_ALLDB_NAMES CURSOR FOR
SELECT name 
FROM Sys.Databases
WHERE name NOT IN('master', 'tempdb') 

OPEN CURSOR_ALLDB_NAMES

FETCH CURSOR_ALLDB_NAMES INTO @DB_NAME

WHILE @@Fetch_Status = 0
BEGIN
  EXEC('UPDATE '+ @DB_NAME + '..SameTableNameAllDb SET Status=1')
  FETCH CURSOR_ALLDB_NAMESINTO INTO @DB_NAME
END

CLOSE CURSOR_ALLDB_NAMES

答案 5 :(得分:0)

根据要求,您可以执行以下操作:


declare @dbName nvarchar(100)
declare @script nvarchar(max)
declare @dbIndex bigint = 0
declare @dbCount bigint = (
    select count(*) from
        sys.databases

    )
declare crs_databases cursor for
(
    select
        [name]
    from
        sys.databases   
)
open crs_databases
fetch next from crs_databases into @dbName
while @@FETCH_STATUS = 0
begin
    set @dbIndex = @dbIndex+1
    set @script = concat(@script,
        ' select Id from ['+@dbName+']..YourTableName ',        
        case 
            when @dbIndex = @dbCount then ''
            else 'union'
        end)
    fetch next from crs_databases into @dbName
end

select @script
close crs_databases
deallocate crs_databases

请注意,双点符号表示架构为dbo。否则,您需要显式写下架构。

select Id from ['+@dbName+'].schema.YourTableName

当您需要在每台服务器上执行存储过程时,@script变量将包含其他内容。

答案 6 :(得分:0)

您可以使用以下脚本在一组数据库上运行相同的脚本。只需在插入行中更改过滤器即可。


declare @dbs table (
  dbName varchar(100),
  done bit default 0
)

insert @dbs select [name], 0 FROM master.dbo.sysdatabases WHERE [Name] like 'targets_%'

while (exists(select 1 from @dbs where done = 0))
begin
  declare @db varchar(100);
  select top 1 @db = dbName from @dbs where done = 0;
  exec ('
    use [' + @db + '];
    update table1 set
      col1 = '''',
      col2 = 1
    where id = ''45b6facb-510d-422f-a48c-687449f08821''
  ');
  print @db + ' updated!';
  update @dbs set done = 1 where dbName = @db;
end

如果您的SQL Server版本不支持表变量,请使用临时表,但不要忘记在脚本末尾删除它们。

答案 7 :(得分:-1)

丹的答案解决了我的问题! 只有一点,我必须在SQL Server Management的Query选项卡上启用SQLCMD模式。此外,文件的路径不能有空格。 感谢您的帮助!