如何将结果放在单个“表”中

时间:2017-05-15 13:36:37

标签: sql-server tsql

每次我运行此查询

Declare @name varchar(100)
Declare @sqlstatement nvarchar(4000)
--move declare cursor into sql to be executed
Declare users_cursor CURSOR FOR Select name from sys.databases where 
database_id > 4
declare @bdname varchar(100)
declare @test varchar(100)
set @test ='myserver'
--declare  @listagem table(ServerName  varchar(100),DatabaseName  
varchar(100), UserName  varchar(100), [UserRole]  varchar(100))


OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
print 'Database ' + @name

set @bdname = @name 
set @sqlstatement = N'use ' + @name +' '+char(13)+N' select '''+ @test +''', ''' + @bdname +''',
convert(char(30),dp2.name), convert(char(20),dp.name)  
FROM sys.database_principals dp
INNER JOIN sys.database_role_members drm ON dp.principal_id = 
drm.role_principal_id
INNER JOIN sys.database_principals dp2 ON drm.member_principal_id = 
dp2.principal_id
WHERE dp2.principal_id > 4 AND dp2.type <>'+'''R'''


exec sp_executesql @sqlstatement

FETCH NEXT FROM users_cursor -- have to fetch again within loop
INTO @name
END
CLOSE users_cursor
DEALLOCATE users_cursor
END

结果显示为好像是输出窗口中的几个表。

有没有办法可以将输出作为单个“表”运行?

2 个答案:

答案 0 :(得分:0)

我就是这样做的。

DECLARE @name VARCHAR(100);
DECLARE @sqlstatement NVARCHAR(4000);
--move declare cursor into sql to be executed
DECLARE users_cursor CURSOR
FOR SELECT name
    FROM sys.databases
    WHERE database_id > 4;
DECLARE @bdname VARCHAR(100);
DECLARE @test VARCHAR(100);
SET @test = 'myserver';
DECLARE @listagem TABLE
(ServerName   VARCHAR(100),
 DatabaseName VARCHAR(100),
 UserName     VARCHAR(100),
 [UserRole]   VARCHAR(100)
);
OPEN users_cursor;
FETCH NEXT FROM users_cursor INTO @name;
WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT 'Database '+@name;
        SET @bdname = @name;
        SET @sqlstatement = N'use '+@name+' '+CHAR(13)+N' select '''+@test+''', '''+@bdname+''',
convert(char(30),dp2.name), convert(char(20),dp.name)  
FROM sys.database_principals dp
INNER JOIN sys.database_role_members drm ON dp.principal_id = 
drm.role_principal_id
INNER JOIN sys.database_principals dp2 ON drm.member_principal_id = 
dp2.principal_id
WHERE dp2.principal_id > 4 AND dp2.type <>'+'''R''';
        INSERT INTO @listagem
        EXEC sp_executesql
             @sqlstatement; 
        FETCH NEXT FROM users_cursor -- have to fetch again within loop
        INTO @name;
    END;
CLOSE users_cursor;
DEALLOCATE users_cursor;
SELECT *
FROM @listagem;

你实际上非常接近解决方案。

使用您声明的表:

DECLARE @listagem TABLE
    (ServerName   VARCHAR(100),
     DatabaseName VARCHAR(100),
     UserName     VARCHAR(100),
     [UserRole]   VARCHAR(100)
    );

并简单地将循环的每个迭代中返回的结果插入到表中,如下所示:

INSERT INTO @listagem
    EXEC sp_executesql
         @sqlstatement;

然后只需从光标外的表中选择:

SELECT *
FROM @listagem;

答案 1 :(得分:0)

这适用于SQL Server 2012及更高版本。如果您需要SQL Server 2008,那么我将不得不编辑以不使用CONCAT()函数,除非您能够找出差异。这将返回所有数据库的所有数据库主体及其附带的数据库角色。请记住,不在数据库级别(sysadmin)的任何权限都不会显示在此查询中。

DECLARE @sqlStatement NVARCHAR(MAX) = '';

SELECT @sqlStatement +=
CONCAT
(
        'SELECT ''',[name],'''
        ,CONVERT(CHAR(30),DP.[name]) AS DatabasePrincipal
        ,CONVERT(CHAR(20),DR.[name]) AS DatabaseRole
    FROM [',[name],'].sys.database_principals AS DP
        LEFT JOIN [',[name],'].sys.database_role_members AS DRM
            ON DP.principal_id = DRM.member_principal_id
        LEFT JOIN [',[name],'].sys.database_principals AS DR
            ON DRM.role_principal_id = DR.principal_id
    WHERE DR.[name] IS NOT NULL
    UNION ALL
    '
)
FROM sys.databases
;

SET @sqlStatement = LEFT(@sqlStatement,LEN(@sqlStatement)-12);

EXEC sp_executeSQL @sqlStatement;