Cursors vs Select Statements

- A difference in T-SQL versus Progress is that in progress Insert, Delete, and Update were performed in a record by record basis. In T-SQL the Insert, Update and Delete Statements can be performed on a group of records (ie: a loop). This greatly reduces the amount of cursors that are required.

- Another difference is doing INNER JOINS and WHERE stmts on the UPDATEs and SELECTs, this controls the data that is involved and allows for exclusion of the Cursor

Syntax:

INSERT/UPDATE/DELETE

UPDATE [table] SET [Column] FROM [table] INNER JOIN (lefttable.field = righttable.field)

WHERE [certain condition(s) are true]

Example:

UPDATE jobmatl

SET scrap_fact FROM jobmatl

INNER JOIN item ON (jobmatl.item = item.item)

INNER JOIN job ON (jobmatl.job = job.job and jobmatl.suffix = job.suffix)

WHERE

charindex(job.type, @job_type) > 0

and jobmatl.item >= @StartItem

and jobmatl.item <= @EndItem

and item.product_code >= @StartProdCode

and item.product_code <= @EndProdCode

Here is a sample of T-sql Procedure where the cursor was removed and the update and select statements were added. The processing time went from 15 mins to about 15 secs. The removed logic is in red, the added logic is in blue.

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_NULLS ON

GO

Create PROCEDURE dbo.CAR_ScrapU1Sp (

@t_scrap decimal(5,4)= NULL

,@job_type nvarchar(3)= NULL

,@StartItem ItemType= NULL

,@EndItem ItemType= NULL

,@StartProdCode ProductCodeType= NULL

,@EndProdCode ProductCodeType= NULL

,@t_post Tinyint= NULL

,@DisplayHeader Tinyint= NULL

)

AS

-- expand columns out on key report options and check for NULL input start

SET @t_scrap= ISNULL(@t_scrap,0.0000)

SET @Job_Type= ISNULL(@Job_Type, 'S')

SET @StartItem= ISNULL(dbo.ExpandKyByType('ItemType', @StartItem), dbo.LowString('ItemType'))

SET @EndItem= ISNULL(dbo.ExpandKyByType('ItemType', @EndItem), dbo.HighString('ItemType'))

SET @StartProdCode= ISNULL(dbo.ExpandKyByType('ProductCodeType', @StartProdCode), dbo.LowString('ProductCodeType'))

SET @EndProdCode= ISNULL(dbo.ExpandKyByType('ProductCodeType', @EndProdCode), dbo.HighString('ProductCodeType'))

SET @t_post= ISNULL(@t_post,0)

SET @DisplayHeader= ISNULL(@DisplayHeader,0)

--select @t_scrap ,@job_type ,@StartItem ,@EndItem ,@StartProdCode ,@EndProdCode ,@t_post ,@DisplayHeader --debug

-- expand columns out on key report options and check for NULL input end

--Var Declarations - start

declare

@t_jobnvarchar(15)

-- Cursor Vars - start

,@CurJMItemas nvarchar(30)

,@CurIDescriptionas nvarchar(40)

,@CurIProductCodeas nvarchar(10)

,@CurJMScrapFactoras decimal(5,4)

,@CurJTypeas nvarchar(1)

,@CurJJobas JobType

,@CurJSUffixas SuffixType

-- Cursor Vars - end

-- Var Declarations - end

--create temp tables for result set

/*

declare @ResultSet table (

ResultItemnvarchar(30)

, ResultDescriptionnvarchar(40)

, ResultProduct_Codenvarchar(10)

, ResultScrapFactordecimal(5,4)

, ResultTypenvarchar(1)

, ResultJobnvarchar(20)

, ResultSuffixsmallint

)

declare JobMatlItemJobCursor CURSOR for

select

jobmatl.item

,item.description

,item.Product_Code

,jobmatl.scrap_fact

,job.type

,job.job

,job.suffix

from jobmatl

inner JOIN item on (jobmatl.item = item.item)

inner join job on (jobmatl.job = job.job and jobmatl.suffix = job.suffix)

where

charindex(job.type, @job_type) > 0

and jobmatl.item >= @StartItem

and jobmatl.item <= @EndItem

and item.product_code >= @StartProdCode

and item.product_code <= @EndProdCode

Open JobMatlItemJobCursor

--fetches first record for cursor

While 1=1

Begin

FETCH NEXT FROM JobMatlItemJobCursor INTO @CurJMItem

,@CurIDescription

,@CurIProductCode

,@CurJMScrapFactor

,@CurJType

,@CurJJob

,@CurJSuffix

if @@Fetch_status != 0 break --stop when reach EOF and @@FetchStatus = -1

-- logic to update the scrap factor

if @t_post = 1

Begin

update jobmatl

set scrap_fact = @t_scrap

End -- end if @t_post =1

insert into @ResultSet

(

ResultItem

, ResultDescription

, ResultProduct_Code

, ResultScrapFactor

, ResultType

, ResultJob

, ResultSuffix

)

values

(

@CurJMItem

,@CurIDescription

,@CurIProductCode

,@CurJMScrapFactor

,@CurJType

,@CurJJob

,@CurJSuffix

)

End -- End FETCH NEXT FROM JobMatlItemJobCursor

Close JobMatlItemJobCursor

Deallocate JobMatlItemJobCursor

*/

if @t_post = 1

Begin

update jobmatl set scrap_fact = @t_scrap from jobmatl

inner JOIN item on (jobmatl.item = item.item)

inner join job on (jobmatl.job = job.job and jobmatl.suffix = job.suffix)

where

charindex(job.type, @job_type) > 0

and jobmatl.item >= @StartItem

and jobmatl.item <= @EndItem

and item.product_code >= @StartProdCode

and item.product_code <= @EndProdCode

End /* end if @t_post = 1 */

select jobmatl.item, item.description, item.product_code, jobmatl.scrap_fact

from jobmatl

inner JOIN item on (jobmatl.item = item.item)

inner join job on (jobmatl.job = job.job and jobmatl.suffix = job.suffix)

where

charindex(job.type, @job_type) > 0

and jobmatl.item >= @StartItem

and jobmatl.item <= @EndItem

and item.product_code >= @StartProdCode

and item.product_code <= @EndProdCode

GO

SET QUOTED_IDENTIFIER OFF

GO

SET ANSI_NULLS ON

GO