web-dev-qa-db-ja.com

SSRS-カンマ区切りの文字列を使用して複数の値パラメーターをストアドプロシージャに渡す際のエラー番号:7357

特定のサーバー上の一連のデータベースのログイン権限を表示するSSRSレポートに取り組んでいます。

サーバー、ログイン、データベースはすべてパラメーターです。 NULLはそれらすべてを示します(ログインおよびDBS)サーバー-1つのみ-指定する必要があります。

プロシージャは、COMMA DELIMITED STRINGとしてプロシージャに渡す複数のパラメータを受け入れます。ここが間違いだと思います。

レポートには、提供されたログインのリストと提供されたDBのリストのパーミッションのみをリストする必要があります。

これは、ストアドプロシージャに渡されるパラメーターを収集するレポートの画像です。

enter image description here

以下に示すように、ストアドプロシージャはレポート内から実行されます。さらに、ストアドプロシージャの出力を含む画像の下にも実行されます。

exec bsp_GetServerDBRoles 
@SERVER=N'my server\instance',
@LOGINS=NULL,
@DBS='master'

enter image description here

これで、以下に、私のストアドプロシージャのコードが表示されます。

PRINT 'THE SERVER IS ' + @@SERVERNAME
--select db_name()
PRINT 'THE DATABASE IS ' + db_NAME() 
PRINT ''
GO

USE [Monitoring]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
BEGIN TRY
    PRINT  @@SERVERNAME
    PRINT  DB_NAME()
    PRINT 'PROCEDURE bsp_GetServerDBRoles'
    DROP PROCEDURE bsp_GetServerDBRoles
    print 'dropped PROCEDURE bsp_GetServerDBRoles'
END TRY
BEGIN CATCH
END CATCH
GO

CREATE PROCEDURE bsp_GetServerDBRoles
     @SERVER NVARCHAR(128),
     @LOGINS NVARCHAR(MAX)=NULL,
     @DBS NVARCHAR(MAX)=NULL
    WITH EXECUTE AS OWNER, ENCRYPTION
AS
/*
=======================================================================
Script  :   bsp_GetServerDBRoles
Author  :   Marcelo Miorelli
Date    :   5-May-2015

Desc    :   this procedure shows the database names on a specific server

            it needs @SERVER to be a linked server with enabled data access in the current server.
Usage   :  

            exec bsp_GetServerDBRoles @SERVER=N'my server/instance',@LOGINS=N'my login',@DBS=N'AppFabric'
            go

             exec bsp_GetServerDBRoles 'my server'

            SELECT * FROM OPENQUERY([my server\instsqlweb1],'SET FMTONLY OFF;SET NOCOUNT ON; exec sp_GetServerDBRoles ''UKStock,US15AUTPProduct''')
            --================================================================
            -- using a temp table to store the results
            --================================================================


            BEGIN TRY 

               DROP TABLE #Radhe

            END TRY
            BEGIN CATCH
            END CATCH



            CREATE TABLE #Radhe(
                [DB_Name] [nvarchar](128) NULL
            )

            --==================================================================================
            --this way it does not work -- An INSERT EXEC statement cannot be nested.
            -- see the links below

            --INSERT INTO #Radhe
            --exec sp_GetServerLogins
            --==================================================================================

            -- and if you get the error below:
            -- Server 'SQLSALON1\STOCKALLOCATION' is not configured for DATA ACCESS

            --select @@servername

            -- get this done first:
                --EXEC sp_serveroption @server = @@servername
                --                  ,@optname =  'data access'     
                --                  ,@optvalue =  'TRUE'

                declare @sql nvarchar(max)
                select @sql = 'SELECT 
                                        [DB_Name]
                                 FROM OPENQUERY(' + quotename(@@servername) + ',' + '''' + 'SET FMTONLY OFF; exec monitoring.dbo.bsp_GetServerDBRoles ' + '''' + '''' + 'SQLREPLON1\REP' + ''''  + '''' + '''' + ')'

                --print ( @sql)
                INSERT INTO #Radhe
                exec ( @sql)

                select
                    [DB_Name]
                from #Radhe

Links   :

=======================================================================

Vritasura talking to Indra:

SB 6.12.14: Since everything is dependent on the supreme will of the Personality of Godhead, 
            one should be equipoised in fame and defamation, 
            victory and defeat, life and death. 
            In their effects, 
            represented as happiness and distress, 
            one should maintain oneself in equilibrium, without anxiety.

SB 6.12.15: One who knows that the three qualities — goodness, passion and ignorance — 
            are not qualities of the soul but qualities of material nature, 
            and who knows that the pure soul is simply an observer of the actions and reactions of these qualities, 
            should be understood to be a liberated person. 
            He is not bound by these qualities.
=======================================================================
History
Date             Action        User                Desc
-----------------------------------------------------------------------
05-May-2015     created       Marcelo Miorelli


=======================================================================
*/
SET NOCOUNT ON
SET XACT_ABORT ON
SET DEADLOCK_PRIORITY NORMAL;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DECLARE @I INT
       ,@Z INT
       ,@LOGIN nvarchar(128)

    DECLARE @sql NVARCHAR(MAX)

    DECLARE  @log NVARCHAR(MAX)
            ,@vCrlf CHAR(2);

    SELECT  @log = ''
           ,@vCrlf = CHAR(13)+CHAR(10);

SELECT @SERVER = COALESCE(UPPER(LTRIM(RTRIM(@SERVER))),@@SERVERNAME)

IF NOT EXISTS(
                SELECT * 
                  FROM SYS.SERVERS
                  WHERE NAME = @SERVER
                    AND PROVIDER = 'SQLNCLI'
                    AND is_data_access_enabled = 1
) BEGIN

           SELECT @SQL = 'The server called %s cound not be found, or does not have data access enabled.' + @vCrlf + @vCrlf +
                         'bsp_GetServerDBRoles usage:' + @vCrlf +
                         'bsp_GetServerDBRoles @Server sysname' + @vCrlf +
                         'Example:' + @vCrlf +
                         'bsp_GetServerDBRoles ''sqlreplon1\rep''' + @vCrlf

           RAISERROR(@SQL ,16,1,@SERVER)
           RETURN (-1)


END 


BEGIN TRY

            --==================================================================================

            -- and if you get the error below:
            -- Server 'SQLSALON1\STOCKALLOCATION' is not configured for DATA ACCESS

            -- get this done first:
                --EXEC sp_serveroption @server = @SERVER 
                --                  ,@optname =  'data access'     
                --                  ,@optvalue =  'TRUE'

                --DECLARE @Radhe TABLE (
                --  db nvarchar(128)          NULL,
                --  login_ nvarchar(128)      NULL,
                --  role_ nvarchar(128)       NULL,
                --  Obj nvarchar(517)         NULL,
                --  Permission nvarchar(128)  NULL,
                --  script nvarchar(588)      NULL
                --) 

                SELECT @DBS    = CASE WHEN LEN(LTRIM(RTRIM(@DBS))) < 1    THEN NULL ELSE LTRIM(RTRIM(@DBS)) END
                SELECT @LOGINS = CASE WHEN LEN(LTRIM(RTRIM(@LOGINS))) < 1 THEN NULL ELSE LTRIM(RTRIM(@LOGINS)) END

                select @sql = 'SELECT 
                                       [name]
                                      ,[Type_Desc]
                                      ,[The_Server_Roles]
                                      ,[List_of_Groups_Login_belong_to]
                                      ,[dbname]
                                      ,[modify_date]
                                      ,[Permissions_user]
                                 FROM OPENQUERY(' + quotename(@SERVER) + ','  + '''' + 'SET FMTONLY OFF;SET NOCOUNT ON; exec sp_GetServerDBRoles ' + 
                                 CASE WHEN @DBS IS NULL THEN 'NULL' 
                                                        ELSE '''' +  '''' + @DBS  + ''''  + ''''
                                  END + ',' +  
                                 CASE WHEN @LOGINS IS NULL THEN 'NULL'
                                                          ELSE  '''' + '''' + @LOGINS + ''''  + ''''
                                  END  + '''' + ')'

                print @sql

                exec ( @sql)


        RETURN (0)

END TRY
BEGIN CATCH

        PRINT '--EXCEPTION WAS CAUGHT--' + CHAR(13) +
              'THE ERROR NUMBER:' + COALESCE(CAST ( ERROR_NUMBER()  AS VARCHAR), 'NO INFO') + CHAR(13) 

        PRINT 'SEVERITY: '        + COALESCE(CAST ( ERROR_SEVERITY()  AS VARCHAR), 'NO INFO') + CHAR(13) +
              'STATE: '           + COALESCE(CAST ( ERROR_STATE() AS VARCHAR), 'NO INFO')  + CHAR(13) 

        PRINT 'PROCEDURE: '       + COALESCE(CAST ( COALESCE(ERROR_PROCEDURE(),'NO INFO')  AS VARCHAR), 'NO INFO') + CHAR(13) +
              'LINE NUMBER: '     + COALESCE(CAST ( ERROR_LINE() AS VARCHAR), 'NO INFO')  + CHAR(13) 

        PRINT 'ERROR MESSAGE: '
        PRINT  CAST ( COALESCE(ERROR_MESSAGE(),'NO INFO')   AS NTEXT)
        RETURN (-1)

END CATCH;


  ------------------------------------
  GO
  ------------------------------------
  print 'created PROCEDURE bsp_GetServerDBRoles'
GO
--  exec sys.sp_MS_marksystemobject 'bsp_GetServerDBRoles'
--GO

問題は

以下に示すようにストアドプロシージャを呼び出すと、例外が発生します。

exec bsp_GetServerDBRoles 
@SERVER=N'my server\instance'
the list of my logins'

例外は次のとおりです。

--EXCEPTION WAS CAUGHT--
THE ERROR NUMBER:7357

SEVERITY: 16
STATE: 2

PROCEDURE: NO INFO
LINE NUMBER: 1

ERROR MESSAGE: 
Cannot process the object "SET FMTONLY OFF;SET NOCOUNT ON; exec sp_GetServerDBRoles 'the list of my logins ...

レポートが呼び出すプロシージャは、SQLMON1と呼ばれる監視サーバーにあります。そこから、LINKED SERVERSを介して、パラメーターとして渡されたサーバーに移動し、必要なデータを返すローカルストアドプロシージャがあります。

質問:

カンマ区切りの文字列の代わりにテーブルタイプを使用することは、このための良い解決策でしょうか?

監視するサーバーごとにこのテーブルタイプを作成する必要があります。

これは客観的な質問ではないことを理解しています。

4

ここでの問題は、SSRSパラメーターが値を返す方法です。

たとえば、bsp_GetServerDBRolesストアドプロシージャを実行しようとしたとき(デモでは@Loginパラメータが長すぎるため、スキップしました):

 exec bsp_GetServerDBRoles 
 @SERVER=N'my server'
,@DBS=N'UK15AUTMProduct,UK15SUMMProduct,UK15SUMSProduct,UK15WINPProduct'

@DBSで予期される値の形式は次のとおりです。

'UK15AUTMProduct','UK15SUMMProduct','UK15SUMSProduct','UK15WINPProduct'

しかし、ssrsパラメータ@DBSは以下の形式で複数の値を返すため、クエリは失敗します。

UK15AUTMProduct,UK15SUMMProduct,UK15SUMSProduct,UK15WINPProduct

これを解決するには、ストアドプロシージャで新しい変数を宣言するには、@DBSNEWを想定し、その値を次のように設定します。

SET @DBSNEW = REPLACE(@DBS,',',''',''')

これにより、以下に示すように、SSRS @DBSパラメータから返される値が変わります。

UK15AUTMProduct','UK15SUMMProduct','UK15SUMSProduct','UK15WINPProduct

これで、引用符が最初と最後に欠けているため、動的選択クエリのwhere句で@DBSNEW変数を('''+@DBSNEW+''')として使用します。お役に立てれば。

1
Shivam Kumar