【问题标题】:How to use cursor value in Select Statement within Dynamic SQL (SQL Server)如何在动态 SQL (SQL Server) 中的 Select 语句中使用游标值
【发布时间】:2018-06-01 00:13:15
【问题描述】:

我正在尝试通过 LinkdedServers 聚合 SQL Server 用户,但无法在我的查询中选择数据库名称。我尝试在我的选择语句中使用db_name() as ''Database'',但它使用当前数据库上下文,而不是我从中选择的数据库。我意识到发生这种情况是因为我使用的是“完全限定”的数据库名称,因此数据库上下文实际上从未改变。我也无法将光标值作为我的选择语句的一部分。

有人对我如何获取我选择的数据库的数据库名称有任何想法吗?

这是我的代码:

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'.

在这种情况下如何将变量变成字符串?

【问题讨论】:

  • 你有数据库名称...在变量中。而不是 db_name 使用 ' + @DatabaseName + ' 作为数据库
  • 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'。
  • 你必须把它变成一个字符串。可能只需要 '' 在字符串文字的每一侧。您可以在问题中发布您的代码吗? cmets 中的格式化很糟糕。
  • Sean Lange,我将代码添加到问题中。感谢您的观看!

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


【解决方案1】:

您应该改掉将列别名用单引号括起来的习惯。它们不是字符串文字,它使您的代码更难阅读。动态 sql 也会带来很多麻烦。

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

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

【讨论】:

  • 太棒了,非常感谢肖恩!我用双引号试过了,但现在明白为什么我需要使用三个刻度。我对 t-sql 比较陌生,并且在筛选文档以处理我的查询时遇到了麻烦。我正在构建现有代码,但将来会尽量避免这种类型的事情,因为它会让事情变得更加混乱
猜你喜欢
  • 2013-02-17
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 2014-07-10
  • 1970-01-01
  • 2017-09-26
相关资源
最近更新 更多