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
 General SQL Server Forums
 New to SQL Server Programming
 USING CURSOR

Author  Topic 

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-19 : 22:55:42
I am trying to implement a program by using the cursor. From some reason it does not recognize my declare statement @wScenarioName.

"The error 170 line 31: Incorrect syntax near '@wScenarioName: Must declare variable @wScenarioName"

Hoping someone might be able to look at the attached code (I only included partial for simplcity purposes) and see why I may be receiving the error. Thought a 2nd pair of eyes might help. Thanks for your time in advance.


CREATE PROCEDURE [SOE_SCENARIOS] AS
go
-----------------------------------------------------------------------
-- Declare variable step 1 & 3 will read for the filename
-- and the scenario name it will save
---------------------------------------------------------------------

BEGIN
DECLARE @wScenarioName Varchar(50)

DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun
OPEN cur
FETCH NEXT FROM cur INTO @wScenarioName
WHILE @@fetch_status = 0
BEGIN


------------------------------------
-- Step 1:
-- Creates SOEbyProduct table
------------------------------------

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'SOEbyProduct')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table SOEbyProduct (
Scenario char(20), Product char(50), BankName char(50),
SumOfNotional float, SumOfAvgBal float,
SumOfEOPBal float, SumOfIntCF float, SumOfAmortCF float, SumOfPrepayCF float, SumOfPrinCF float,
SumOfAddAmt float, SumOfFTEIncome float,AvgAccruedInt float, AvgYield float, AvgPeriodCap float,
AvgCap float, AvgFloor float, AvgPriceRateBase float, AvgRepriceSpread float , AvgRepriceRate float)
CREATE INDEX SoeID_IDX on @wScenarioName (AccountID)
-- CREATE INDEX SoeID_IDX on soebasecase (AccountID)
End

ELSE
Truncate TABLE SOEbyProduct


-----------------------------------------------------------------------------
-- Step2:
--
-- CREATES a TEMPORY table for the CvgWriteOut_Account table
-- so that it can PARSE out the AccountName to obtain product & bankname
------------------------------------------------------------------------------
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'Parsed_CVGWriteOut')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table Parsed_CVGWriteout
( [w_id] int,
Scenid int,
Product char(50),
BankName char(50) )

CREATE INDEX ParseID_IDX on Parsed_CVGWriteout(w_id);
END

ELSE
Truncate TABLE SOEbyProduct

Insert into Parsed_CVGWriteOut
([w_id],scenid,product,bankname)

select [id],scenid,
--these would also work if function failed at some point - keep in here
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),2),'#~@','.') as dimension,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),3),'#~@','.') as bank,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),4),'#~@','.') as product

DBO.GetStringAtPos(AccountName,':',1 ),
DBO.GetStringAtPos(AccountName,':',2 )
from dbo.CvgWriteOut_Accounts as w


------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and create a sum/wavg file called SOEbyProduct
--
-------------------------------------------------------------------------------------------

INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)

SELECT 'wScenarioName' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
--from SOEBasecase as s JOIN dbo.Parsed_CVGWriteOut as W
--on w.[w_id]=s.accountid
from Parsed_CVGWriteout as w inner JOIN @wScenarioName as s
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX


FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-19 : 23:50:57
The code is incorrect .

CREATE PROCEDURE [SOE_SCENARIOS] AS
go
-----------------------------------------------------------------------
-- Declare variable step 1 & 3 will read for the filename
-- and the scenario name it will save
---------------------------------------------------------------------

BEGIN
DECLARE @wScenarioName Varchar(50)

DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun
OPEN cur
FETCH NEXT FROM cur INTO @wScenarioName
WHILE @@fetch_status = 0
BEGIN


------------------------------------
-- Step 1:
-- Creates SOEbyProduct table
------------------------------------

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'SOEbyProduct')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table SOEbyProduct (
Scenario char(20), Product char(50), BankName char(50),
SumOfNotional float, SumOfAvgBal float,
SumOfEOPBal float, SumOfIntCF float, SumOfAmortCF float, SumOfPrepayCF float, SumOfPrinCF float,
SumOfAddAmt float, SumOfFTEIncome float,AvgAccruedInt float, AvgYield float, AvgPeriodCap float,
AvgCap float, AvgFloor float, AvgPriceRateBase float, AvgRepriceSpread float , AvgRepriceRate float)

CREATE INDEX SoeID_IDX on soebasecase (AccountID) --Index can only be created on tables or views but not on variable. End

ELSE
Truncate TABLE SOEbyProduct


-----------------------------------------------------------------------------
-- Step2:
--
-- CREATES a TEMPORY table for the CvgWriteOut_Account table
-- so that it can PARSE out the AccountName to obtain product & bankname
------------------------------------------------------------------------------
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'Parsed_CVGWriteOut')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table Parsed_CVGWriteout
( [w_id] int,
Scenid int,
Product char(50),
BankName char(50) )

CREATE INDEX ParseID_IDX on Parsed_CVGWriteout(w_id);
END

ELSE
Truncate TABLE SOEbyProduct

Insert into Parsed_CVGWriteOut
([w_id],scenid,product,bankname)

select [id],scenid,
--these would also work if function failed at some point - keep in here
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),2),'#~@','.') as dimension,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),3),'#~@','.') as bank,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),4),'#~@','.') as product

DBO.GetStringAtPos(AccountName,':',1 ),
DBO.GetStringAtPos(AccountName,':',2 )
from dbo.CvgWriteOut_Accounts as w


------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and create a sum/wavg file called SOEbyProduct
--
-------------------------------------------------------------------------------------------

INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)

SELECT 'wScenarioName' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
--from SOEBasecase as s JOIN dbo.Parsed_CVGWriteOut as W
--on w.[w_id]=s.accountid
from Parsed_CVGWriteout as w inner JOIN @wScenarioName as s -- @wScenarioName is a variable. You cannot join the variable
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX


FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END


Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-19 : 23:59:44
Try this:

CREATE PROCEDURE [SOE_SCENARIOS] AS
-----------------------------------------------------------------------
-- Declare variable step 1 & 3 will read for the filename
-- and the scenario name it will save
---------------------------------------------------------------------

BEGIN
DECLARE @wScenarioName Varchar(50)
DECLARE @sqlStmt Varchar(Max)

DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun

OPEN cur

FETCH NEXT FROM cur INTO @wScenarioName
WHILE @@fetch_status = 0
BEGIN


------------------------------------
-- Step 1:
-- Creates SOEbyProduct table
------------------------------------

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'SOEbyProduct')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table SOEbyProduct (
Scenario char(20), Product char(50), BankName char(50),
SumOfNotional float, SumOfAvgBal float,
SumOfEOPBal float, SumOfIntCF float, SumOfAmortCF float, SumOfPrepayCF float, SumOfPrinCF float,
SumOfAddAmt float, SumOfFTEIncome float,AvgAccruedInt float, AvgYield float, AvgPeriodCap float,
AvgCap float, AvgFloor float, AvgPriceRateBase float, AvgRepriceSpread float , AvgRepriceRate float)


Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')
End
ELSE
Truncate TABLE SOEbyProduct


-----------------------------------------------------------------------------
-- Step2:
--
-- CREATES a TEMPORY table for the CvgWriteOut_Account table
-- so that it can PARSE out the AccountName to obtain product & bankname
------------------------------------------------------------------------------
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'Parsed_CVGWriteOut')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table Parsed_CVGWriteout
( [w_id] int,
Scenid int,
Product char(50),
BankName char(50) )

CREATE INDEX ParseID_IDX on Parsed_CVGWriteout(w_id);
END

ELSE
Truncate TABLE SOEbyProduct


Insert into Parsed_CVGWriteOut
([w_id],scenid,product,bankname)

select [id],scenid,
--these would also work if function failed at some point - keep in here
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),2),'#~@','.') as dimension,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),3),'#~@','.') as bank,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),4),'#~@','.') as product

DBO.GetStringAtPos(AccountName,':',1 ),
DBO.GetStringAtPos(AccountName,':',2 )
from dbo.CvgWriteOut_Accounts as w


------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and create a sum/wavg file called SOEbyProduct
--
-------------------------------------------------------------------------------------------

set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)

SELECT ''wScenarioName'' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
--from SOEBasecase as s JOIN dbo.Parsed_CVGWriteOut as W
--on w.[w_id]=s.accountid
from Parsed_CVGWriteout as w inner JOIN ' + @wScenarioName +' as s
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX'

--Print @sqlStmt

Exec (@sqlStmt)



FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END


Regards,
Bohra

I am here to learn from Masters and help new bees in learning.
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-20 : 09:56:34
Hi Bohra,

Thank you for your feedback. I implemented your suggestion and ran into a small issue with step3 where it states

SELECT 'wScenarioName' as Scenario. This actually stores the value of 'wScenarioName', what I really need it to store is the
value in the scenario_name field that it is reading from the ScenariosToRun table. I guess it is the same value as what is stored
in the @wScenarioName. How can I do this?

--------------------
My overall thought process was to use the cursor so that I maybe able to execute the program numerous times, each time referencing a different table (same structure). I just did not want to have to repeat the logic 40+ time. The tablenames it needs to run each time are stored in the 'ScenariosToRun' table within the 'scenario_name' field. The value of this field is also stored
in step3 Select .... as Scenario line.

Maybe there is a quicker and better way? My apologies for my ignorance on this. Your help is greatly appreciate. Regards, cirugio
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-20 : 23:33:17
quote:
Originally posted by cirugio

Hi Bohra,

Thank you for your feedback. I implemented your suggestion and ran into a small issue with step3 where it states

SELECT 'wScenarioName' as Scenario. This actually stores the value of 'wScenarioName', what I really need it to store is the
value in the scenario_name field that it is reading from the ScenariosToRun table. I guess it is the same value as what is stored
in the @wScenarioName. How can I do this?



Replace
SELECT 'wScenarioName' as Scenario,

with

SELECT @wScenarioName as Scenario,

quote:

--------------------
My overall thought process was to use the cursor so that I maybe able to execute the program numerous times, each time referencing a different table (same structure). I just did not want to have to repeat the logic 40+ time. The tablenames it needs to run each time are stored in the 'ScenariosToRun' table within the 'scenario_name' field. The value of this field is also stored
in step3 Select .... as Scenario line.

Maybe there is a quicker and better way? My apologies for my ignorance on this. Your help is greatly appreciate. Regards, cirugio



There are other ways too for avoiding the cursor and using while loop etc..

Try googling.
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-21 : 09:58:50
--
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-21 : 12:31:23
quote:
Originally posted by cirugio

I actually had tried that, but was getting the following error message. I am not sure why, for it is defined in the beginning of the program. Maybe the @sqlstmt plays into it?


Server: Msg 137, Level 15, State 2, Line 8
Must declare the variable '@wScenarioName'.




Since dynamic statement is used, a small change is required.

set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)

SELECT ' + @wScenarioName + ' as Scenario,Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,

Hope now the issue should be resolved.

Regards,
Bohra




I am here to learn from Masters and help new bees in learning.
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-21 : 13:54:24
Hi Bohra,

I changed it to --> SELECT ' +@wScenarioName+ ' as Scenario,
but now getting the following errors:

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOEBaseCase'.
(
7272 row(s) affected)

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOERampDn200'.

(7272 row(s) affected)

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOERampUp200'.

(7272 row(s) affected)

It appears to be returning the correct values (e.g. SOEBASE, SOERampDn200, SoeRampUP200), but that value is needs to be stored in the table SOEbyProduct's Scenario field . I am not sure how to store this value. I thinking some kind of additional quotes. I tried " quotes, but also received an error. Thoughts?
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-22 : 02:02:12
quote:
Originally posted by cirugio

Hi Bohra,

I changed it to --> SELECT ' +@wScenarioName+ ' as Scenario,
but now getting the following errors:

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOEBaseCase'.
(
7272 row(s) affected)

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOERampDn200'.

(7272 row(s) affected)

Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'SOERampUp200'.

(7272 row(s) affected)

It appears to be returning the correct values (e.g. SOEBASE, SOERampDn200, SoeRampUP200), but that value is needs to be stored in the table SOEbyProduct's Scenario field . I am not sure how to store this value. I thinking some kind of additional quotes. I tried " quotes, but also received an error. Thoughts?



My fault. In hurry, i gave incomplete answer.

Try this:

set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)

SELECT '''+ @wScenarioName + ''' as Scenario,
Product,
BankName,
..........


Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-22 : 10:10:36
That worked. Thanks.

But for some reason, even though it looks like it is using the cursor, it is only storing the last value the cursor points to.
For example, the ScenariosToRun table contains the following values:

SOEBaseCase
SOERampDn200
SOERampUp200

When the program runs through the cursor, the only value that gets stored from the
SELECT '''+ @wScenarioName + ''' as Scenario, statement is SOERampUp200 for all the records. Your thoughts on this are greatly appreciated. Regards,cirugio
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-22 : 12:37:19
quote:
Originally posted by cirugio

That worked. Thanks.

But for some reason, even though it looks like it is using the cursor, it is only storing the last value the cursor points to.
For example, the ScenariosToRun table contains the following values:

SOEBaseCase
SOERampDn200
SOERampUp200

When the program runs through the cursor, the only value that gets stored from the
SELECT '''+ @wScenarioName + ''' as Scenario, statement is SOERampUp200 for all the records. Your thoughts on this are greatly appreciated. Regards,cirugio



Do a small check :
1. Print the value of @sqlStmt.
2. Remove the "Insert part" from the statement printed from @sqlstmt. You will be left only with "Select" part.
3. Execute the "Select" part and see if it returns any record.
4. It the step 3 returns the record then it will also be inserted in SOEbyProduct table.

Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-22 : 13:46:08
Ok. I think I found my issue. It looks like I was truncating the ByProduct table each time each looped through and only the last run was being saved. I had to move around my steps and then only execute the WHILE FETCH statement within step3. I think it may be working now, I just need to test a bit further. The issue I am experiencing now is with creating the index on each of the tables. Each time it runs it goes down on an error "There is already an index on table 'SOEBasecase' named 'SoeID_IDX'". I thought a create overwrites any existing idx which may be out there. Thoughts???

Most current logic:

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO


ALTER PROCEDURE [SOE_SCENARIOS] AS

-----------------------------------------------------------------------------
-- Step1:
--
-- CREATES a TEMPORY table containing parsed out data rom the CvgWriteOut_Account table
-- AccountName is parased into two seperate fields containing product & bankname
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'Parsed_CVGWriteOut')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table Parsed_CVGWriteout
( [w_id] int,
Scenid int,
Product char(50),
BankName char(50) )

CREATE INDEX ParseID_IDX on Parsed_CVGWriteout(w_id);
END

ELSE
Truncate TABLE Parsed_CVGWriteout


Insert into Parsed_CVGWriteOut
([w_id],scenid,product,bankname)

select [id],scenid,
--these would also work if function failed at some point - keep in here
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),2),'#~@','.') as dimension,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),3),'#~@','.') as bank,
--replace(parsename(replace(replace(AccountName+'x','.','#~@'),':','.'),4),'#~@','.') as product

DBO.GetStringAtPos(AccountName,':',1 ),
DBO.GetStringAtPos(AccountName,':',2 )
from dbo.CvgWriteOut_Accounts as w


------------------------------------
-- Step 2:
-- Creates SOEbyProduct table - which will stored aggregated data (sum/avgs)
--
------------------------------------

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'SOEbyProduct')
and OBJECTPROPERTY(id, N'IsUserTable') = 1)
Begin
create table SOEbyProduct (
Scenario char(20), Product char(50), BankName char(50),
SumOfNotional float, SumOfAvgBal float,
SumOfEOPBal float, SumOfIntCF float, SumOfAmortCF float, SumOfPrepayCF float, SumOfPrinCF float,
SumOfAddAmt float, SumOfFTEIncome float,AvgAccruedInt float, AvgYield float, AvgPeriodCap float,
AvgCap float, AvgFloor float, AvgPriceRateBase float, AvgRepriceSpread float , AvgRepriceRate float)
End
ELSE
Truncate TABLE SOEbyProduct


------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and aggreates the summed/avegered data into the SOEbyProduct table
-- This step is performed multiple times for each table identified in the dbo.ScenariosToRun
-------------------------------------------------------------------------------------------
BEGIN
DECLARE @wScenarioName Varchar(50)
DECLARE @sqlStmt Varchar (8000)

DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun
OPEN cur

FETCH NEXT FROM cur INTO @wScenarioName
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')
WHILE @@fetch_status = 0
BEGIN

set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)
SELECT '''+ @wScenarioName + ''' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
--from SOEBasecase as s JOIN dbo.Parsed_CVGWriteOut as W
--on w.[w_id]=s.accountid
from Parsed_CVGWriteout as w inner JOIN ' + @wScenarioName +' as s
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX'

--Print @sqlStmt

Exec (@sqlStmt)



FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-23 : 03:24:16
quote:

FETCH NEXT FROM cur INTO @wScenarioName
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')
WHILE @@fetch_status = 0



Index name must be unique.You are trying to create the index with same name in different table. This is not supported.

If this SP is going to be called frequently and the tables to be processed are going to be same then I suggest that you add the index outside the SP.

If for some reason you don't want to add the index outside the SP, then you can use some meaningful name while creating index in the SP.
Ex: SOEBaseCase_AccId_Idx

In the SP, you can check whether the index exists before creating it.
In case it exists then skip the index creation part. In case the index doesn't exists, then create it.


Regards,
Bohra


Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-23 : 08:40:37
Hi Bohar,

Per your suggestion, I modified the logic to check if the index exists. The program is running fine, but it only creates the index the first time around for the SOEBaseCase table but not for the others (SOERampDn200 & SOERampUp20). I tried moving the logic around (see below) to different parts within Step3, but still only creates it for the first time around. Thoughts??



------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and aggreates the summed/avegered data into the SOEbyProduct table
-- This step is performed multiple times for each table identified in the dbo.ScenariosToRun
-------------------------------------------------------------------------------------------
BEGIN
DECLARE @wScenarioName Varchar(50)
DECLARE @sqlStmt Varchar (8000)
DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun
OPEN cur

FETCH NEXT FROM cur INTO @wScenarioName
-- IF NOT EXISTS (SELECT name from sysindexes WHERE name = 'soeid_idx')
-- Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')


WHILE @@fetch_status = 0
BEGIN
IF NOT EXISTS (SELECT name from sysindexes WHERE name = 'soeid_idx')
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')


set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)
SELECT '''+ @wScenarioName + ''' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
--from SOEBasecase as s JOIN dbo.Parsed_CVGWriteOut as W
--on w.[w_id]=s.accountid
from Parsed_CVGWriteout as w inner JOIN ' + @wScenarioName +' as s
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX'

--Print @sqlStmt

Exec (@sqlStmt)



FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-23 : 11:33:46
What version of SQL server you are using ?
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-23 : 11:37:59
Were currently using SQL Server 2000.
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-23 : 11:48:09
quote:

IF NOT EXISTS (SELECT name from sysindexes WHERE name = 'soeid_idx')
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')




Try this:
IF NOT EXISTS (SELECT name from sysindexes WHERE name = 'soeid_idx' and id = object_id(@wScenarioName))
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-23 : 11:51:21
Thanks. I think that did the trick.

I am going to test this program a bit more to ensure it is doing exactly what I need to do. Can you clarify for me before I do that:

1) If I really need the first BEGIN statement in step 3?
when I developed it, I was basing it off another example. It appears to run without it.

2) I am trying to understand why I need the set @sqlStmt = ' ? Would you mind providing me with a brief explanatin.
I want to ensure I have a good understnading so that if I have to code another cursor, I understand the reasoning behind it.

3) Last question, can you clarify for me why the following statemetn has to be an EXCEC and use ticks :
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')


------------------------------------------------------------------------------------------
-- Step3:
--
-- Performs match b/w the above 2 files and aggreates the summed/avegered data into the SOEbyProduct table
-- This step is performed multiple times for each table identified in the dbo.ScenariosToRun
-------------------------------------------------------------------------------------------
BEGIN
DECLARE @wScenarioName Varchar(50)
DECLARE @sqlStmt Varchar (8000)
DECLARE cur CURSOR FOR
SELECT scenario_name FROM ScenariosToRun
OPEN cur

FETCH NEXT FROM cur INTO @wScenarioName

WHILE @@fetch_status = 0
BEGIN
IF NOT EXISTS (SELECT name from sysindexes WHERE name = 'soeid_idx' and id = object_id(@wScenarioName))
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')

set @sqlStmt = 'INSERT INTO SOEbyProduct
(Scenario, Product, BankName,
SumOfNotional, SumOfAvgBal,
SumOfEOPBal, SumOfIntCF, sumOfAmortCF, SumOfPrepayCF, SumOfPrinCF,
SumOfAddAmt, SumOfFTEIncome, AvgAccruedInt, AvgYield, AvgPeriodCap,
AvgCap, AvgFloor, AvgPriceRateBase, AvgRepriceSpread, AvgRepriceRate)
SELECT '''+ @wScenarioName + ''' as Scenario,
Product,
BankName,
sum(s.notional) as SumOfNotional,
sum(s.avgbal) as SumOfAvgBal,
sum(s.eopbal) as SumOfEOPBAL,
sum(s.Intcf) as SumOfIntCF,
sum(s.amortCF) as SumOfAmortCF,
sum(s.prepaycf) as SumOfPrepayCF,
sum(s.princf) as SumofPrinCF,
-- if null value in field replaces it with 0.0 since floating, otherwise if int would have used 0
sum (coalesce(s.addamt,0.0)) as SumAddamt,
sum(coalesce(s.FTEIncome,0.0)) as SumofFTEIncome,
sum(s.[accruedint]*s.[eopbal])/NULLIF(sum(s.[eopbal]),0.0) as AvgAccruedInt,
sum(coalesce(s.[avgyld],0.0)*s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgYield,
sum(s.[PeriodicCap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPeriodCap,
sum(s.[Cap] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgCap,
sum(s.[Floor] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgFloor,
sum(s.[ReprRateBase] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgPriceRateBase,
sum(s.[ReprRateAvgAdj] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceSpread,
sum(s.[ReprRate] *s.[eopbal])/nullif(sum(s.[eopbal]),0.0) as AvgRepriceRate
from Parsed_CVGWriteout as w inner JOIN ' + @wScenarioName +' as s
on w.[w_id]=s.accountid
group by PRODUCT,BANKNAME,S.SCENDATEINDEX'

--Print @sqlStmt

Exec (@sqlStmt)

FETCH NEXT FROM CUR INTO @Wscenarioname

END
CLOSE cur
DEALLOCATE cur
END
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-23 : 12:02:57
quote:
Originally posted by cirugio

OK. I will try it out now and will get back to you shortly. In the meanwhile, can you tell me do you think I need that 1st set of begin in the program? I was following another example, but not sure if its necessary??



If you meant that Table creation and index creation are required in Begin and End then my answer is Yes.

Begin
create table Parsed_CVGWriteout
( [w_id] int,
Scenid int,
Product char(50),
BankName char(50) )

CREATE INDEX ParseID_IDX on Parsed_CVGWriteout(w_id);
END

If you question was something different then let us know the same.
Go to Top of Page

cirugio
Yak Posting Veteran

90 Posts

Posted - 2010-07-23 : 12:09:55
Sorry, I modified my reply (see my previous post). I actually meant the 1st BEGIN statement in Step3.
Also, hope you don't mind the additional questions I posted . I have
such a large learning curve to accomplish, but please note that your help is so
greatly appreciated.
Go to Top of Page

pk_bohra
Master Smack Fu Yak Hacker

1182 Posts

Posted - 2010-07-23 : 12:25:44
quote:

1) If I really need the first BEGIN statement in step 3?
when I developed it, I was basing it off another example. It appears to run without it.



The first begin is not essential but you can still keep it. This will help you in differentiating the blocks. (Easy readability


quote:

2) I am trying to understand why I need the set @sqlStmt = ' ? Would you mind providing me with a brief explanatin.
I want to ensure I have a good understnading so that if I have to code another cursor, I understand the reasoning behind it.



Since the table name needs to be read from another table and to be used in select query, We have to use dynamic query.

You can remove the @sqlStmt = ' and put the complete statement in Exec(' block, it will still work.
The reason for using the variable is, if required while debugging we can print the value of variable.
It is generally recommended to store such big chunks in a variable and execute it instead of keeping such big statement in Exec(' block directly.



quote:

3) Last question, can you clarify for me why the following statemetn has to be an EXCEC and use ticks :
Exec ('CREATE INDEX SoeID_IDX on ' + @wScenarioName +' (AccountID)')




Exec (' :- This is one of way of dynamic execution in SQL server. It have its own Pros and cons. Google for dynamic exeuction in Sql server and you will find lot of information.

Go to Top of Page
    Next Page

- Advertisement -