Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
Utpal
Posting Yak Master
179 Posts |
Posted - 2002-09-14 : 08:18:40
|
| Hi everybody, I am using SQL Server 7.0. Can a cursor declared in one stored procedure be passed as a parameter to another stored procedure? If not, can it be emulated in any way? |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2002-09-14 : 11:42:29
|
| According to Books Online, cursor variables can only be used as output variables in a stored procedure. I *think* you might be able to open it in the receiving stored procedure, but I can't find a definite yes/no in BOL about it and I can't test it.The best thing to do is NOT use cursor. Put the results into a temp table (or regular table). It can be created in Procedure A and referenced in Procedure B. |
 |
|
|
Utpal
Posting Yak Master
179 Posts |
Posted - 2002-09-16 : 02:07:07
|
quote: The best thing to do is NOT use cursor. Put the results into a temp table (or regular table). It can be created in Procedure A and referenced in Procedure B.
I used this technique in other stored procedures. In this one as I have to anyway open a cursor, I thought passing the cursor as a parameter would be the fastest and would consume minimum server resources, because in the temp table approach, first the temp table has to be created, then it has to be filled with the results, then a cursor has to be declared from the other stored procedure. Tell me if I am wrong. |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2002-09-16 : 08:22:52
|
quote: In this one as I have to anyway open a cursor
Well, if you think that you HAVE TO use a cursor, it's a fair bet that you're doing it wrong If you post your code, your table structures, and what you're trying to accomplish, we can take a stab at another, non-cursor approach. We've done it before. |
 |
|
|
M.E.
Aged Yak Warrior
539 Posts |
Posted - 2002-09-16 : 16:10:27
|
| I've seen something simular done passing table variables around. Cursor loads a table var and passes that to a different server. On the same note I tore it apart and made it setbased... Hehehe so much nicer that way-----------------------Take my advice, I dare ya |
 |
|
|
Utpal
Posting Yak Master
179 Posts |
Posted - 2002-09-17 : 06:43:25
|
quote: If you post your code, your table structures, and what you're trying to accomplish, we can take a stab at another, non-cursor approach. We've done it before.
Basically, the sp generates standard costs of items as on a given date and stores it in the StdCost_Master table. The standard cost of a raw material is based on the weighted average price of its purchases. The standard cost of a sub-assembly or finished good is calculated based on the values (qty * standard cost) of its constituents, which is contained in the Parts_List table. I am opening the cursor for the purpose of calculation of standard cost of a sub-assembly/finished good, which is done using a recursive sp Std_Cost_Derived.The table structures (relevant fields) are as follows:Item_Masterpart_nodescriptionopening_stockStdCost_Master (Std. costs of part_no as on various dates)part_nocost_datecostParts_List (Details of constituents of part_no)part_norm_part_noqtyThe code of the Std Cost generation sp is as follows: CREATE PROCEDURE Generate_Std_Costs @cost_date DateTime, @rmc Bit, @fga Bit ASDECLARE @part_no Char(8), @opening_stock Numeric(9,3), @last_cost_date Datetime, @last_cost Money, @new_cost Money, @update BitSET NOCOUNT ONBEGIN TRANSACTION DECLARE Cursor_Item_Master CURSOR LOCAL FAST_FORWARD FOR SELECT Item_Master.part_no, Item_Master.opening_stock, StdCost_Master.last_cost_date, StdCost_Master.last_cost FROM Item_Master LEFT JOIN ( SELECT A.part_no, A.cost_date AS last_cost_date, A.cost AS last_cost FROM StdCost_Master A INNER JOIN ( SELECT part_no, MAX(cost_date) AS last_cost_date FROM StdCost_Master WHERE cost_date < @cost_date GROUP BY part_no ) B ON A.part_no = B.part_no AND A.cost_date = B.last_cost_date ) StdCost_Master ON Item_Master.part_no = StdCost_Master.part_no ORDER BY Item_Master.group_code OPEN Cursor_Item_Master FETCH NEXT FROM Cursor_Item_Master INTO @part_no, @opening_stock, @last_cost_date, @last_cost WHILE @@FETCH_STATUS = 0 BEGIN SET @new_cost = 0 IF EXISTS ( SELECT rm_part_no, qty FROM Parts_List WHERE part_no = @part_no ) BEGIN IF @fga = 1 EXECUTE Std_Cost_Derived @part_no, @rmc, @cost_date, @new_cost = @new_cost OUTPUT SET @update = @fga END ELSE BEGIN IF @rmc = 1 EXECUTE Std_Cost_Purchase_Based @part_no, @cost_date, @opening_stock, @last_cost_date, @last_cost, @new_cost = @new_cost OUTPUT SET @update = @rmc END IF @update = 1 BEGIN IF EXISTS ( SELECT cost FROM StdCost_Master WHERE part_no = @part_no AND cost_date = @cost_date ) UPDATE StdCost_Master SET cost = @new_cost WHERE part_no = @part_no AND cost_date = @cost_date ELSE INSERT INTO StdCost_Master VALUES ( @part_no, @cost_date, @new_cost ) END FETCH NEXT FROM Cursor_Item_Master INTO @part_no, @opening_stock, @last_cost_date, @last_cost END CLOSE Cursor_Item_Master DEALLOCATE Cursor_Item_Master IF EXISTS( SELECT cost_date FROM StdCost_Dates WHERE cost_date = @cost_date ) UPDATE StdCost_Dates SET rmc = CASE rmc WHEN 1 THEN 1 ELSE @rmc END, fga = CASE fga WHEN 1 THEN 1 ELSE @fga END ELSE INSERT INTO StdCost_Dates VALUES ( @cost_date, @rmc, @fga )COMMIT TRANSACTIONSET NOCOUNT OFFRETURN CREATE PROCEDURE Std_Cost_Derived @part_no Char(8), @rmc Bit, @cost_date Datetime, @new_cost Money OUTPUT ASDECLARE @rm_part_no Char(8), @qty Numeric(9,3), @rm_new_cost Money, @opening_stock Numeric(9,3), @last_cost_date Datetime, @last_cost MoneyDECLARE Cursor_Parts_List CURSOR LOCAL FAST_FORWARD FOR SELECT rm_part_no, qty FROM Parts_List WHERE part_no = @part_noOPEN Cursor_Parts_ListFETCH NEXT FROM Cursor_Parts_List INTO @rm_part_no, @qtyIF @@FETCH_STATUS = 0BEGIN WHILE @@FETCH_STATUS = 0 BEGIN SET @rm_new_cost = 0 EXECUTE Std_Cost_Derived @rm_part_no, @rmc, @cost_date, @new_cost = @rm_new_cost OUTPUT SET @new_cost = @new_cost + ( @rm_new_cost * @qty ) FETCH NEXT FROM Cursor_Parts_List INTO @rm_part_no, @qty ENDENDELSEBEGIN IF @rmc = 1 BEGIN SELECT @opening_stock = Item_Master.opening_stock, @last_cost_date = StdCost_Master.last_cost_date, @last_cost = StdCost_Master.last_cost FROM Item_Master LEFT JOIN ( SELECT A.part_no, A.cost_date AS last_cost_date, A.cost AS last_cost FROM StdCost_Master A INNER JOIN ( SELECT part_no, MAX(cost_date) AS last_cost_date FROM StdCost_Master WHERE cost_date < @cost_date GROUP BY part_no ) B ON A.part_no = B.part_no AND A.cost_date = B.last_cost_date ) StdCost_Master ON Item_Master.part_no = StdCost_Master.part_no WHERE Item_Master.part_no = @part_no EXECUTE Std_Cost_Purchase_Based @part_no, @cost_date, @opening_stock, @last_cost_date, @last_cost, @new_cost = @new_cost OUTPUT ENDENDRETURN To determine whether the item is a sub-assembly/finished good or a raw material, I am using: IF EXISTS ( SELECT rm_part_no, qty FROM Parts_List WHERE part_no = @part_no ) Again in the Std_Cost_Derived sp, using the same query I am opening a cursor. If instead of using the above code (IF EXISTS (...)), I opened a cursor there itself and passed it as a parameter to the Std_Cost_Derived sp, I wouldn't have had to run the same query again in Std_Cost_Derived.So let me know what is the best way to implement this.Edited by - Utpal on 09/17/2002 06:45:06Edited by - Utpal on 09/17/2002 06:56:31Edited by - Utpal on 09/17/2002 06:58:14Edited by - Utpal on 09/17/2002 07:00:34Edited by - Utpal on 09/17/2002 08:13:30 |
 |
|
|
|
|
|
|
|