2015-05-29 3 views
0
  • У меня есть «главная» база данных, которая содержит таблицу с именем ServerName и столбцами DatabaseName.
  • Каждая строка представляет собой «дочернюю» базу данных, которая может находиться на том же или разных серверах.
  • Всегда будет как минимум 1 ряд, но теоретически может быть неограниченное количество строк.
  • В каждой «дочерней» базе данных есть таблица A с ColumnA.

Как создать представление или функцию (возможно, возвращает xml) в мастер, который объединит все значения ColumnA во всех базах данных?Создать VIEW, охватывающий неизвестное количество баз данных

Что-то вроде этого:

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 

но, очевидно, мы читаем имя_сервера и имя базы данных из основной таблицы.

+0

не видят никакого другого пути, кроме использования курсора и цикла тщательного и получить unioned колоннообразных данных. – Rahul

+0

Но даже тогда он не был бы динамичным, как .. + ServerValue + ']. [' + DbValue + '] .dbo.TableA.ColumnA - ему понадобится exec для каждой строки, а exec не будет работать в функции. Tricky – DomBat

+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

Было бы более безопасно использовать 'функция QUOTENAME' процитировать сервера и базы данных имен: 'ВЫБРАТЬ Columna ОТ dbo.Table1' 'REPLACE (ЗАМЕНИТЬ ('', QUOTENAME (t.databasename)),' ', QUOTENAME (t.severname)) ' –

+0

@DmitrySavchenko. , , Это очень хороший момент. Спасибо. –

0

Технически они правы. Ограничение ограничений SQL - это не то, что я бы рекомендовал. Методы CLR предоставляют еще один дополнительный путь в дополнение к вышесказанному.

Однако, если вы почувствовали отчаянное желание «нарушить правила», я не рекомендую это как лучшую практику, но вы могли бы подумать о master.dbo.xp_cmdshell и использовать сценарий, чтобы заставить перестроить представление и т. д. Этот сценарий действительно позволит EXEC и динамический.

Отказ от ответственности: Не рекомендация :)

(Просто чтобы доказать, всегда есть способы)

+0

Я, конечно, предполагаю, что это не рутинное обходное решение для многораздельной базы данных. Посмотрите раздел. –

Смежные вопросы