每次我运行此查询
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
结果显示为好像是输出窗口中的几个表。
有没有办法可以将输出作为单个“表”运行?
答案 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;