Переписать представление UNION как динамическое представление - PullRequest
2 голосов
/ 15 февраля 2011

Я работаю над этим уже несколько дней и не могу найти правильного решения, надеюсь, кто-то может помочь.

У нас есть несколько серверов баз данных (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

Есть несколько проблем с этим:

  • Когда мы добавляем серверы, мы должны изменить вид.
  • Наши среды разработки нуждаются такое же количество баз данных и поддельные ссылки серверы, чтобы мы могли установить эти вид.
  • Некоторые из серверов не включите данные с некоторых других серверов. Сегодня мы делаем это с помощью настраиваемых представлений на этих серверах, но это кошмар развертывания.

Так что я надеялся переписать это динамически. Цели:

  • Разрешить средам разработки содержат различное количество баз данных. Они могут иметь 2 или более баз данных на одном сервере.
  • Предоставить способ для каждого сервера указать, какие другие серверы включить в результаты.
  • Минимизируйте сложность, чтобы решение остается несколько ремонтопригодны.
  • Создайте одно решение, которое можно источник контролируется и используется на всех серверы.

И самое главное:

  • Выставить его как вид с тем же имя, поэтому мы не должны переписывать наши вся заявка.

Конечно, я не могу сделать динамический SQL в представлении или функции. Я попытался переписать это как хранимую процедуру, а затем с помощью трюка OPENROWSET запросить сохраненный процесс из представления. Это не сработало, потому что мне пришлось полностью квалифицировать proc с именем базы данных, что потребовало бы более динамического SQL (потому что имена баз данных разные). Затем я подумал о том, чтобы дурачиться с синонимами в основной базе данных, но это нарушает цели обслуживания и контроля версий.

У меня все в порядке с созданием новой таблицы с именами серверов и баз данных и флагами включения, если это необходимо. На самом деле это идеально, потому что централизует конфигурацию для каждой среды.

Я был полностью сбит с толку этим, и теперь я обращаюсь к вам, Интернету, в последний раз за помощью!

Ответы [ 5 ]

2 голосов
/ 15 февраля 2011

Одним из возможных решений является создание хранимой процедуры, которая регулирует представление. Например (не проверено):

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)

После этого вы можете вызвать хранимую процедуру после добавления базы данных или даже из запланированной задачи.

0 голосов
/ 15 февраля 2011

Вот что я бы предложил. Создайте таблицу для хранения конфигурации для каждого представления на конкретном сервере. Затем напишите динамический sql для создания скрипта вида на основе этих конфигураций. Затем запустите скрипт просмотра на сервере. Если вы хотите добавить новый сервер, добавьте его в таблицу конфигурации, в которой может быть триггер для автоматического воссоздания сценариев для изменяемых представлений. Или создайте заново сценарии из таблицы и выполняйте их как стандартную часть каждого развертывания.

0 голосов
/ 15 февраля 2011

Это похоже на задание для хранилища данных ... 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

Итак, вам необходимо создать много операторов вставки.Один для каждой комбинации сервера / базы данных / таблицы.

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

Поэтому, когда вы загружаете данные в эту новую таблицу базы данных, вы просто добавляете к каждой строке исходное имя сервера /имя_базы данных / имя таблицы SO .... Ваши данные выглядят так

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

Теперь все, что вам нужно сделать, это запрос к одной таблице, это будет очень быстро и чисто.

0 голосов
/ 15 февраля 2011

Если у вас есть таблица отслеживания серверов и баз данных, вы можете динамически построить представление в триггере этой таблицы.

Посмотрите на этот ответ на другой вопрос.Он предлагает то же самое и имеет некоторый пример кода для изменения определения представления в триггере.

Динамический дизайн таблицы (общая таблица поиска), нужен хороший запрос для получения значений

Это может сработать для вас.

0 голосов
/ 15 февраля 2011

Использование Синоним будет хорошим вариантом, если вы используете последний сервер SQL

...