2

我想要一个程序来访问表/视图/存储过程等(物化的东西,我们称之为 X)抽象三个基本表中包含的数据的真实位置(这些表在所有位置都有相同的定义)。

我希望X从某个地方(可能是一个表)获取服务器名称、目录名称和表名称,并访问特定的三个基本表。X的调用者不知道正在调用哪些特定的表。

如何在 SQL Server (2008) 中执行此操作?

4

4 回答 4

2

像函数一样,视图不能使用动态 SQL - 它不能在某处找到一些元数据引用并进行相应调整。

我认为最接近你想要的是同义词。假设您有三个不同的数据库ABC。在A表中,您希望视图引用的是dbo.foo、 in Bit isdbo.bar和 in Cit is dbo.splunge。那么你可以在每个数据库中创建一个这样的同义词:

USE A;
GO
CREATE SYNONYM dbo.YourCommonViewName FOR dbo.foo;
GO

USE B;
GO
CREATE SYNONYM dbo.YourCommonViewName FOR dbo.bar;
GO

USE C;
GO
CREATE SYNONYM dbo.YourCommonViewName FOR dbo.splunge;
GO

现在这在技术上不是一个视图,但在每个数据库中你可以说......

SELECT <cols> FROM dbo.YourCommonViewName;

...它将从特定于数据库的表中返回数据。


在存储过程中执行此操作会简单得多。假设您将服务器、数据库和表名存储在某个表中,例如dbo.lookup

CREATE TABLE dbo.lookup
(
  id INT PRIMARY KEY,
  [server]   SYSNAME,
  [database] SYSNAME,
  [table]    SYSNAME,
  active BIT NOT NULL DEFAULT (0)
);

-- you may want a constraint or trigger to ensure
-- only one row can be active at any one time.

INSERT dbo.lookup(id, [server], [database], [table])
  SELECT 1,N'serverA',N'databaseA',N'tableA'
  UNION ALL SELECT 2,N'serverB',N'databaseB',N'tableB';

现在你的程序可以说:

UPDATE dbo.lookup SET active = 1 WHERE ... ?

您的存储过程可以是:

CREATE PROCEDURE dbo.whatever
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @sql NVARCHAR(MAX);

  SELECT @sql = N'SELECT <cols> FROM ' + QUOTENAME([server]) 
    + '.' + QUOTENAME([database]) + '.dbo.' + QUOTENAME([table])
    FROM dbo.lookup WHERE active = 1;

  EXEC sp_executesql @sql;
END
GO

我仍然不明白这一点,并且我不知道当两个不同的用户希望同时调用您的程序时您打算做什么,并且他们每个人都应该从不同的位置获得结果。

于 2012-09-23T15:58:44.950 回答
1

同意 Aaron 关于视图和函数不能使用动态 sql 的事实。

您仍然可以做的是构建一个 clr 表值函数。在那里,您可以使用 .net 代码并查询您想要的任何内容。并相应地构建您的数据并输出您需要的内容。

所以而不是像查询数据

select * from myview

你可以查询它

select * from dbo.clr_mymockupview()
于 2012-09-23T16:02:22.767 回答
1
  1. 为您的远程服务器创建同义词。
  2. 使用 UNION ALL 创建您的视图以将您的位置连接在一起。

既然您说“表”,请在 UNION ALL 之前加入您的表,并希望 MS 将远程执行 JOIN。

于 2012-09-23T16:11:46.973 回答
1

使用带有数据库、服务器和目录参数的联合查询:

Select col1, col2, <etc.>, 'table1' as tablename, 'server1' as servername, 'catalog1' as catname from server1.catalog1.table1
Union Select col1, col2, <etc.>, 'table2' as tablename, 'server2' as servername, 'catalog2' as catname from server2.catalog2.table2
Union Select col1, col2, <etc.>, 'table3' as tablename, 'server3' as servername, 'catalog3' as catname from server3.catalog3.table3

然后根据您的 3 个标准进行过滤。这可能不会很快,但会与 std. SQL。

于 2012-09-23T16:15:56.973 回答