3

我目前有一个在存储过程中查询的链接服务器。我的查询目前工作得很好,但是这个查询需要针对我拥有的每个代码分支进行更改。我想知道派生我在跨服务器查询中调用的数据库名称的最佳方法是什么。

例如:服务器 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

服务器 A 上的每个数据库都有相同的存储过程。存储过程中唯一改变的是跨服务器选择。所以 SRV_A.DB1_Dev 在存储过程中有一个选择,内容如下:

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 项目,将数据库部署到提到的每个分支,我希望能够动态填写数据库名称。我想出的解决方案是使用 CHARINDEX 函数进行一系列 IF 检查,然后使用动态 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);

我不得不想象有一个更好的解决方案,如果有人可以帮助我,将不胜感激。如果通过一些外线投篮,这是最好的方法,也让我知道。

谢谢,詹姆斯

4

2 回答 2

5

解决此问题的一种方法可能是通过将链接服务器名称包装在同义词中来抽象它:
注意目标表名称中的额外部分 - 跨服务器查询需要一个四部分名称 - 我假设这是一个错字在问题中,那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在存储过程脚本中使用参数,因为(AFAIK)VS 项目用于SQLCMD部署数据库对象。
此功能允许您使用表单中的变量参数化 SQL 脚本$(variablename)- 在您的情况下:

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

-v可以使用环境变量设置变量的值,也可以使用开关将其作为参数传递给命令。有关完整详细信息,请参阅SQLCMD上面的 MSDN 链接。

于 2012-04-16T08:53:13.323 回答
0

我能够将上述环境变量组合用于 db-name,并且还可以使用以下查询动态生成 SRV 名称:

DECLARE @ServerName NVARCHAR(100);
SET @ServerName = (SELECT name FROM sys.servers WHERE server_id = 1)
于 2012-04-17T01:41:32.330 回答