创建跨越未知数量的数据库的VIEW

时间:2015-05-29 10:12:57

标签: sql sql-server tsql view multiple-tables

  • 我有一个"主人"包含ServerName和表的数据库 DatabaseName列。
  • 每一行代表一个"孩子"数据库可能在同一个或 不同的服务器。
  • 总会有至少一行,但理论上可以有一行 无限数量的行。
  • 在每个"孩子"数据库中有TableA和ColumnA。

如何在master中创建一个视图或函数(可能返回xml),它将在所有数据库中合并所有ColumnA值?

这样的事情:

USE Master;
GO
CREATE VIEW dbo.MyView
AS
    SELECT ColumnA FROM Server1.database1.dbo.TableA
    UNION ALL
    SELECT ColumnA FROM Server1.database2.dbo.TableA
    UNION ALL
    SELECT ColumnA FROM Server2.database1.dbo.TableA;
GO

但显然我们正在从主表中读取服务器名和数据库名。

2 个答案:

答案 0 :(得分:3)

如果要维护主列表,则需要更新此列表。这使您有机会添加/修改执行更新的触发器或存储过程。

换句话说,您希望主表上的触发器将重建视图。像这样:

create trigger dbo.trigger_mastertable_change on dbo.atable
for insert, update, delete
as begin
    declare @sql = nvarchar(max);

    select @sql = stuff((select 'union all ' +
                         replace(replace('select columnA from <server>.<database>.dbo.Table1',
                                         '<database>', quotename(t.databasename),
                                        ), '<server>', quotename(t.servername)
                                )
                          from dbo.atable
                          for xml path ('')
                        ), 1, 10, '');

    select @sql = 'alter view myview as ' + @sql;
    exec sp_executesql @sql;
end;

由于锁定问题,通常不建议在触发器中使用动态SQL。如果您有用于更改表的存储过程,那么最好将逻辑放在那里。

答案 1 :(得分:0)

从技术上讲,他们是对的。绕过SQL限制不是我推荐的。除上述内容外,CLR方法还提供另一个可选路径。

然而,如果您确实感到绝望的“违反规则”的愿望,我不建议将其作为最佳实践,但您可以考虑使用master.dbo.xp_cmdshell并使用脚本强制重建这个脚本确实允许EXEC和动态。

免责声明:不推荐:)

(只是为了证明总有办法)