3

В настоящее время у меня есть связанный сервер, который я запрашиваю в хранимой процедуре. У меня есть запрос, который работает нормально сейчас, однако этот запрос нужно будет изменить для каждой ветви кода, который у меня есть. Я хотел бы знать, что лучший метод для derrive имя базы данных, которую я вызываю в кросс-серверном запросе.Связанный серверный запрос/динамический SQL

Ex: Сервер A имеет ссылку на сервер B. Сервер A содержит 3 базы данных. SRV_A.DB1_DEV, SRV_A.DB2_Trunk, SRV_A.DB3_Prod Каждый связаны с их сервером B коллегой ... SRV_B.DB1_DEV, SRV_B.DB2_Trunk, SRV_B.DB3_Prod

Каждая база данных на сервере А имеет ту же хранимую процедуру. Единственное, что изменяется в sproc, - это выбор кросс-сервера. Так SRV_A.DB1_Dev есть выбор в sproc, который гласит:

SELECT foo FROM [SRV_B].[DB1_DEV].[foo_table] WHERE bar = 1 

, а хранимая процедура на ветви ствола будет

SELECT foo FROM [SRV_B].[DB2_Trunk].[foo_table] WHERE bar = 1 

Так как я хотел бы иметь проект VS, который будет развернут DB для каждой отмеченной ветви я хотел бы иметь возможность динамически заполнять имя базы данных. Решение, которое я придумал, что работает, чтобы использовать серию IF проверок с функцией CHARINDEX, а затем создать запрос с помощью динамического SQL, например:

DECLARE @dSql NVARCHAR(4000); 
DECLARE @databaseName NVARCHAR(100) = DB_NAME(); 
DECLARE @tableName NVARCHAR(100); 
IF SELECT CHARINDEX('Dev', @databaseName, 0) 
    SET @tableName = '[SRV_B].[DB1_DEV].[foo_table] 
    ...Same if & set for Trunk 
    ...Same if & set for Prod 
SET @dSql = 'DECLARE @retID INT;SELECT foo FROM ' + @tableName 
+ ' WHERE bar = 1';SET @retID = SELECT SCOPE_IDENTITY()' 
EXEC(@dSQL); 

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

Спасибо, Джеймс

ответ

5

Одним из способов решения этой проблемы может быть абстрактным именем связанного сервера, обернув его в synonym:
запиской дополнительную часть в имени таблицы назначения - кросс-серверные запросы требует имени из четырех частей - Я предполагаю, что это опечатка в вопросе и что foo_table находится в dbo схемы

CREATE SYNONYM dbo.syn_foo_table 
FOR [SRV_B].[DB1_DEV].[dbo].[foo_table] 

, который затем может быть назван в коде как

SELECT foo FROM dbo.syn_foo_table WHERE bar = 1 

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

Другим возможным решением является использование параметров SQLCMD в сценарии хранимой процедуры, поскольку проекты VSA (AFAIK) используют SQLCMD для развертывания объектов базы данных.
Эта функция позволяет параметризацию сценарии SQL с переменными в виде $(variablename) - в вашем случае:

SELECT foo FROM [SRV_B].[$(dbname)].[foo_table] WHERE bar = 1 

Значение переменной можно установить с помощью переменной окружения или переданы в команду в качестве аргумента, используя -v переключатель. Для получения более подробной информации см. Ссылку SQLCMD MSDN.

+0

Удивительный, оба метода работали как Шарм. Я решил пойти с опцией B. Да, вопрос был опечаткой, я действительно использую 4 названия частей. Спасибо за отличное объяснение! – SSISPissesMeOff

0

я был в состоянии использовать комбинацию enviornment переменных, как упоминалось выше, для имя-БД, а также динамически генерировать имя SRV, а также с помощью следующего запроса:

DECLARE @ServerName NVARCHAR(100); 
SET @ServerName = (SELECT name FROM sys.servers WHERE server_id = 1) 
Смежные вопросы