Return value from Stored Procedure

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dooza

    Return value from Stored Procedure

    I have a stored procedure that takes a number of inputs, does a bulk
    insert, and then outputs a recordset. When I run the stored procedure in
    Server Management Studio I also get a return value from the stored
    procedure which is an INT.

    I want to access this return value on my ASP/VBScript page, but do not
    know how to access it.

    Here is my code so far:

    <%
    Dim rsImport
    Dim rsImport_cmd
    Dim rsImport_numRow s

    Set rsImport_cmd = Server.CreateOb ject ("ADODB.Command ")
    rsImport_cmd.Ac tiveConnection = MM_aclv4test_ST RING
    rsImport_cmd.Co mmandText = "{call dbo.PriceUpdate Import(?,?,?,?, ?)}"
    rsImport_cmd.Pr epared = true
    rsImport_cmd.Pa rameters.Append
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param1",
    200, 1, 255, rsImport__vendo r)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param2",
    200, 1, 255, rsImport__name)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param3",
    200, 1, 255, rsImport__filen ame)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param4",
    200, 1, 255, rsImport__valid from)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param5",
    200, 1, 255, rsImport__user)

    Set rsImport = rsImport_cmd.Ex ecute
    rsImport_numRow s = 0
    %>

    There is more code above that sets the variable for each parameter.

    I have tried adding this: rsImport_cmd.Cr eateParameter(" @RETURN_VALUE",
    3, 4) but I got this error:

    Microsoft OLE DB Provider for ODBC Drivers error '80040e21'

    Multiple-step OLE DB operation generated errors. Check each OLE DB
    status value, if available. No work was done.

    My stored procedure doesn't declare an output return value, which may be
    the problem, but when I execute the stored procedure in server
    management studio I am given a return value.

    Any ideas or pointers?

    Cheers,

    Steve
  • Bob Barrows [MVP]

    #2
    Re: Return value from Stored Procedure

    Dooza wrote:
    I have a stored procedure that takes a number of inputs, does a bulk
    insert, and then outputs a recordset. When I run the stored procedure
    in Server Management Studio I also get a return value from the stored
    procedure which is an INT.
    >
    I want to access this return value on my ASP/VBScript page, but do not
    know how to access it.
    >
    Here is my code so far:
    >
    <%
    Dim rsImport
    Dim rsImport_cmd
    Dim rsImport_numRow s
    >
    Set rsImport_cmd = Server.CreateOb ject ("ADODB.Command ")
    rsImport_cmd.Ac tiveConnection = MM_aclv4test_ST RING
    rsImport_cmd.Co mmandText = "{call dbo.PriceUpdate Import(?,?,?,?, ?)}"
    rsImport_cmd.Pr epared = true
    rsImport_cmd.Pa rameters.Append
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param1",
    200, 1, 255, rsImport__vendo r)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param2",
    200, 1, 255, rsImport__name)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param3",
    200, 1, 255, rsImport__filen ame)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param4",
    200, 1, 255, rsImport__valid from)
    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param5",
    200, 1, 255, rsImport__user)
    >
    Set rsImport = rsImport_cmd.Ex ecute
    rsImport_numRow s = 0
    %>
    >
    There is more code above that sets the variable for each parameter.
    >
    I have tried adding this:
    rsImport_cmd.Cr eateParameter(" @RETURN_VALUE", 3, 4) but I got this
    error:
    >
    The return parameter should be the first one you append. You will
    probably appreciate my free Command object code generator available
    here: http://common.mvps.org/barrowsb/Clas..._generator.zip
    My stored procedure doesn't declare an output return value, which may
    be the problem,
    No. A peculiarity of SQL Server is that it will not send output or
    return parameters until all resultsets generated by the procedure have
    been consumed by the caller. This is done for you behind the scenes in
    Query Manager. In ADO code, you have to do this yourself. You have to
    either navigate to the last record in the recordset, or close the
    recordset, before attempting to read the output or return parameter
    values. Switching to a client-side cursor guarantees that the current
    resultset is consumed.

    Moreover, you need to make sure the procedure is not generating any
    unexpected resultsets. Another peculiarity of SQL Server is that it
    sends those "x rows were affected" messages to the caller as closed
    resultsets. If your ADO code does not handle them, you will never see
    the output or return parameters. So, your standard practice should be to
    suppress those messages by including the line "SET NOCOUNT ON" at the
    beginning of your procedure.

    --
    Microsoft MVP -- ASP/ASP.NET
    Please reply to the newsgroup. The email account listed in my From
    header is my spam trap, so I don't check it very often. You will get a
    quicker response by posting to the newsgroup.


    Comment

    • Dooza

      #3
      Re: Return value from Stored Procedure

      Bob Barrows [MVP] wrote:
      The return parameter should be the first one you append. You will
      probably appreciate my free Command object code generator available
      here: http://common.mvps.org/barrowsb/Clas..._generator.zip
      Thanks Bob, I will give it a go.
      >My stored procedure doesn't declare an output return value, which may
      >be the problem,
      No. A peculiarity of SQL Server is that it will not send output or
      return parameters until all resultsets generated by the procedure have
      been consumed by the caller. This is done for you behind the scenes in
      Query Manager. In ADO code, you have to do this yourself. You have to
      either navigate to the last record in the recordset, or close the
      recordset, before attempting to read the output or return parameter
      values. Switching to a client-side cursor guarantees that the current
      resultset is consumed.
      Aha, the missing piece of the pie, that will explain it.
      Moreover, you need to make sure the procedure is not generating any
      unexpected resultsets. Another peculiarity of SQL Server is that it
      sends those "x rows were affected" messages to the caller as closed
      resultsets. If your ADO code does not handle them, you will never see
      the output or return parameters. So, your standard practice should be to
      suppress those messages by including the line "SET NOCOUNT ON" at the
      beginning of your procedure.
      Thats something I have always let Server Studio Manager do for me each
      time I create an SP... I didn't know what it was to begin with, so
      Googled it and realised how important it was.

      Thanks for the advice, I will let you know how I get on.

      Steve

      Comment

      • Dooza

        #4
        Re: Return value from Stored Procedure

        Bob Barrows [MVP] wrote:
        The return parameter should be the first one you append. You will
        probably appreciate my free Command object code generator available
        here: http://common.mvps.org/barrowsb/Clas..._generator.zip
        Bob, just to let you know this doesn't do anything in Firefox, but it
        does work in Internet Explorer.

        Steve

        Comment

        • Bob Barrows [MVP]

          #5
          Re: Return value from Stored Procedure

          Dooza wrote:
          Bob Barrows [MVP] wrote:
          >The return parameter should be the first one you append. You will
          >probably appreciate my free Command object code generator available
          >here:
          >http://common.mvps.org/barrowsb/Clas..._generator.zip
          >
          Bob, just to let you know this doesn't do anything in Firefox, but it
          does work in Internet Explorer.
          >
          I knew that and was willing to live with it. After all, I created it for my
          own use and I use IE at work. You are certainly free to rewrite it to make
          it browser-independent.

          --
          Microsoft MVP - ASP/ASP.NET
          Please reply to the newsgroup. This email account is my spam trap so I
          don't check it very often. If you must reply off-line, then remove the
          "NO SPAM"


          Comment

          • Dooza

            #6
            Re: Return value from Stored Procedure

            Bob Barrows [MVP] wrote:
            Dooza wrote:
            >Bob Barrows [MVP] wrote:
            >>The return parameter should be the first one you append. You will
            >>probably appreciate my free Command object code generator available
            >>here:
            >>http://common.mvps.org/barrowsb/Clas..._generator.zip
            >Bob, just to let you know this doesn't do anything in Firefox, but it
            >does work in Internet Explorer.
            >>
            I knew that and was willing to live with it. After all, I created it for my
            own use and I use IE at work. You are certainly free to rewrite it to make
            it browser-independent.
            No thanks, I can live with using IE now and then :)

            Steve

            Comment

            • Dooza

              #7
              Re: Return value from Stored Procedure

              Bob Barrows [MVP] wrote:
              No. A peculiarity of SQL Server is that it will not send output or
              return parameters until all resultsets generated by the procedure have
              been consumed by the caller. This is done for you behind the scenes in
              Query Manager. In ADO code, you have to do this yourself. You have to
              either navigate to the last record in the recordset, or close the
              recordset, before attempting to read the output or return parameter
              values. Switching to a client-side cursor guarantees that the current
              resultset is consumed.
              I have decided to change my tactics, as I needed the return parameter
              before the recordset.

              The stored procedure does a bulk insert into a temporary table, does
              some checks on the data. If there are duplicates it returns an error
              code and a recordset with the duplicate data.

              If there are no duplicates but other errors it will output different
              error numbers.

              If there are no errors, a success number is returned and the data is
              inserted into a permanent table and its details inserted into a job
              table, with its ID returned.

              My ASP needs to check the error number and display a message. If the
              duplicates are found it needs to list them. I need the error message
              before the recordset.

              I need to change my stored procedure to return 3 recordsets:

              1. Error number
              2. ID of import job if it was successful
              3. Recordset of duplicates

              Am I thinking this the right way?

              Steve

              Comment

              • Dooza

                #8
                Re: Return value from Stored Procedure

                Bob Barrows [MVP] wrote:
                Dooza wrote:
                >Bob Barrows [MVP] wrote:
                Actually, from reading the next paragraphs, you don't. You need either a
                recordset and error number, or a returned ID
                >The stored procedure does a bulk insert into a temporary table, does
                >some checks on the data. If there are duplicates it returns an error
                >code and a recordset with the duplicate data.
                >>
                >If there are no duplicates but other errors it will output different
                >error numbers.
                >>
                >If there are no errors, a success number is returned and the data is
                >inserted into a permanent table and its details inserted into a job
                >table, with its ID returned.
                >
                I'm not clear here: if there are multiple records involved, why would there
                necessarily be a single ID returned?
                Just re-read this...

                There are 3 tables
                #Import - for the initial bulk insert from a tab separated file
                PriceUpdateJob - the main details of the import, with an auto-id, name
                of job, date of job, active from date, username, and various other bit
                checks to indicate progress throughout the import process
                PriceUpdateImpo rtData - for the actual data from the initial file, with
                the job id and item id being primary keys.

                Not sure if that makes much difference :)

                Steve

                Comment

                • Dooza

                  #9
                  Re: Return value from Stored Procedure

                  Hi Bob,
                  I have changed my SP so that it doesn't specify an output parameter, I
                  am going to rely on the return value instead, if thats possible.

                  Throughout my SP I have RETURN 50001 to stop the SP and give the error
                  number. Right at the end, if everything has been successful I use RETURN
                  @import (which is the I job ID)

                  In SSMS I always get a recordset, even if its empty, and always get a
                  return value.

                  The return value is either 50000, 50001, 50002 or the ID of the job. I
                  may have to change the error numbers to something bigger, or do as you
                  suggest and have an output parameter.

                  I have also changed my code as per your instructions:

                  <%
                  Dim rsImport
                  Dim rsImport_cmd
                  Dim rsImport_numRow s

                  Set conn = CreateObject ("ADODB.Connect ion")
                  conn.open MM_aclv4test_ST RING
                  Set rsImport_cmd = CreateObject ("ADODB.Command ")
                  Set rsImport_cmd.Ac tiveConnection = conn
                  rsImport_cmd.Co mmandText = "PriceUpdateImp ort"
                  rsImport_cmd.Co mmandType = 4 'adCmdStoredPro c
                  rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param1",
                  200, 1, 255, rsImport__vendo r) ' adVarChar
                  rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param2",
                  200, 1, 255, rsImport__name) ' adVarChar
                  rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param3",
                  200, 1, 255, rsImport__filen ame) ' adVarChar
                  rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param4",
                  200, 1, 255, rsImport__valid from) ' adVarChar
                  rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param5",
                  200, 1, 255, rsImport__user) ' adVarChar

                  Set rsImport = rsImport_cmd.Ex ecute

                  If NOT rsImport.EOF Then
                  ardata = rsImport.GetRow s
                  End if
                  rsImport.Close
                  errcode = rsImport_cmd(0)

                  conn.close
                  Set conn = Nothing
                  %>

                  When there are duplicates I can loop through the array of data and see
                  the duplicates, but I never get the correct errcode. I always get the
                  value of the first parameter. I have tried adding the @RETURN_VALUE
                  parameter but always get an error about there being too many arguments.

                  Am I making an obvious mistake?

                  Cheers,

                  Steve

                  Comment

                  • Bob Barrows [MVP]

                    #10
                    Re: Return value from Stored Procedure

                    Dooza wrote:
                    Hi Bob,
                    I have changed my SP so that it doesn't specify an output parameter, I
                    am going to rely on the return value instead, if thats possible.
                    It's possible, but not advisable.
                    >
                    Throughout my SP I have RETURN 50001 to stop the SP and give the error
                    number. Right at the end, if everything has been successful I use
                    RETURN @import (which is the I job ID)
                    >
                    In SSMS I always get a recordset, even if its empty, and always get a
                    return value.
                    >
                    The return value is either 50000, 50001, 50002 or the ID of the job. I
                    may have to change the error numbers to something bigger, or do as you
                    suggest and have an output parameter.
                    There should be no problem returning the
                    >
                    I have also changed my code as per your instructions:
                    >
                    <%
                    Dim rsImport
                    Dim rsImport_cmd
                    Dim rsImport_numRow s
                    >
                    Set conn = CreateObject ("ADODB.Connect ion")
                    conn.open MM_aclv4test_ST RING
                    Set rsImport_cmd = CreateObject ("ADODB.Command ")
                    Set rsImport_cmd.Ac tiveConnection = conn
                    rsImport_cmd.Co mmandText = "PriceUpdateImp ort"
                    rsImport_cmd.Co mmandType = 4 'adCmdStoredPro c
                    The Return parameter should have been appended here - this is very
                    important!
                    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param1",
                    200, 1, 255, rsImport__vendo r) ' adVarChar
                    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param2",
                    200, 1, 255, rsImport__name) ' adVarChar
                    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param3",
                    200, 1, 255, rsImport__filen ame) ' adVarChar
                    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param4",
                    200, 1, 255, rsImport__valid from) ' adVarChar
                    rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param5",
                    200, 1, 255, rsImport__user) ' adVarChar
                    >
                    Set rsImport = rsImport_cmd.Ex ecute
                    >
                    If NOT rsImport.EOF Then
                    ardata = rsImport.GetRow s
                    End if
                    rsImport.Close
                    errcode = rsImport_cmd(0)
                    The 0 refers to the first item in the Parameters collection. Right now,
                    that is the rsImport__vendo r parameter. You need to append the
                    RETURN_VALUE parameter first!
                    >
                    conn.close
                    Set conn = Nothing
                    %>
                    >
                    When there are duplicates I can loop through the array of data and see
                    the duplicates, but I never get the correct errcode. I always get the
                    value of the first parameter. I have tried adding the @RETURN_VALUE
                    parameter but always get an error about there being too many
                    arguments.
                    >
                    Am I making an obvious mistake?
                    >
                    See above

                    --
                    Microsoft MVP -- ASP/ASP.NET
                    Please reply to the newsgroup. The email account listed in my From
                    header is my spam trap, so I don't check it very often. You will get a
                    quicker response by posting to the newsgroup.


                    Comment

                    • Dooza

                      #11
                      Re: Return value from Stored Procedure

                      I was missing the 2 from the end

                      rsImport_cmd.Pa rameters.Append
                      rsImport_cmd.Cr eateParameter(" @RETURN_VALUE", 3, 4,2)

                      It now does return the correct error number AND the successfully
                      inserted ID.

                      Steve

                      Comment

                      • Bob Barrows [MVP]

                        #12
                        Re: Return value from Stored Procedure

                        Use the code generator! Just substitute your variable names for the
                        names I used in the generator.

                        Dooza wrote:
                        Hi Bob,
                        I have changed my SP so that it doesn't specify an output parameter, I
                        am going to rely on the return value instead, if thats possible.
                        >
                        Throughout my SP I have RETURN 50001 to stop the SP and give the error
                        number. Right at the end, if everything has been successful I use
                        RETURN @import (which is the I job ID)
                        >
                        In SSMS I always get a recordset, even if its empty, and always get a
                        return value.
                        >
                        The return value is either 50000, 50001, 50002 or the ID of the job. I
                        may have to change the error numbers to something bigger, or do as you
                        suggest and have an output parameter.
                        >
                        I have also changed my code as per your instructions:
                        >
                        <%
                        Dim rsImport
                        Dim rsImport_cmd
                        Dim rsImport_numRow s
                        >
                        Set conn = CreateObject ("ADODB.Connect ion")
                        conn.open MM_aclv4test_ST RING
                        Set rsImport_cmd = CreateObject ("ADODB.Command ")
                        Set rsImport_cmd.Ac tiveConnection = conn
                        rsImport_cmd.Co mmandText = "PriceUpdateImp ort"
                        rsImport_cmd.Co mmandType = 4 'adCmdStoredPro c
                        rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param1",
                        200, 1, 255, rsImport__vendo r) ' adVarChar
                        rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param2",
                        200, 1, 255, rsImport__name) ' adVarChar
                        rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param3",
                        200, 1, 255, rsImport__filen ame) ' adVarChar
                        rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param4",
                        200, 1, 255, rsImport__valid from) ' adVarChar
                        rsImport_cmd.Pa rameters.Append rsImport_cmd.Cr eateParameter(" param5",
                        200, 1, 255, rsImport__user) ' adVarChar
                        >
                        Set rsImport = rsImport_cmd.Ex ecute
                        >
                        If NOT rsImport.EOF Then
                        ardata = rsImport.GetRow s
                        End if
                        rsImport.Close
                        errcode = rsImport_cmd(0)
                        >
                        conn.close
                        Set conn = Nothing
                        %>
                        >
                        When there are duplicates I can loop through the array of data and see
                        the duplicates, but I never get the correct errcode. I always get the
                        value of the first parameter. I have tried adding the @RETURN_VALUE
                        parameter but always get an error about there being too many
                        arguments.
                        >
                        Am I making an obvious mistake?
                        >
                        Cheers,
                        >
                        Steve
                        --
                        Microsoft MVP -- ASP/ASP.NET
                        Please reply to the newsgroup. The email account listed in my From
                        header is my spam trap, so I don't check it very often. You will get a
                        quicker response by posting to the newsgroup.


                        Comment

                        • Dooza

                          #13
                          Re: Return value from Stored Procedure

                          Bob Barrows [MVP] wrote:
                          Dooza wrote:
                          >Hi Bob,
                          >I have changed my SP so that it doesn't specify an output parameter, I
                          >am going to rely on the return value instead, if thats possible.
                          >
                          It's possible, but not advisable.
                          I have taken your advice and used an output parameter, and its working!
                          >Throughout my SP I have RETURN 50001 to stop the SP and give the error
                          >number. Right at the end, if everything has been successful I use
                          >RETURN @import (which is the I job ID)
                          >>
                          >In SSMS I always get a recordset, even if its empty, and always get a
                          >return value.
                          >>
                          >The return value is either 50000, 50001, 50002 or the ID of the job. I
                          >may have to change the error numbers to something bigger, or do as you
                          >suggest and have an output parameter.
                          >
                          There should be no problem returning the
                          >I have also changed my code as per your instructions:
                          >>
                          ><%
                          >Dim rsImport
                          >Dim rsImport_cmd
                          >Dim rsImport_numRow s
                          >>
                          >Set conn = CreateObject ("ADODB.Connect ion")
                          >conn.open MM_aclv4test_ST RING
                          >Set rsImport_cmd = CreateObject ("ADODB.Command ")
                          >Set rsImport_cmd.Ac tiveConnection = conn
                          >rsImport_cmd.C ommandText = "PriceUpdateImp ort"
                          >rsImport_cmd.C ommandType = 4 'adCmdStoredPro c
                          >
                          The Return parameter should have been appended here - this is very
                          important!
                          I am there now, thanks to you Bob. Its all starting to make sense and
                          work, my days of relying on Dreamweaver are almost over :)

                          Thanks again!

                          Steve

                          Comment

                          Working...