从具有数据库名称

时间:2015-06-15 17:05:31

标签: sql-server database tsql

您好我需要创建一个视图或存储过程,它结合数据并使用包含模式(db)名称的列从同一服务器上的3个不同数据库返回结果集。

例如,在第一个数据库中我有这个表:

CREATE TABLE [dbo].[CloudUsers](
    ID int IDENTITY(1,1) NOT NULL,
    Username nvarchar(50) NULL,
    MainDB nvarchar(100) NULL
) ON [PRIMARY]

每个CloudUser都有一个单独的数据库,所以接下来我需要使用MainDB名称从User数据库中获取数据。我需要的数据总是1行,因为我正在使用聚合函数/查询。

所以在User MainDB中假设我有这个表。

CREATE TABLE [dbo].[CLIENT](
   ID int NOT NULL,
   Name nvarchar(50) NULL,
   ProjectDBName [nvarchar](100) NULL
   CreationDate datetime NULL
) ON [PRIMARY]

我查询如下:

select min(CreationDate) from MainDB.Client

客户端的相同想法我需要从指向Client ProjectDBName的第3个数据库中获取更多数据。它再次是汇总数据:

select Count(id) as TotalTransactions from ProjectDBName.Journal

我的最终结果应该包含所有数据库的记录。这是统计数据所需的只读数据。

最终结果集示例:

CloudUsers.Username,MainDB-> CreationDate,ProjectDBName-> TotalTransaction

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

这并不容易 - 如果没有架构和示例数据,我无法给出准确的答案。

您需要遍历每个客户端,并使用dynamic SQL执行针对mainDB和projectDB连接的查询。您可以在一个巨大的“联合”查询中执行此操作,也可以通过创建临时表并将数据插入该临时表,然后从查询末尾的临时表中进行选择。

答案 1 :(得分:0)

对于那些对如何解决这个问题感到好奇的人,我找到了自己的解决方案,使用了一些游标+动态和一个简单的表变量,享受。

ALTER PROCEDURE CloudAnalysis as
DECLARE @objcursor cursor
DECLARE @innercursor cursor
DECLARE @userid int
       ,@maindb nvarchar(100)
       ,@clientid int
       ,@name nvarchar(50)
       ,@projdb nvarchar(100)
       ,@stat nvarchar(50)
       ,@sql nvarchar(max)
       ,@vsql nvarchar(max)
       ,@rowcount int


DECLARE @result table(userid int,clientid int,maindb nvarchar(100),name nvarchar(50),projdb nvarchar(100),stat nvarchar(50))

SET @objcursor =  CURSOR FORWARD_ONLY STATIC FOR SELECT c.id,c.maindb,u.client_id FROM dbo.ClientUsers c join dbo.UserClients u on c.id = u.user_id  open @objcursor

FETCH NEXT FROM @objcursor INTO @userid,@maindb,@clientid
WHILE (@@FETCH_STATUS=0)
BEGIN

IF (EXISTS (SELECT name 
FROM master.dbo.sysdatabases 
WHERE ('[' + name + ']' = @maindb 
OR name = @maindb)))
BEGIN

    set @sql = N'SELECT @name = c.name,@projdb=c.ProjectDBName FROM ' + @maindb + '.dbo.CLIENT c WHERE c.id = ' + cast(@clientid as nvarchar)


    EXECUTE sp_executesql @sql, N'@name NVARCHAR(50) OUTPUT,@projdb NVARCHAR(100) OUTPUT', 
    @name = @name OUTPUT
    ,@projdb = @projdb OUTPUT

    SELECT @rowcount = @@ROWCOUNT

    IF @rowcount > 0
    BEGIN

    --print '    client: ' + cast(@clientid as nvarchar)+
    --':' + @name + ' projdb: ' + @projdb

    IF (EXISTS (SELECT name 
    FROM master.dbo.sysdatabases 
    WHERE ('[' + name + ']' = @projdb 
    OR name = @projdb)))
    BEGIN

    SET @sql = N'SELECT @stat = j.stat FROM ' + @projdb + '.dbo.JournalTransaction j'

    EXECUTE sp_executesql @sql
    ,N'@stat NVARCHAR(50) OUTPUT'
    ,@stat = @stat OUTPUT

    END

    INSERT INTO @result (userid,clientid,maindb,name,projdb,stat)
    VALUES (@userid,@clientid,@maindb,@name,@projdb,@stat)

    END

END

FETCH NEXT FROM @objcursor INTO @userid,@maindb,@clientid


END

CLOSE @objcursor
DEALLOCATE @objcursor 

SELECT * FROM @result