我试图通过LinkdedServers聚合SQL Server用户,但我无法在查询中选择数据库名称。我尝试在我的select语句中使用db_name() as ''Database''
,但它使用当前的数据库上下文,而不是我选择的数据库。我意识到发生这种情况是因为我使用的是“完全限定”的数据库名称,因此数据库上下文永远不会实际更改。我也无法将游标值作为select语句的一部分。
有没有人对如何获取我选择的数据库的数据库名称有任何想法?
这是我的代码:
DECLARE @DatabaseName VARCHAR(30)
DECLARE c1 CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR
SELECT
Name
FROM
[LinkedServer].master.sys.databases
WHERE
Name NOT IN (
'master',
'model',
'tempdb',
'msdb',
'distribution',
)
OPEN c1
FETCH NEXT FROM c1
INTO @DatabaseName
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC (
'
--INSERT INTO [Gather_Privileged_DBUsers_Sox]
SELECT distinct (dp.name) as ''DatabaseUser'',
s.name as ''ServerName'',
db_name() as ''Database'',
getdate() as ''date''
FROM [LinkedServer].[' + @DatabaseName + '].sys.database_role_members drm
JOIN [LinkedServer].[' + @DatabaseName + '].sys.database_principals dp
ON drm.member_principal_id = dp.principal_id
JOIN [LinkedServer].[' + @DatabaseName + '].sys.database_principals dp2
ON drm.role_principal_id = dp2.principal_id
JOIN [LinkedServer].[master].[sys].[servers] s on 1=1
WHERE
dp2.name in
(''db_owner'',''db_accessadmin'',''db_securityadmin'',''db_ddladmin'')
AND s.server_id = 0
AND dp.name not in (''dbo'')
AND dp.type != ''R''
')
FETCH NEXT FROM c1
INTO @DatabaseName
END
CLOSE c1;
DEALLOCATE c1;
GO
尝试使用变量值:
SELECT distinct (dp.name) as ''DatabaseUser'',
s.name as ''ServerName'',
' + @DatabaseName + ' as ''Database'',
getdate() as ''date''
当我这样做时,我收到以下错误:Msg 207, Level 16, State 1, Line 5
Invalid column name 'myTestDatabase'.
在这种情况下,如何将变量转换为字符串?
你应该不习惯用单引号包装列别名。它们不是字符串文字,它使您的代码更难阅读。它还会导致动态sql带来很多痛苦。
下面是一个示例,说明如何捕获变量中的值并构建此字符串,而不使用那些额外的单引号。
declare @SQL nvarchar(max) =
'SELECT distinct (dp.name) as DatabaseUser,
s.name as ServerName,
''' + @DatabaseName + ''' as Database,
getdate() as [date]'