【问题标题】:No fields for dynamic SQL stored procedure in SSRS with SET FMTONLY使用 SET FMTONLY 的 SSRS 中没有动态 SQL 存储过程的字段
【发布时间】:2014-01-29 15:02:30
【问题描述】:

我有以下 SP,它在单独运行时可以正常工作:

USE [Orders]
GO
SET FMTONLY OFF; 

CREATE PROCEDURE [dbo].[Get_Details_by_Type]

@isArchived varchar(10),
@Type varchar(50)

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    declare @sqlQuery nvarchar(max)
          IF(@isArchived = 'ALL')
            BEGIN
                set @sqlQuery  = 'SELECT *  FROM [dbo].[Orders] 
              WHERE ' + @Type + ' != € 
                ORDER BY [IDNumber]'
                exec sp_executesql @sqlQuery
            END
        ELSE
            BEGIN
            set @sqlQuery  = 'SELECT * FROM [dbo].[Orders] 
          WHERE ' + @Type + ' != € AND [isArchived] = ' + @isArchived + ' ORDER BY [IDNumber]'
            exec sp_executesql @sqlQuery
        END
END
SET FMTONLY ON; 

我遇到的问题是,当我为 SSRS 报告添加数据集时,它在“字段”部分中没有提取任何字段/列。我猜是动态 SQL 的原因?

我该如何解决?

【问题讨论】:

  • 尝试在SET NOCOUNT ON之后添加SET FMTONLY OFF;
  • 好的,我已经编辑了上面的代码以反映您的更改,但没有任何反应。我把它放在正确的地方了吗?
  • 不,你应该将它添加到 sp 中,在 SET NOCOUNT ON;987654324@ 之后(或之前)
  • 不走运。手动添加确实有效,但有很多字段:(
  • 手动将每个字段添加到 SSRS 报告中数据集的字段部分。

标签: sql sql-server stored-procedures reporting-services


【解决方案1】:

问题
包含 Dynamic Sql 和 Temp 表的存储过程是 SSRS 和 ORM 生成器(如 Linq2SQL 和 EF 逆向工程工具)等向导的祸根。

这是因为工具 SET FMTONLY ON;(或最近的 sp_describe_first_result_set)在运行 PROC 之前,为了派生 PROC 生成的结果集架构,以便生成 ReportViewer UI 的映射。但是,FMTONLY ONsp_describe_first_result 都没有实际执行 PROC。

例如该工具将执行以下操作:

SET FMTONLY ON;
EXEC dbo.MyProc NULL;

一些解决方法:

  • 手动编辑 RDL/RDLC 文件以插入实际结果集列名和类型。
  • 暂时删除 real proc 并将其替换为返回由 real proc 返回的实际数据类型和列名组成的零行或多行数据集,运行向导,然后恢复 real proc。李>
  • 暂时将SET FMTONLY OFF; 添加为PROC 中的第一行- 这将强制执行PROC。完成后恢复原始 PROC(尽管请注意,您的 proc 可能由于工具传入的 null 或虚拟参数而失败)。另外,FMTONLYbeing deprecated
  • 在 proc 的开头,添加一个虚拟语句,该语句返回结果集的实际模式,包装在一个永远不会执行的条件分支中。

这是最后一个 hack 的示例:

CREATE PROCEDURE [dbo].[Get_Details_by_Type]
  @isArchived varchar(10),
  @Type varchar(50)
AS
BEGIN
   -- For FMTONLY ON tools only
   IF 1 = 2
     BEGIN
       -- These are the actual column names and types returned by the real proc
       SELECT CAST('' AS NVARCHAR(20)) AS Col1, 
              CAST(0 AS DECIMAL(5,3)) AS Col2, ...
     END;
-- Rest of the actual PROC goes here

FMTONLY ON / sp_describe_first_result_set 被虚拟条件所愚弄,并假定来自从未执行的分支的架构。

顺便说一句,为了您自己的理智,我建议您不要在您的 PROC 中使用 SELECT * - 而是明确列出从 Orders 返回的所有真实列名

最后,请确保您的 proc 中没有包含 SET FMTONLY ON; 语句(来自您上面的代码!)

END - Proc
GO **
SET FMTONLY ON; ** This isn't part of the Proc!

【讨论】:

  • 感谢您的详细解释,我只有SELECT * 用于此示例,因为我有很多列。我可能只是手动添加此实例中的列,但将来我会尝试破解。
  • 你先生是个传奇!
  • Here's an example of the last hack: 也很好用!伟大的! +1
  • 一个陷阱:最后指出的技巧......如果你的过程中碰巧有一个动态语句和一个非动态语句,如果你不使用 SET FMTONLY OFF 你将从非动态语句中获取字段,即使它在 proc 中出现第二个,并且被包裹在一个错误的 if 语句中(如您所说,但只是指出我自己忽略的另一种情况)。
  • 那个黑客是惊人的和可怕的,我现在正在使用它。我有点不敢相信它会起作用(但我明白它为什么会起作用)
【解决方案2】:

如果有人仍然面临这个问题,我解决了与 ssrs 和动态 sql 类似的问题。

  1. 为了让 ssrs 正确映射来自 SP 的字段,
  2. 选择查询类型下的“文本”选项,
  3. 输入 SP 名称和参数,就像您从 SSMS 窗口调用它一样。 sp_YourStoredProc @Parameter1....@ParameterN
  4. 单击刷新字段按钮。
  5. 语句运行时,字段将刷新,您的矩阵将被填充。

顺便说一句,我使用的是 SQL 2012

希望这会有所帮助。

【讨论】:

  • 这在 Report Builder SQL Server 2016 中也很有效。谢谢!
【解决方案3】:

以下是我为解决该问题所做的 - SSRS 中未列出字段

  1. 原来我有存储过程;当我执行数据集时它会返回数据。但是SSRS中没有列出这些字段

  2. 我复制了存储过程的文本并将数据集设为Text 而不是Stored Procedure。参考How to: Refresh Fields for a Dataset

  3. 它产生了错误,我“忽略”了这些错误。参考The Declare cursor SQL construct or statement is not supported.

  4. 现在我验证了为 SSRS 填充的字段

  5. 现在我更新了数据集以使用我的Stored Procedure

完成上述步骤后,刷新数据集,如下所示:

【讨论】:

    【解决方案4】:

    并不是要恢复死线,而是将我们的报告从 SSRS 2005 升级到存储过程使用 openquery 的 SSRS 2016 时让我发疯。

    我们将其范围缩小到包含空值字段的报告。所以我们在存储过程的开头添加了这个:

    SET CONCAT_NULL_YIELDS_NULL OFF;
    

    这意味着我们不需要对每个字段都进行 CAST。

    【讨论】:

    • 你成就了我的一天!谢谢!!
    【解决方案5】:

    按照以下给定的步骤进行操作

    •   Delete DataSource. Create a new Data Source .
    •   Delete DataSet. Create a new DataSet .
    •   Use Query Designer. 
    •   Add valid parameter when asked  .
    •   One should get result for provided prarameters . 
        Donot click on refresh Field .
    •   Then Report parameters and Report field will appear .
    •   Now Filter criteria should work.
    

    **Add the Report field manually . It works.**
    

    如果存储过程无法检索模式数据或元数据,我们应该手动指定报告字段。

    【讨论】:

      【解决方案6】:

      这是一个非常晚的添加,但对于我们这些不熟悉 SSRS/报告设计的人来说: 请记住在 Visual Studio 的“报告数据”窗格中检查参数的顺序。它们将从上到下创建,因此顶部的参数不能依赖于底部的参数。这是我在一份报告中遇到的问题,但我收到的错误消息没有说明这一点,所以我追了几个小时试图解决它。

      【讨论】:

        【解决方案7】:

        我遇到了类似的问题。我有一些调试语句,我经常使用标志变量打开/关闭它们。

        这条线仍然影响结果,即使它没有运行 (@debug =0)

        --check your work
        if @debug =1  select @reportStartDate  RSD ,@reportEndDate 
                 , @yearStart YS, @folderStartDate  FSD, @MonthCount MC
                 , @dataStart  DataStart
        

        我通过运行带有 fmtONly 的 sp 发现了这个问题

        SET FMTONLY ON
        exec rpt_mo_DashBoard_YTD_Total  'ajax20','12/1/2019'
        

        我通过注释掉 SP 中的代码解决了这个问题。是的,现在我必须在调试时取消注释/注释每个返回语句...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-18
          • 2016-09-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-28
          • 2010-11-05
          • 2011-02-27
          • 1970-01-01
          相关资源
          最近更新 更多