【问题标题】:How to capture the result set of a stored procedure with a dynamic Select (sp_executesql) in a RDLC report如何在 RDLC 报告中使用动态选择 (sp_executesql) 捕获存储过程的结果集
【发布时间】:2019-05-29 07:54:13
【问题描述】:

我需要能够获得将生成具有动态查询(sp_executesql)的存储过程的结果集,问题是在定义DataSource时,在这种情况下将是存储过程,它不会从DataSource 向导返回任何列作为结果。

我有另一个报告 (rdlc),具有 DataSource 的存储过程不是返回结果集的动态查询。

我正在考虑能够捕获解决变量 (@instruction) 中的 sp_executesql 的指令,然后从 TableAdapter 的查询配置向导中将其作为 Select 再次执行。

ALTER PROCEDURE dbo.StoredProcedureA 
    @xmlParameter XML 
AS
BEGIN
    SET NOCOUNT ON 

    DECLARE @DespachoR  VARCHAR(100),
    @DespachoRBEsta TINYINT,
    @PaisOrigenR VARCHAR(100),
    @PaisOrigenBEsta TINYINT,
    @Estampilla INTEGER,
    @DesdeFecha VARCHAR(10),
    @HastaFecha VARCHAR(10),
    @desfecha datetime,
    @hasfecha datetime,
    @strWhereRan VARCHAR(MAX),
    @strWhere VARCHAR(MAX),


    @seteos nvarchar(200),
    @instruccion nvarchar(max),
    @instruccion2 nvarchar(max),
    @texto varchar(max),
    @columna varchar(100),
    @tipodato varchar(50)


    If @xmlParametros is not null
    begin

DECLARE @xml TABLE ( identidad integer IDENTITY (1,1) not null, tipo char(1) not null, columna varchar(30) not null, campoxml varchar(1000) not null, 
    tipodato varchar(50) not null, nulo tinyint null)

INSERT @xml (columna, tipo, campoxml, tipodato, nulo)


SELECT '@DespachoR', 'E', '(/Parameters/DESPACHOR/text())[1]', 'varchar(100)', null 
UNION ALL
SELECT '@DespachoRBEsta', 'E', '(/Parameters/DESPACHORBESTA/text())[1]', 'tinyint', null 
UNION ALL
SELECT '@PaisOrigenR', 'E', '(/Parameters/PAISORIGENR/text())[1]', 'varchar(100)', null 
UNION ALL
SELECT '@PaisOrigenBEsta', 'E', '(/Parameters/PAISORIGENRBESTA/text())[1]', 'tinyint', null 
UNION ALL
SELECT '@Estampilla', 'E', '(/Parameters/ESTAMPILLA/text())[1]', 'integer', null 
UNION ALL
SELECT '@DesdeFecha', 'E', '(/Parameters/DESDEFECHA/text())[1]', 'varchar(10)', null 
UNION ALL
SELECT '@HastaFecha', 'E', '(/Parameters/HASTAFECHA/text())[1]', 'varchar(10)', null 


SELECT @seteos = 'SET ANSI_NULLS ON
        SET QUOTED_IDENTIFIER ON
        SET CONCAT_NULL_YIELDS_NULL ON
        SET ANSI_PADDING ON
        SET ANSI_WARNINGS ON
        SET ARITHABORT ON
        SET NUMERIC_ROUNDABORT OFF '
select @instruccion =null, @instruccion2 = N'@xmlParametros xml'

DECLARE INSTRUCCION INSENSITIVE CURSOR FOR
SELECT columna, "@xmlParametros.value('" + campoxml + "', '" + tipodato + "')", tipodato
FROM @xml
WHERE tipo='E'
ORDER BY identidad  

OPEN INSTRUCCION
FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato

WHILE (@@FETCH_STATUS <> -1)
 begin
    If @instruccion is not null
        SELECT @instruccion  = @instruccion + ', '

    SELECT @instruccion  = @instruccion + @columna + '=' + @texto, @instruccion2 = @instruccion2 + ', ' + @columna + ' ' + @tipodato + ' OUTPUT'

    FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato
 end

CLOSE INSTRUCCION
DEALLOCATE INSTRUCCION

SELECT @instruccion = @seteos + N'SELECT ' + @instruccion 

--end
                    --@instruccion: SETEOS
exec sp_executesql  @instruccion, @instruccion2,@xmlParametros=@xmlParametros, @DespachoR=@DespachoR OUTPUT,
                    @DespachoRBEsta=@DespachoRBEsta OUTPUT, @PaisOrigenR=@PaisOrigenR OUTPUT, @PaisOrigenBEsta=@PaisOrigenBEsta OUTPUT, @Estampilla=@Estampilla OUTPUT,
                    @DesdeFecha=@DesdeFecha OUTPUT, @HastaFecha=@HastaFecha OUTPUT

IF @DespachoR is not null
 begin
    EXEC sp_armo_rango @DespachoR, 'D.Despacho', @DespachoRBEsta, 0, @strWhereRan OUTPUT

    IF @strWhereRan is not null
        Set @strWhere = @strWhere + " AND " + rtrim(@strWhereRan)


 end

IF @PaisOrigenR is not null
begin
     EXEC sp_armo_rango @PaisOrigenR, 'D.Paisorigen', @PaisOrigenBEsta, 0, @strWhereRan OUTPUT
     IF @strWhereRan is not null
          Set  @strWhere  =  @strWhere  + " AND " + rtrim(@strWhereRan)
end

IF @Estampilla is not null
     --Esto determina que se listen los despachos que tienen la estampilla indicada, los despachos así determinados se listan completos, 
     --es decir, con todos los rangos de estampillas.
     Set @strWhere = @strWhere + ' AND 0<>(SELECT count(*) FROM Despachosestampillas De1 (nolock)
                          WHERE     De1.Despacho=D.Despacho AND 
                               De1.Hasta >=@estampilla AND De1.Desde <= @estampilla )'

IF @DesdeFecha is not null
begin
    select @desfecha=convert(datetime, @desdefecha, 103)

     Set  @strWhere  =  @strWhere  + ' AND  D.Fecha >=@desfecha'
 end

IF @HastaFecha is not NULL
    begin
    select @hasfecha=convert(datetime, @HastaFecha, 103)

     Set @strWhere = @strWhere + ' AND  D.Fecha <=@hasfecha'
 end


Set @instruccion  = N'SELECT D.Despacho, D.Fecha as FechaD, D.Aduana, D.Paisorigen as Pais, D.Garantia, 
                CASE WHEN D.TipoGarantia="E" THEN "Efectivo" 
                     WHEN D.TipoGarantia="C" THEN "Caución" 
                     WHEN D.TipoGarantia="M" THEN "Mixto" 
                     ELSE null END as Tipo, 
                D.Efectivo, D.FechaGarantia as Fecha, D.Compania, D.Poliza, D.FechavtoGarantia as Fechavto, D.Monto as Importe, 
                De.Desde, De.Hasta, convert(varchar(254), D.Observacion) as Observacion 
          FROM Despachos D (nolock)
                LEFT JOIN Despachosestampillas De (nolock) ON D.Despacho=De.Despacho
          WHERE 1=1 ' +  @strWhere + '
          ORDER BY D.Despacho, De.Desde'


          exec sp_executesql    @instruccion, N'@estampilla integer, @desfecha datetime, @hasfecha datetime', @estampilla=@estampilla, @desfecha=@desfecha, @hasfecha=@hasfecha


    end



    END

ALTER PROCEDURE dbo.StoredProcedureB    
    @xmlParametros XML
AS
BEGIN
    SET NOCOUNT ON;
    SET CONCAT_NULL_YIELDS_NULL OFF
    SET ANSI_NULLS OFF
    SET QUOTED_IDENTIFIER OFF
    SET NOCOUNT ON

    DECLARE @Sistema CHAR(1),
@Caratula tinyint,
@FormatoQRP VARCHAR(12),

@seteos NVARCHAR(200),
@instruccion NVARCHAR(max),
@instruccion2 NVARCHAR(max),
@texto VARCHAR(max),
@columna VARCHAR(100),
@tipodato VARCHAR(50)

IF @xmlParametros is not null
 BEGIN

    DECLARE @xml TABLE ( identidad integer IDENTITY (1,1) not null, tipo char(1) not null, columna varchar(30) not null, campoxml varchar(1000) not null, 
        tipodato varchar(50) not null, nulo tinyint null)

    INSERT @xml (columna, tipo, campoxml, tipodato, nulo)

    --      PARAMETRO    DIF      RUTA_DEL_NODO                         TIPO_DATO_NODO  NULO

    SELECT '@Sistema', 'E', '(/Parameters/SISTEMA)[1]', 'char(1)', null 
    UNION ALL
    SELECT '@Caratula', 'E', '(/Parameters/CARATULA)[1]', 'tinyint', null 
    UNION ALL
    SELECT '@FormatoQRP', 'E', '(/Parameters/FORMATOQRP)[1]', 'varchar(12)', null 
    --SELECT*FROM @xml

    --SETEOS SUMADOS A LA INSTRUCCION GRAL.
    SELECT @seteos = 'SET ANSI_NULLS ON
            SET QUOTED_IDENTIFIER ON
            SET CONCAT_NULL_YIELDS_NULL ON
            SET ANSI_PADDING ON
            SET ANSI_WARNINGS ON
            SET ARITHABORT ON
            SET NUMERIC_ROUNDABORT OFF '
    select @instruccion =null, @instruccion2 = N'@xmlParametros xml'

    --DECLARA CURSOR PARA RECORRER TABLA DECLARADA
    DECLARE INSTRUCCION INSENSITIVE CURSOR FOR
    SELECT columna, "@xmlParametros.value('" + campoxml + "', '" + tipodato + "')", tipodato
    FROM @xml
    WHERE tipo='E'
    ORDER BY identidad  

    OPEN INSTRUCCION
    FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato

    WHILE (@@FETCH_STATUS <> -1)
     BEGIN
        If @instruccion is not null
            SELECT @instruccion  = @instruccion + ', '

        SELECT @instruccion  = @instruccion + @columna + '=' + @texto, @instruccion2 = @instruccion2 + ', ' + @columna + ' ' + @tipodato + ' OUTPUT'

        FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato
     END

    CLOSE INSTRUCCION
    DEALLOCATE INSTRUCCION

    SELECT @instruccion = @seteos + N'SELECT ' + @instruccion 


    exec sp_executesql  @instruccion, @instruccion2,@xmlParametros=@xmlParametros,
                        @Sistema=@Sistema OUTPUT, @Caratula=@Caratula OUTPUT,
                        @FormatoQRP=@FormatoQRP OUTPUT
 END


IF @Sistema != 'C'
    SELECT CENPREFI, CODCEN, NOMBRE, ADMNEGOCIOS
    FROM dbo.CENTROSAP  (NOLOCK)
    ORDER BY CENPREFI
ELSE
    SELECT CENPREFI, CODCEN, NOMBRE
    FROM dbo.CENTROSAP  (NOLOCK)
    ORDER BY CENPREFI
END

需要在这两种情况下获取结果集以提供 RDLC 报告中定义的DataSource。

非常感谢!

【问题讨论】:

  • 尝试在查询中添加“USE DataBaseName”。服务器可以有多个数据库,并且报表管理器不知道要查询哪个数据库。 RDLC(是文本,可以用记事本打开)文件有一个带有 CommandText 的标签,您可以将命令文本放入 SSMS 中进行测试并确保它返回结果。大于号和小于号分别是html>和 <并且需要在 SSMS 中替换。
  • 好!在 CommandText 标记中为我指示了以下相同的图: / * Local Query * / CommandText> 关于大于和小于的符号,我无法理解您的指示。
  • html 包含字符“”的元素名称到内部文本不能包含这两个字符。所以你使用的 html 的内部文本 '>'而不是大于号和'<'而不是小于号。内部文本应该是您在 cmets 中放入的内容 "/* Local Query */ 我假设有一个真正的 SELECT 语句而不仅仅是 cmets。
  • 这里添加我正在使用的 SP 的完整代码,以便为我带来结果集。正如我所指出的,不便之处在于,当我将数据集添加到 rdlc 报告时,它并没有给我任何回报。
  • 我会在查询中添加一个“USE”以确保它使用的是正确的数据库。我会检查日志文件以查看数据库是否报告了任何错误。我也会尝试确定是否正在调用这些程序。您可以创建一个用于调试的视图并将写入添加到视图中,这样您就可以判断程序是否运行以及代码执行了多远。

标签: c sql-server rdlc sp-executesql


【解决方案1】:

WITH RESULT SETS 选项可用于在输入参数未返回任何结果时为存储过程定义元数据。通过这样做,您将定义将用于结果的列,并且无论使用什么参数,报告中都会有正在使用的列。下面是一个例子。另外,NOLOCK 提示是否必要?这可能会导致结果不一致。

EXEC YourDatabase.YourSchema.YourSP @ParameterName
WITH RESULT SETS 
(
  (
    ColumnA INT,
    ColumnB VARCHAR(100),
    ColumnC VARCHAR(100)
  )
)

【讨论】:

  • @NHCives 我不太明白你的评论。这解决了您的问题吗?
  • 下午好!我不认为问题出在组成 ResultSet 的每一列的数据类型上,而是它没有将存储过程识别为返回行的对象,就好像 SP 的情况具有“选择”
  • WITH RESULT SETS 选项定义返回的列。包含数据类型以关联正确的元数据。这类似于定义“选择”将包含哪些列。
【解决方案2】:

我刚刚生成了连接、sql 命令和数据适配器来获取结果集。你能告诉我是否可以吗:

SqlConnection conexionSQL = new SqlConnection("Data Source=SRVDESARROLLO7\\BASCS;Initial Catalog=BASCSREPORT;Integrated Security=True");
conexionSQL.Open();
string stringCommand = "dbo.XXX_SP_REPORTING_SERVICES_DESPACHOS";
SqlCommand comandoSQL = new SqlCommand(stringCommand, conexionSQL);
comandoSQL.CommandType = CommandType.StoredProcedure;
comandoSQL.Parameters.AddWithValue("@xmlParametros", SqlDbType.Xml).Value = parametrosXML.ToString();
SqlDataAdapter da = new SqlDataAdapter(comandoSQL.ToString(), conexionSQL);
da.SelectCommand = comandoSQL;
BASCSREPORTDataSet dataSet1 = new BASCSREPORTDataSet();
da.Fill(dataSet1, dataSet1.Tables[0].TableName);
ReportDataSource rds = new ReportDataSource("XXX_SP_REPORTING_SERVICES_DESPACHOS", dataSet1.Tables[0]);
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(rds);
this.reportViewer1.LocalReport.Refresh();
this.reportViewer1.RefreshReport();

【讨论】:

    猜你喜欢
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多