如何在动态SQL(SQL Server)中的Select语句中使用游标值

时间:2017-12-18 16:00:32

标签: sql-server cursor dynamic-sql linked-server

我正在尝试通过LinkdedServers聚合SQL Server用户,但无法在查询中选择数据库名称。我尝试使用db_name() as ''Database''在我的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'.

在这种情况下如何将变量转换为字符串?

1 个答案:

答案 0 :(得分:2)

你应该不习惯用单引号包装列别名。它们不是字符串文字,它使您的代码更难阅读。它还会在动态sql中引起很多痛苦。

下面是一个示例,说明如何在变量中捕获值并构建此字符串,而不使用那些额外的单引号。

declare @SQL nvarchar(max) = 
'SELECT  distinct (dp.name) as DatabaseUser, 
        s.name as ServerName, 
        ''' + @DatabaseName + ''' as Database, 
        getdate() as [date]'