Question : Call a stored procedure containing a CURSOR from a stored procedure

I need to execute one stored procedure from within another. I can do this successfully with one exception and that is when the called stored procedure uses a CURSOR to return the result. I have plenty of stored procedures that call others and pick up the output from them but in this case I need to concatenate a series of linked records into a single string.

The cursor to do this works, i.e. I can show that it returns the correct string but when I execute the stored procedure containing the cursor I only get the result from the cursor. I'm hoping I've missed something really simple here and that someone has that answer.

I've attached the code for both stored procedures, the results from the inner stored procedure (the one containing the cursor), the output of the inner stored procedure showing that it works and some SQL Query Analyzer results showing two result sets rather than one for the calling stored procedure.

Any help will be greatly appreciated.
 
Results for INNER Stored Procedure
332516
 
 
Results for OUTER (Calling) Stored Procedure
332517
 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
/* This is the OUTER/CALLING stored procedure */

/*
	Procedure Name:	usp_NewProductForm_Print_Document_By_DocumentID
	Author:			Peter Stanford
	Date Written:		8th October 2006
	Description:		This Procedure returns a list of New Product Forms
	Last Updated:		
	Change History:		
	7th March 2010		Added Description_2 and Description_3
*/
CREATE PROCEDURE dbo.usp_NewProductForm_Print_Document_By_DocumentID
	@DocumentID as integer
AS


DECLARE @Warehouse_List varchar(1000)

EXEC usp_NewProductForm_Select_Warehouse_List_For_Printing @DocumentID, @Warehouse_List OUTPUT

SELECT 
	a.ID,
	CASE a.OwnManufacture WHEN 1 THEN 'Yes' ELSE 'No' END as 'OwnManufacture',
	CONVERT(char(6), a.APDApprovalNumber) + ' ' +
	CONVERT(char(20), g.Customer) + ' ' + 
	CONVERT(char(20), g.ProposedCodeNumber) + ' ' + 
	CONVERT(char(10),g.DateClosed,103) as 'APDApprovalNumber' ,
	CASE b.Name WHEN NULL THEN 'Not selected' ELSE b.Name END as 'RequestedBy',
	CASE c.Name WHEN NULL THEN 'Not selected' ELSE c.Name END as 'Branch',
	CONVERT (varchar(10), a.NPFDate, 103) as 'NPFDate',
	a.ReasonForProposal,
	a.ProductCode,
	CASE d.Name WHEN NULL THEN 'Not selected' ELSE d.Name END as 'GroupCode',
	a.ColoursAndSizes,
	a.Description,
	CASE e.Name WHEN NULL THEN 'Not selected' ELSE e.Name END as 'StockType',
	CASE f.Name WHEN NULL THEN 'Not selected' ELSE f.Name END as 'SalesType',
	CASE l.Name WHEN NULL THEN 'Not selected' ELSE l.Name END as 'SalesUnitOfMeasure',
	a.PackQuantity,
	a.SupplierName,
	a.SupplierNumber,
	a.SupplierStockCode,
	CASE m.Name WHEN NULL THEN 'Not selected' ELSE m.Name END as 'SupplierUnitOfMeasure',
	a.ConversionFactor,
	a.SupplierPackQuantity,
	a.EstimatedLeadTimeDays,
	a.EconomicOrderQuantity,
	a.MinimumQuantity,
	a.MaximumQuantity,
	a.CurrentBuyPrice,
	a.QuantityPerUnit,
	a.Currency,
	a.SellingPrice01,
	a.SellingPrice02,
	a.SellingPrice03,
	a.SellingPrice04,
	CONVERT (varchar(10), a.ForecastStartDate, 103) as 'ForecastStartDate',
	a.ForecastPeriod01,
	a.ForecastPeriod02,
	a.ForecastPeriod03,
	a.ForecastPeriod04,
	a.ForecastPeriod05,
	a.ForecastPeriod06,
	a.APN,
	a.ExchangeRateApproved,
	a.DutyRate,
	a.OverseasFreight,
	a.LocalCosts,
	CASE h.Name WHEN NULL THEN 'Not yet approved' ELSE h.Name END as 'MaterialsManagerApproval',
	CONVERT (varchar(10), a.MaterialsManagerApprovalDate, 103) as 'MaterialsManagerApprovalDate',
	a.LastUpdated,
	a.UpdatedBy,
	CASE a.ProntoChanged WHEN 0 THEN 'No' ELSE 'Yes' END as 'ProntoChanged',
	CASE a.Rejected WHEN 0 THEN CASE a.DateClosed WHEN NULL THEN '' ELSE 'This document was closed by ' + r.Name + ' on ' +   CONVERT(varchar(10), a.DateClosed, 103) END ELSE 'This document was rejected by ' + r.Name + ' on ' + CONVERT(varchar(10), a.DateClosed, 103) END as Status,
	CONVERT(varchar(10),  a.DateClosed, 103) as 'DateClosed',
	CASE r.Name WHEN NULL THEN 'Not Closed' ELSE r.Name END as 'ClosedBy',
	CASE k.Name WHEN NULL THEN 'Not selected' ELSE k.Name END as 'CountryOfOrigin',
	a.AHECCImport,
	a.AHECCExport,
	a.EachWeight,
	a.CartonQuantity,
	a.CartonWeight,
	a.PalletQuantity,
	a.CartonHeight,
	a.CartonWidth,
	a.CartonDepth,
	a.CartonsPerLayer,
	a.MaximumHeight,
	a.MaximumLayers,
	CASE n.Name WHEN NULL THEN 'Not Selected' ELSE n.Name END as 'ABCClassification',
	a.Description_2,
	a.Description_3,
	a.OuterPackQuantity,
	CASE @Warehouse_List WHEN NULL THEN '' ELSE @Warehouse_List END as 'Warehouse_List'
FROM 
	(((((((((((NewProductForms a	
				LEFT OUTER JOIN Staff b on b.ID = a.RequestedBy)
				LEFT OUTER JOIN Locations c on c.ID = a.Branch)
				LEFT OUTER JOIN ProductGroup d on d.ID = a.GroupCode)
				LEFT OUTER JOIN StockType e on e.ID = a.StockType)
				LEFT OUTER JOIN SalesType f on f.ID = a.SalesType)
				LEFT OUTER JOIN Staff h on h.ID = a.MaterialsManagerApproval)
				LEFT OUTER JOIN Staff r on r.ID = a.ClosedByID)
				LEFT OUTER JOIN ProductDevelopmentApplications g on g.ID = a.APDApprovalNumber)
				LEFT OUTER JOIN Country k on k.ID = a.CountryOfOrigin)
				LEFT OUTER JOIN SalesUOM l on l.ID = a.SalesUnitOfMeasure)
				LEFT OUTER JOIN SupplierUOM m on m.ID = a.SupplierUnitOfMeasure)
				LEFT OUTER JOIN ABC_Class n on n.ID = a.ABCClassification
WHERE
	a.ID = @DocumentID
RETURN 0
GO

/* This is the INNER/CALLED stored procedure */

/*
	Procedure Name:	usp_NewProductForm_Select_Warehouse_List_For_Printing
	Author:			Peter Stanford
	Date Written:		1st August 2010
	Description:		This Procedure returns a list of Warehouses for printing on the PDF
	Last Updated:		

*/
CREATE PROCEDURE usp_NewProductForm_Select_Warehouse_List_For_Printing 
	@DocumentID integer,
	@Warehouse_List varchar(1000) OUTPUT
AS

BEGIN

DECLARE Warehouse_Cursor CURSOR FOR

SELECT 
	CASE a.Name WHEN NULL THEN '' ELSE a.Name END as Name
FROM
	Warehouse_FG a LEFT OUTER JOIN NPF_FGWarehouse b on b.WarehouseID = a.ID
WHERE
	b.NPFID = @DocumentID
ORDER BY Name


OPEN  Warehouse_Cursor

SET NOCOUNT ON

/*SET @Warehouse_List = NULL*/

DECLARE @Name varchar(50)

FETCH NEXT FROM 
	Warehouse_Cursor 
INTO 
	@Name

WHILE @@FETCH_STATUS = 0 BEGIN
	SELECT @Warehouse_List = @Warehouse_List + @Name + ', '

FETCH NEXT FROM 
	Warehouse_Cursor 
INTO 
	@Name
END

END

SELECT @Warehouse_List

CLOSE Warehouse_Cursor

DEALLOCATE Warehouse_Cursor
GO
Related Solutions: SQL SERVER Coding Best Practice

Answer : Call a stored procedure containing a CURSOR from a stored procedure

Asside from the doubtful merits of that inner Stored Procedure which is in desperate need of recoding, you are comparing apples to oranges. When you are testing it you are doing it like this:

EXEC usp_NewProductForm_Select_Warehouse_List_For_Printing 1, ''

Yet, when you call it, you are doing it like this:
EXEC usp_NewProductForm_Select_Warehouse_List_For_Printing @DocumentID, @Warehouse_List OUTPUT

Since @Warehouse_List is NULL and never initialized, that is exactly the value you are going to get back, regardless of your invalid use of SELECT @Warehouse_List at the end of the Stored Procedure.

So if you are just trying to fix the code so that it resolves the problem, rather than fix the problem: than you need to iniitialize the value of @Warehouse_List somewhere.

For example you can do one of the following options:
1. In your outer Stored Procedure:
DECLARE @Warehouse_List varchar(1000)

SET @Warehouse_List = ''                -- add this line

EXEC usp_NewProductForm_Select_Warehouse_List_For_Printing @DocumentID, @Warehouse_List OUTPUT

2. In your Inner Stored Procedure
SET NOCOUNT ON

/*SET @Warehouse_List = NULL*/
SET @Warehouse_List = ''                -- add this line

DECLARE @Name varchar(50)

3.  Change this line in the Inner Stored Procedure:
    BEGIN
        -- SELECT  @Warehouse_List = @Warehouse_List + @Name + ', '
        SELECT  @Warehouse_List = ISNULL(@Warehouse_List, '')+ @Name + ', '           -- Change this line
        FETCH NEXT FROM Warehouse_Cursor INTO @Name
    END

And when you get a chance please re-write that Stored Procedure or better still convert it to a UDF.
Random Solutions  
 
programming4us programming4us