是否可以在 T-SQL 中以完全限定的 table 名称有条件地指定数据库?

Is it possible to conditionally specify the database in a fully qualified table name in T-SQL?

在工作中,我们有三个 SQL Server 2008 R2 数据库环境:生产、测试​​和开发。

在生产环境中,我们系统的不同部分 运行 在 3 个不同的数据库服务器上(我们称它们为 PROD1PROD2PROD3),而在我们在同一台服务器上拥有所有数据库 运行ning 的开发环境(我们称之为 DEV1)。

这通常不是问题,因为我们的大多数 SQL 代码不需要引用其自身数据库之外的对象。但在少数情况下,视图或存储过程需要引用 table、视图或函数,这些视图或函数不仅驻留在另一个数据库中,而且还驻留在不同生产服务器上的数据库中。 IE。我们在 PROD3 上有一个视图,需要在 PROD1 的用户列表中查找用户,如下所示:

PROD1.UserDB.UserSchema.UserList

当然这给我们的测试环境带来了问题,因为我们需要这些views/stored程序来引用不同的服务器,这取决于它们运行.

我的问题:是否可以在 T-SQL 中的完全限定 table 名称 (ServerName.DatabaseName.SchemaName.TableName) 中包含条件值? IE。我可以在视图或存储过程中使用类似 (PROD1|DEV1).UserDB.UserSchema.UserList 的东西吗?或者以某种方式从变量中获取服务器名称,然后我们可以根据当前服务器进行设置?

额外问题:在一种情况下,我们甚至还必须更改数据库名称。这可以用类似的方式完成吗?

我意识到我们可以通过在字符串中创建动态 SQL 语句然后执行它来解决这个问题。但出于各种原因,我们非常希望避免这种方法。

对于跨数据库引用,您最好的选择可能是使用 synonyms。 DEV 和 PROD 的同义词定义会有所不同,但使用同义词的复杂对象(视图、SP 等)的定义可以保持不变。

您想要 Linked Servers and server aliases.

的组合

如前所述,您确实需要使用动态 SQL。但是您可以使用它来创建对象:只需在动态 SQL 中为需要从另一台服务器和/或另一台数据库访问的所有对象创建同义词。

在这种情况下,您的所有代码都将是静态的,并且仅在使用动态 SQL 的安装/部署过程中才会引用所需的对象。

代码可以像下面这样:

declare @sql nvarchar(max)

if @@servername = 'DEV1'
    set @sql = 'create synonym vUserList for [Dev1].UserDB.UserSchema.UserList'
else
    set @sql = 'create synonym vUserList for [PROD1].UserDB.UserSchema.UserList'

exec sp_executesql @sql

并且您的所有代码(SP、函数等)都可以使用这个同义词 - vUserList

您可以以相同的方式更改目标数据库名称,具体取决于环境 - test、dev 或 prod