当前位置: 首页 > 面试题库 >

使用SET FMTONLY的SSRS中没有用于动态SQL存储过程的字段

谢俊英
2023-03-14
问题内容

我有以下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引起的吗?

我该如何解决?


问题答案:

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

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

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

SET FMTONLY ON;
EXEC dbo.MyProc NULL;

一些解决方法:

  • 手动编辑RDL / RDLC文件以插入实际结果集的列名称和类型。
  • 临时删除实际proc并将其替换为一个,它将返回零个或更多行的数据集,其中包含实际proc返回的实际数据类型和列名,并运行向导,然后还原真实proc。
  • 临时添加SET FMTONLY OFF;为PROC的第一行-这将强制执行PROC。完成后还原原始的PROC(尽管请注意,由于该工具传递的null或哑元参数,您的proc可能会失败)。此外,FMTONLY在被弃用
  • 在proc的开始处,添加一个伪语句,该语句返回结果集的实际模式,并包装在一个永远不会执行的条件分支中。

这是最近一次黑客攻击的示例:

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由虚拟条件欺骗,并采用从未执行的分支中的架构

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

最后,只需确保您没有SET FMTONLY ON;在proc中包含该语句(从上面的代码中即可!)

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


 类似资料:
  • 问题内容: 我有一个具有应用程序角色的数据库。角色成员都属于Active Directory中的组。我没有给角色授予从表中进行选择的权限,而是给角色赋予了对它需要调用的所有存储过程的执行权限。 除了我的存储过程之一,该过程可以建立一些动态SQL并调用sp_executesql之外,其他方法都可以正常工作。 动态sql看起来像这样: 具有此角色的用户无法调用存储过程。它给出了以下错误,这是我所预期的

  • 问题内容: 如何在MySQL存储过程中构建和使用动态SQL? 问题答案: 我不相信MySQL支持动态sql。您可以执行类似但不同的“准备”语句。 这是一个例子: 准备好的语句通常用于查看给定查询的执行计划。由于它们是使用 execute 命令执行的,并且可以将 sql 分配给变量,因此您可以近似地估计一些与动态sql相同的行为。 这是一个很好的链接: 不要忘记使用最后一行取消分配! 祝好运!

  • 问题内容: 我正在尝试将LIKE关键字与%通配符一起包装参数,但是我不确定如何在不破坏它的情况下将%字符放入语句中。现在我有: 我的.net应用程序中出现SqlException错误,提示“运行时’@search’附近语法不正确。如果删除@search参数周围的%字符,该错误就会消失。 问题答案: %字符必须 在 搜索字符串中… 请注意,以下内容也可以使用,但会引入潜在的SQL注入漏洞…

  • 问题内容: 我正在编写一个存储过程,需要在该过程中动态构造一个SQL语句以引用传入的表名。 我需要让该SQL语句返回结果,然后可以在整个过程的其余部分中使用它。 我已经尝试过使用临时表和其他所有东西,但是我不断收到一条消息,我需要声明变量等。 例如: 或者… 无论如何,有没有这样做而不使用实际表? 谢谢。 问题答案: 您是否尝试过类似的方法: 您需要确保将nvarchar字符串加N作为前缀,例如。

  • 问题内容: 我已经查看了与该问题相关的Stack Overflow上的其他问题,但是似乎没有一个问题能清楚地回答这个问题。 我们有一个名为sp_who2的系统存储过程,该过程为服务器上所有正在运行的进程返回信息的结果集。我想过滤存储过程返回的数据;从概念上讲,我可能会这样做: 但是,该方法不起作用。有什么好的做法可以实现查询存储过程的返回数据的目标,最好无需查看原始存储过程的代码并对其进行修改。

  • 问题内容: 我在存储过程中创建一个动态查询。我的存储过程如下: 当我尝试通过以下调用运行它时: 我收到以下错误消息: 错误代码:1054。“ where子句”中的未知列“ SPA” 我在没有where条件的情况下进行了测试,并且工作正常,但是在where条件不起作用的情况下,我尝试使用@和变量名一起使用,但仍然无法正常工作。 谢谢你的帮助。 问题答案: 您错过了条款中的引号。 尝试这样: 说明 :