将UNION视图重写为动态视图

时间:2011-02-14 21:16:56

标签: sql-server dynamic view union

我已经在这方面工作了好几天,我找不到合适的解决方案,我希望有人可以提供帮助。

我们有几个结构相同的数据库服务器(SQL Server),由链接服务器连接。我们有一堆视图可以跨所有服务器联合数据:

CREATE VIEW Things_view AS
  SELECT id, thing
    FROM server1.database1.dbo.stuff
  UNION ALL
  SELECT id, thing
    FROM server2.database2.dbo.stuff
  UNION ALL
  SELECT id, thing
    FROM server3.database3.dbo.stuff

这有几个问题:

  • 当我们添加服务器时,我们必须修改 视图。
  • 我们的开发环境需要 相同数量的数据库和假链接 服务器所以我们可以安装这些 视图。
  • 某些服务器没有 包括来自其他一些服务器的数据。今天我们使用这些服务器上的自定义视图执行此操作,但这是部署的噩梦。

所以我希望动态地重写它。目标是:

  • 允许开发环境 包含不同数量的数据库。他们很可能 在一台服务器上有两个或更多数据库。
  • 为每个服务器提供一种方法 指定要使用的其他服务器 包含在结果中。
  • 最大限度地减少复杂性 解决方案仍然有点 可维护性。
  • 创建一个可以的解决方案 源控制和使用所有 服务器。

最重要的是:

  • 将其展示为具有相同的视图 名字所以我们不必重写我们的 整个申请。

当然,我无法在视图或函数中执行动态SQL。我尝试将其重写为存储过程,然后使用OPENROWSET trick从视图中查询存储的proc。这不起作用,因为我必须使用数据库名称完全限定proc,这将需要更多动态SQL(因为数据库名称不同)。然后我想到在主数据库上使用同义词,但这违反了维护和源代码控制目标。

如果需要,我可以创建一个包含服务器名称和数据库名称以及包含标志的新表。事实上,这是理想的,因为它集中了每个环境的配置。

我对此感到非常困惑,现在我正在联系你,互联网,请求最后的请求帮助!

5 个答案:

答案 0 :(得分:2)

一种可能的解决方案是创建一个调整视图的存储过程。例如(未测试):

create procedure dbo.RecreateView
as
declare @sql varchar(max)

select @sql = IsNull(@sql + 'union all ','') +
              'select * from ' + name + '.dbo.YourView '
from   sys.databases
where  name like 'DbNamePrefix%'

set @sql = 'create view dbo.YourView as ' + @sql
exec (@sql)

然后,您可以在添加数据库后调用存储过程,甚至可以从计划任务调用存储过程。

答案 1 :(得分:0)

如果您使用的是最新的SQL服务器

,使用同义词将是一个不错的选择

答案 2 :(得分:0)

如果您有一个跟踪服务器和数据库的表,您可以在该表的触发器中动态构建视图。

看看另一个问题的答案。它提出了同样的建议,并有一些示例代码来改变触发器中的视图定义。

Dynamic table design (common lookup table), need a nice query to get the values

它可能适合你。

答案 3 :(得分:0)

这听起来像是数据仓库的工作...... http://en.wikipedia.org/wiki/Data_warehouse您需要按照设定的时间表运行,因此数据不是实时的。这是唯一的缺点。

使用类似于下面的文件从每个server[n].database.tablename加载数据。

--Here is how you would administer the script.  One single script that you would only need to modify when you added/removed servers.
So you can easily add this to source control or whatever. You can also do all this, without linked servers, if you look at some ETL tools. like SSIS

insert into dataserver1.datawarehouse.tablename select *,'svr1,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr2,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr3,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr4,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr5,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr6,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr7,'db','tablename' from svr1.db.tablename
insert into dataserver1.datawarehouse.tablename select *,'svr8,'db','tablename' from svr1.db.tablename

因此您需要创建许多插入语句。每个服务器/ db / table组合一个。

insert into dataserver1.datawarehouse.tablename select *,'svr1,'db','tablename' from svr1.db.tablename

因此,当您将数据加载到此新数据库表中时,您只需将每个行附加原始servername / databasename / tablename SO ....您的数据如下所示

col1 col2 col3 srvnam dbname tbl
foo  bar  some MSSQL1 master mycooltable
foo  bar  some MSSQL2 other  mycooltable

现在,你所要做的就是查询一个表,它会非常快,干净。

答案 4 :(得分:0)

这是我的建议。创建一个表来存储特定服务器上每个视图的配置。 然后编写动态sql以基于这些配置创建视图脚本。 然后在服务器上运行视图脚本。 如果要添加新服务器,请将其添加到配置表中,该配置表可能具有触发器以自动为正在更改的视图重新创建脚本。或者从表中重新创建脚本并运行它们是每个部署的标准部分。