Search code examples
sql-serverstored-procedurescrystal-reports

Stored procedure used for Crystal Reports overwrites previous records


I have the following code to call a stored procedure to populate a Crystal Report. The problem is that the last record is the only one returned and is repeated throughout the report. It seems to be overwriting the previous records rather than returning the each record associated with the ID parameter. Am I missing something?

Dim idSQL As String = "SELECT DISTINCT ID FROM table"

drID = objdata.getOLEDBDR(MSCON1, idSQL)

            While drID.Read
                IDall = drID(0)

              'GET DATA******************************
                sqlstr = "SELECT columnname FROM tablename WHERE Id = '" & IDall & "'"

                Dim DAscp As New OleDbDataAdapter(sqlstr, MSCON1)
                dsQRpt.EnforceConstraints = False

                DAscp.Fill(dsQRpt, "tablename")


              'GET DATA FROM SP***********************
                Dim cmd As OleDbCommand = New OleDbCommand()
                cmd.Connection = MSCON
                cmd.CommandType = CommandType.StoredProcedure
                cmd.CommandText = "NAME_OF_SP"
                cmd.Parameters.Add("@month", OleDbType.VarChar, 10, ParameterDirection.Output).Value = QtrMonth
                cmd.Parameters.Add("@year", OleDbType.VarChar, 10, ParameterDirection.Output).Value = cboYear.SelectedValue
                cmd.Parameters.Add("@id", OleDbType.VarChar, 10, ParameterDirection.Output).Value = IDall

          Dim DAms As New OleDbDataAdapter()

            DAms.SelectCommand = cmd

            'DAms.Fill(dsQRpt)
            DAms.Fill(dsQRpt, "SP_NAME")


              'Populate Report*********************************************************************
                QPrpt.Load(Server.MapPath("rptQuarterly.rpt"))
                QPrpt.SetDataSource(dsQRpt)
                crQtrProgress.ReportSource = QPrpt
                QPrpt.SetParameterValue("vPTSID", PTSall)
                crQtrProgress.DataBind()

            End While

Here's the stored procedure:

USE [DB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_NAME]
(
@month varchar(20),
@year varchar (4),
@id varchar (15)
)
AS

DECLARE @tmp table
(
ID nvarchar(10),
CategoryId nvarchar(5),
CategoryName nvarchar(50),
MDate datetime
)


DECLARE @i varchar(10)
DECLARE @sql varchar(1000)


SET @i = 1
DECLARE @j varchar(10)
SET @j = 1


WHILE (@i <=28)
BEGIN
DECLARE @MIDDATE nvarchar(25)
DECLARE @MIDID nvarchar(15)
SET @MIDDATE = 'mh.MID_'+@i+'_DATE'
SET @MIDID = 'mh.MID_'+@i


IF (((@i= 9) OR (@i =12)) AND (@j = 1))
        BEGIN
            --SET @j = 2
            SET @MIDDATE = 'mh.MID_'+@i+'a_DATE'
            SET @MIDID = 'mh.MID_'+@i+'a'
        END  

 IF (((@i= 9) OR (@i = 12)) AND (@j = 2))
        BEGIN

            SET @MIDDATE = 'mh.MID_'+@i+'b_DATE'
            SET @MIDID = 'mh.MID_'+@i+'b'
       END 


SET @sql ='SELECT mh.ID, mc.CategoryId, mc.CategoryName, '+ @MIDDATE +'
FROM MHistory As mh, MCategories As mc WHERE mc.CategoryId = SUBSTRING('''+
@MIDID +''',8,10) AND mh.ID = ''' + @id + ''' AND mh.Hist_Yr = ' + @year + '
AND mh.Hist_Month = ''' + @month + ''' ORDER BY mh.ID'
INSERT INTO @tmp
EXEC (@sql)

IF (((@i= 9) OR (@i=12)) AND (@j = 1))
                  BEGIN
                  IF @i= 9 SET @i = 9
                  IF @i =12 SET @i = 12
                  SET @j = 2
                  END 
  ELSE
                  BEGIN
                    SET @i = @i + 1
                    SET @j = 1
                  END 
 END

----SET @i = @i + 1
SELECT 
ID AS ID,
CategoryId AS CategoryId,
CategoryName AS CategoryName,
MDate AS MDate

from @tmp

Solution

  • It seems the query for the report's data source is always returning a single record since your datasource query is filtering on Id which I believe is the primary key of tablename.

    'GET DATA******************************
                sqlstr = "SELECT columnname FROM tablename WHERE Id = '" & IDall & "'"
    
                Dim DAscp As New OleDbDataAdapter(sqlstr, MSCON1)
                dsQRpt.EnforceConstraints = False
    
                DAscp.Fill(dsQRpt, "tablename")
    

    Also, I would suggest that you verify if the stored procedure is getting called by the report with correct parameters. You could do this by populating a custom table just before the last SELECT in your stored procedure. In this custom table you could log the values of parameters and anything else you think is relevant to the situation.

    You can use following queries to do this logging.

    Create custom tables for logging

    CREATE TABLE CustomLoggingTable (Parameters varchar(max), RunDate DateTime);
    CREATE TABLE CustomResultsTable (ID int, CategoryId int, CategoryName varchar(500),
                                                                             MDate DateTime);
    

    Add the query below as the last part in your procedure ( the last SELECT in this code is the original SELECT you have and you should not change it, but just place the other part before it)

    Log your stored procedure

    --log procedure parameters
    INSERT INTO CustomLoggingTable ( Parameters, RunDate) 
    select '@month = ' + isnull(@month,'')  + ', @year = ' + isnull(@year,'') 
                                           + ', @id = ' + isnull( @id,''), getdate() ;
    
    --log result set being returned into a custom table
    DELETE from CustomResultsTable;
    INSERT into CustomResultsTable (ID, CategoryId, CategoryName, MDate)
    SELECT 
    ID AS ID,
    CategoryId AS CategoryId,
    CategoryName AS CategoryName,
    MDate AS MDate
    from @tmp
    
    --this is your last statement in procedure for returning final result set
    SELECT 
    ID AS ID,
    CategoryId AS CategoryId,
    CategoryName AS CategoryName,
    MDate AS MDate
    from @tmp
    

    After above setup, you can view exactly what happened when your stored procedure was called. The CustomResultsTable will be refreshed every time with the latest result set returned, while CustomLoggingTable will add a new record for each run of the procedure.