我想要一个程序访问一个表/视图/存储过程等(实现的东西,我们称之为X ),它抽象出三个基本表中包含的数据的真实位置(表在所有位置都有相同的定义。)
我希望 X 从某个地方(可能是一个表)获取服务器名称,目录名称和表名,并访问特定的三个基本表。 X 的调用者不知道调用了哪些特定的表。
如何在SQL Server(2008)中执行此操作?
答案 0 :(得分:2)
与函数一样,视图不能使用动态SQL - 它无法在某处找到某些元数据引用并进行相应调整。
我认为最接近你想要的是synonym。假设您有三个不同的数据库A
,B
和C
。在A
中,您希望视图引用的表格为dbo.foo
,B
为dbo.bar
,C
为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
我仍然不明白这一点,当两个不同的用户希望同时调用你的程序时,我不知道你打算做什么,他们每个人都应该从不同的位置获得结果。
答案 1 :(得分:1)
同意Aaron关于视图和函数不能使用动态sql的事实。
你还能做的是建立一个clr表值函数。在那里你可以使用.net代码并查询你想要的任何内容。并相应地构建数据并输出您需要的数据。
所以不要像
那样查询数据select * from myview
你可以查询它
select * from dbo.clr_mymockupview()
答案 2 :(得分:1)
由于您说过“表格”,请在UNION ALL之前加入您的表格,希望MS能够远程执行JOIN。
答案 3 :(得分: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。