如何在 Dynamic SQL (SQL Server) 中的 Select 语句中使用游标值
How to use cursor value in Select Statement within Dynamic SQL (SQL Server)
我正在尝试通过 LinkdedServers 聚合 SQL 服务器用户,但无法在我的查询中 select 数据库名称。我尝试在我的 select 语句中使用 db_name() as ''Database''
,但它使用当前数据库上下文,而不是我 select 来自的数据库。我意识到发生这种情况是因为我使用的是 "fully qualified" 数据库名称,因此数据库上下文从未真正改变过。我也无法将光标值作为我的 select 语句的一部分。
有没有人知道如何获取我 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]'
我正在尝试通过 LinkdedServers 聚合 SQL 服务器用户,但无法在我的查询中 select 数据库名称。我尝试在我的 select 语句中使用 db_name() as ''Database''
,但它使用当前数据库上下文,而不是我 select 来自的数据库。我意识到发生这种情况是因为我使用的是 "fully qualified" 数据库名称,因此数据库上下文从未真正改变过。我也无法将光标值作为我的 select 语句的一部分。
有没有人知道如何获取我 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]'