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.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Cursor Problem

Author  Topic 

barlowr70
Starting Member

1 Post

Posted - 2003-08-26 : 06:25:32
I need to produce a report that involves currency conversion. All Report costs need to be reported in Dollars. What I've done is create a temporary table to hold the values, which are Spend, Save and ProjSave. I then set up a cursor to pick up the actual values. I loop through the records. If the Currency is dollars I update all values, otherwise I set up another loop and pass the currency values and the loop counter to another procedure that returns the converted values, then depending on the counter value I update a single field in the Temp table, but I'm having a problem with the second loop, it's falling over and terminating the outer loop also. I've included the code below.

Many Thanks.

CREATE PROCEDURE dbo.spConversionTest
AS
BEGIN
SET NOCOUNT ON

--Step one: create a temp table to hold the results of your query
create table #DollarValues (P_ID int not null, AnnualSave float, AnnualSpend float, ProjAnnualSave float)

--step two: Populate temp table with the ID of each Project.
INSERT #DollarValues (P_ID)
SELECT p.ProjID
FROM tblProjects AS p

Declare @lngProject int
Declare @Currency varchar(5)
Declare @dblAnnualSave float
Declare @dblAnnualSpend float
Declare @dblProjAnnualSave float
Declare @dblUSD float
Declare @dblGBP float
Declare @varDate datetime
Declare @myValue float
Declare @intCounter int

Declare curs1 Cursor
FOR
SELECT p.ProjID, p.ProjCurrency, p.ExpectedAnnualSaving, p.AnnualSpend,
p.ProjectedAnnualSaving
FROM tblProjects AS p

OPEN curs1
FETCH NEXT FROM curs1 INTO @lngProject, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave
--Start Loop
WHILE @@fetch_status = 0
BEGIN
--Move to Next Record
FETCH NEXT FROM curs1 INTO @lngProject, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave

UPDATE #DollarValues
SET AnnualSave=@dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject

--If the Currency is Dollars append all Values to Temp Table
IF @Currency ='USD'
--Append Values to Temp Table
UPDATE #DollarValues
SET AnnualSave = @dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject

--If the Currency is not Dollars
--**** PROBLEM AREA ****
ELSE IF @Currency !='USD'
SET @intCounter=0
--Start Loop, I'm having a problem with this loop and it sets the @@fetch_status to 0
--I need to take the cursor variables and pass them to the dbo.spConversionValue procedure

WHILE @intCounter < 3 BEGIN
DECLARE @dblConversion float
EXEC dbo.spConversionValue @dblConversion OUTPUT, @intCounter, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave

--Depending on the Counter value updaet a field in the Temp Table
if @intCounter = 1 --Annual Saving
UPDATE #DollarValues SET AnnualSave = @dblConversion WHERE P_ID = @lngProject
else if @intCounter = 2 --Annual Spend
UPDATE #DollarValues SET AnnualSpend = @dblConversion WHERE P_ID = @lngProject
else if @intCounter = 3 --Projected Saving
UPDATE #DollarValues SET ProjAnnualSave = @dblConversion WHERE P_ID = @lngProject
--Increment the Counter
Set @intCounter=@intCounter+1
END
--**** END PROBLEM AREA ****

END
END

CLOSE curs1
DEALLOCATE curs1

select * from #DollarValues

mohdowais
Sheikh of Yak Knowledge

1456 Posts

Posted - 2003-08-26 : 07:46:43
I have a couple of comments before I get to the problem area. Firstly, look at the following snippet of your code.


FETCH NEXT FROM curs1 INTO @lngProject, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave

UPDATE #DollarValues
SET AnnualSave=@dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject

--If the Currency is Dollars append all Values to Temp Table
IF @Currency ='USD'
--Append Values to Temp Table
UPDATE #DollarValues
SET AnnualSave = @dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject


You are running the same update statement before the IF statement, and when the currency is USD. You could easily get rid of the one inside the IF statement.

Secondly, for the first condition (Currency = USD), you dont need a cursor at all, you can accomplish this with a simple UPDATE...INNER JOIN statement:


UPDATE d
SET
AnnualSave = p.ExpectedAnnualSaving,
AnnualSpend = p.AnnualSpend,
ProjAnnualSave = p.ProjectedAnnualSaving
FROM #DollarValues d INNER JOIN tblProjects p
ON d.P_ID = p.P_ID
AND p.ProjCurrency = 'USD'


After having run the above code, you'll be left with only the non-USD records to deal with. Here you might need a cursor to invoke the stored procedure for each row.

I am wondering why you have a 1-3 loop to get three values out of the stored proc. Can you re-write your procedure to return all the three values as output parameters, so they can be obtained in a single call to the proc?

Owais


Make it idiot proof and someone will make a better idiot
Go to Top of Page

TSQLMan
Posting Yak Master

160 Posts

Posted - 2003-08-27 : 14:25:34
For this project cursors are a waste of keystrokes. #TemporaryTables are much better peformers. The advice already given will work well, so I won't re hash. I used to use cursors, because I thought it would show my skill. I now, very rarely find a need to use cursors, except with app development.

quote:
Originally posted by barlowr70

I need to produce a report that involves currency conversion. All Report costs need to be reported in Dollars. What I've done is create a temporary table to hold the values, which are Spend, Save and ProjSave. I then set up a cursor to pick up the actual values. I loop through the records. If the Currency is dollars I update all values, otherwise I set up another loop and pass the currency values and the loop counter to another procedure that returns the converted values, then depending on the counter value I update a single field in the Temp table, but I'm having a problem with the second loop, it's falling over and terminating the outer loop also. I've included the code below.

Many Thanks.

CREATE PROCEDURE dbo.spConversionTest
AS
BEGIN
SET NOCOUNT ON

--Step one: create a temp table to hold the results of your query
create table #DollarValues (P_ID int not null, AnnualSave float, AnnualSpend float, ProjAnnualSave float)

--step two: Populate temp table with the ID of each Project.
INSERT #DollarValues (P_ID)
SELECT p.ProjID
FROM tblProjects AS p

Declare @lngProject int
Declare @Currency varchar(5)
Declare @dblAnnualSave float
Declare @dblAnnualSpend float
Declare @dblProjAnnualSave float
Declare @dblUSD float
Declare @dblGBP float
Declare @varDate datetime
Declare @myValue float
Declare @intCounter int

Declare curs1 Cursor
FOR
SELECT p.ProjID, p.ProjCurrency, p.ExpectedAnnualSaving, p.AnnualSpend,
p.ProjectedAnnualSaving
FROM tblProjects AS p

OPEN curs1
FETCH NEXT FROM curs1 INTO @lngProject, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave
--Start Loop
WHILE @@fetch_status = 0
BEGIN
--Move to Next Record
FETCH NEXT FROM curs1 INTO @lngProject, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave

UPDATE #DollarValues
SET AnnualSave=@dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject

--If the Currency is Dollars append all Values to Temp Table
IF @Currency ='USD'
--Append Values to Temp Table
UPDATE #DollarValues
SET AnnualSave = @dblAnnualSave, AnnualSpend=@dblAnnualSpend, ProjAnnualSave=@dblProjAnnualSave
WHERE P_ID = @lngProject

--If the Currency is not Dollars
--**** PROBLEM AREA ****
ELSE IF @Currency !='USD'
SET @intCounter=0
--Start Loop, I'm having a problem with this loop and it sets the @@fetch_status to 0
--I need to take the cursor variables and pass them to the dbo.spConversionValue procedure

WHILE @intCounter < 3 BEGIN
DECLARE @dblConversion float
EXEC dbo.spConversionValue @dblConversion OUTPUT, @intCounter, @Currency, @dblAnnualSave, @dblAnnualSpend, @dblProjAnnualSave

--Depending on the Counter value updaet a field in the Temp Table
if @intCounter = 1 --Annual Saving
UPDATE #DollarValues SET AnnualSave = @dblConversion WHERE P_ID = @lngProject
else if @intCounter = 2 --Annual Spend
UPDATE #DollarValues SET AnnualSpend = @dblConversion WHERE P_ID = @lngProject
else if @intCounter = 3 --Projected Saving
UPDATE #DollarValues SET ProjAnnualSave = @dblConversion WHERE P_ID = @lngProject
--Increment the Counter
Set @intCounter=@intCounter+1
END
--**** END PROBLEM AREA ****

END
END

CLOSE curs1
DEALLOCATE curs1

select * from #DollarValues


Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-08-27 : 15:26:49
Do me a favor: give us some sample data and the table structure you are starting with, and then what you hope to return. Forget about how you are currently solving the problem; just tell us what calculations you need to make and what results you are looking to return.

For example:

create table foo (f1,f2,f3)
insert into foo values (1,2,3)
insert into foo values (4,5,6)
insert into foo values (7,8,9)

I would like to return the sum of all columns:

f1,f2,f3
12,15,18


---
then, I have a feeling you will get a really quick and efficient solution not using temp tables, cursors, or loops of any kind.



- Jeff
Go to Top of Page
   

- Advertisement -