April 4, 2007 at 11:17 pm
Hi All,
I want to avoid cursors. Will I get any advantage if doing the same thing in extended stored procedure (iterating each record using native C and apply custom instructions). Will I get performance benefits comparing to sql cursors ? Any help / suggestion will help me alot.
Thanks & Regards,
Govind Bhavan
April 5, 2007 at 7:25 am
There are many ways to avoid using cursors depending on how and what you want to do. I never use extended stored procedure but I am able to avoid using cursor. Unless you give me an example, it is hard to give you any suggestion.
April 5, 2007 at 9:11 am
Thanks loner.
Its a FIFO based costing routine. Source of cost have multiple paths, i.e. Exact item received / purchased, Std cost, Conversion of items (cost carrying & Issuing item differ from receiving item for a job) etc.
Here is the sample of code
DECLARE CUR CURSOR FAST_FORWARD READ_ONLY FOR
SELECT Z.ROWNO, Z.TYPE
, Z.DEPT, Z.ACT_DEPT
, Z.ITEMTYPEID, Z.ITEMID, ISNULL(Z.SRC_ITEMID,-2) AS [SRC_ITEMID]
, CASE WHEN Z.ITEMTYPEID IN (1) THEN Z.SHADE ELSE '' END AS [SHADE], Z.REF
, ISNULL(Z.DOC,'') AS [DOC], Z.DO_SERIAL
, CASE WHEN Z.TYPE = 'R' THEN REC_VALUE ELSE ISS_VALUE END AS [VALUE]
, CASE WHEN Z.TYPE = 'R' THEN RATE ELSE ISS_RATE END AS [RATE]
, CASE WHEN Z.TYPE = 'R' THEN CB_QTY ELSE ISS_QTY END AS [QTY]
, CASE WHEN Z.TYPE = 'R' THEN CB_QTY ELSE ISS_QTY END - Z.CALC_QTY AS [QTYBAL]
, ISNULL(MAIN_DEPT.RMWAREHOUSE,0) AS [RMWAREHOUSE]
, ISNULL(MAIN_DEPT.WPDWAREHOUSE,0) AS [WPDWAREHOUSE]
, ISNULL(MAIN_DEPT.FINISHINGWAREHOUSE,0) AS [FINISHINGWAREHOUSE]
, ISNULL(MAIN_DEPT.TWISTINGWAREHOUSE,0) AS [TWISTINGWAREHOUSE]
, ISNULL(MAIN_DEPT.WBCWAREHOUSE,0) AS [WBCWAREHOUSE]
, ISNULL(MAIN_DEPT.DCWAREHOUSE,0) AS [DCWAREHOUSE]
, ISNULL(MAIN_DEPT.MUMWAREHOUSE,0) AS [MUMWAREHOUSE]
, ISNULL(MAIN_DEPT.ISMILLSTORE,0) AS [ISMILLSTORE]
, ISNULL(MAIN_DEPT.ISCOLORLAB,0) AS [ISCOLORLAB]
, ISNULL(MAIN_DEPT.ISVENDOR,0) AS [ISVENDOR]
, ISNULL(MAIN_DEPT.ISQCD,0) AS [ISQCD]
, ISNULL(MAIN_DEPT.FGWAREHOUSE,0) AS [FGWAREHOUSE]
, ISNULL(ACT_DEPT.FGWAREHOUSE,0) AS [ACT_FGWAREHOUSE]
FROM TMP_COSTLEDGER Z
INNER JOIN DEPARTMENTS MAIN_DEPT ON Z.DEPT = MAIN_DEPT.DEPTCODE
LEFT JOIN DEPARTMENTS ACT_DEPT ON Z.ACT_DEPT = ACT_DEPT.DEPTCODE
WHERE (ISNULL(MAIN_DEPT.FGWAREHOUSE,0) = 0 OR Z.SOURCE <> 'RECEIVE')
AND Z.TYPE IN ('I')
AND Z.CALC_QTY < (Z.ISS_QTY + Z.REC_QTY)
AND Z.ITEMTYPEID IN (1,2,3,4)
AND Z.SOURCE NOT IN ('OPENING','PURCHASE','PURCHASE_RETURN','SALE','SALE_RETURN','SAMPLE')
AND EXISTS (SELECT X.ROWNO FROM TMP_COSTLEDGER X
INNER JOIN DEPARTMENTS DEPT ON X.DEPT = DEPT.DEPTCODE
LEFT JOIN DEPARTMENTS TODEPT ON X.ACT_DEPT = TODEPT.DEPTCODE WHERE 1 = 1
AND ( (X.ITEMID = Z.ITEMID OR X.ITEMID = ISNULL(Z.SRC_ITEMID,0) OR Z.ITEMID = ISNULL(X.SRC_ITEMID,0) OR ISNULL(X.SRC_ITEMID,-1) = ISNULL(Z.SRC_ITEMID,0) )
OR ( (ISNULL(DEPT.WPDWAREHOUSE,0) = 1 OR ISNULL(DEPT.FINISHINGWAREHOUSE,0) = 1) AND X.ITEMTYPEID = Z.ITEMTYPEID AND X.REF = Z.REF))
AND X.TYPE IN ('I','R')
AND (X.REF = Z.REF OR ISNULL(DEPT.RMWAREHOUSE,0) = 1 OR ISNULL(DEPT.DCWAREHOUSE,0) = 1 OR ISNULL(DEPT.MUMWAREHOUSE,0) = 1 OR ISNULL(DEPT.ISMILLSTORE,0) = 1 OR ISNULL(DEPT.DCWAREHOUSE,0) = 1 OR ISNULL(DEPT.FGWAREHOUSE,0) = 1 OR ISNULL(DEPT.ISCOLORLAB,0) = 1 OR ISNULL(DEPT.ISQCD,0) = 1 OR ISNULL(DEPT.ISVENDOR,0) = 1 )
AND X.USED_QTY < (X.ISS_QTY + X.REC_QTY + X.OPEN_QTY)
AND X.CALC_QTY >= ABS(X.CB_QTY)
AND ISNULL(CASE WHEN X.TYPE = 'R' THEN X.RATE ELSE X.ISS_RATE END,0) <> 0.0
AND CASE WHEN X.TYPE = 'R' THEN X.DEPT ELSE X.ACT_DEPT END = Z.DEPT
 
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN CB_QTY ELSE ISS_QTY END - Z.CALC_QTY,0) > 0.0
ORDER BY CASE WHEN Z.DOC = 'ADJ' AND Z.TYPE = 'I' THEN 999 ELSE 1 END, Z.TYPE, Z.[DATE], Z.ITEMTYPEID, Z.COSTINGSORTNO, Z.DEPT, Z.ITEMID, Z.SHADE, CASE WHEN Z.REF = '' THEN 'Z999999' ELSE Z.REF END, Z.ROWNO
OPEN CUR
FETCH NEXT FROM CUR
INTO @ROWNO, @TYPE, @DEPT, @ACT_DEPT, @ITEMTYPEID, @ITEMID, @SRC_ITEMID, @SHADE, @REF, @DOC, @DO_SERIAL, @VALUE, @RATE, @QTY, @QTYBAL, @RMWAREHOUSE , @WPDWAREHOUSE , @FINISHINGWAREHOUSE , @TWISTINGWAREHOUSE , @WBCWAREHOUSE , @DCWAREHOUSE , @MUMWAREHOUSE , @ISMILLSTORE , @ISCOLORLAB , @ISVENDOR , @ISQCD , @FGWAREHOUSE, @ACT_FGWAREHOUSE
WHILE @@FETCH_STATUS = 0
BEGIN
SET @TOTAL_CALCQTY = 0
WHILE (1 = 1)
BEGIN
IF (@QTYBAL > 0.0)
BEGIN
SET @CURRUSED = 0
SET @ROWFOUND = NULL
SELECT @ROWFOUND = MIN(Z.ROWNO) FROM TMP_COSTLEDGER Z
INNER JOIN DEPARTMENTS DEPT ON Z.DEPT = DEPT.DEPTCODE
LEFT JOIN DEPARTMENTS TODEPT ON Z.ACT_DEPT = TODEPT.DEPTCODE
WHERE Z.ROWNO <> @ROWNO AND Z.ITEMID IN (@ITEMID, @SRC_ITEMID)
AND Z.TYPE IN ('I','R') AND (@ITEMTYPEID <> 1 OR Z.SHADE = @SHADE)
AND Z.USED_QTY < (Z.ISS_QTY + Z.REC_QTY + Z.OPEN_QTY)
AND (@RMWAREHOUSE = 1 OR @DCWAREHOUSE = 1 OR @MUMWAREHOUSE = 1 OR @FGWAREHOUSE = 1 OR @ISMILLSTORE = 1 OR Z.REF = @REF OR @REF = '')
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END,0) <> 0.0
AND CASE WHEN Z.TYPE = 'R' THEN Z.DEPT ELSE Z.ACT_DEPT END = @DEPT
AND Z.CALC_QTY >= ABS(Z.CB_QTY)
IF ((@ROWFOUND IS NULL) AND (@WPDWAREHOUSE = 0 AND @FINISHINGWAREHOUSE = 0))
SELECT @ROWFOUND = MIN(Z.ROWNO) FROM TMP_COSTLEDGER Z
INNER JOIN DEPARTMENTS DEPT ON Z.DEPT = DEPT.DEPTCODE
LEFT JOIN DEPARTMENTS TODEPT ON Z.ACT_DEPT = TODEPT.DEPTCODE
WHERE Z.ROWNO <> @ROWNO AND Z.SRC_ITEMID IN (@ITEMID, @SRC_ITEMID)
AND Z.TYPE IN ('I','R') AND (@ITEMTYPEID <> 1 OR Z.SHADE = @SHADE)
AND Z.USED_QTY < (Z.ISS_QTY + Z.REC_QTY + Z.OPEN_QTY)
AND (@RMWAREHOUSE = 1 OR @DCWAREHOUSE = 1 OR @MUMWAREHOUSE = 1 OR @FGWAREHOUSE = 1 OR @ISMILLSTORE = 1 OR Z.REF = @REF OR @REF = '')
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END,0) <> 0.0
AND CASE WHEN Z.TYPE = 'R' THEN Z.DEPT ELSE Z.ACT_DEPT END = @DEPT
AND Z.CALC_QTY >= ABS(Z.CB_QTY) AND Z.SRC_ITEMID IS NOT NULL
ELSE IF ((@ROWFOUND IS NULL) AND (@WPDWAREHOUSE = 1 OR @FINISHINGWAREHOUSE = 1))
BEGIN
SELECT @ROWFOUND = MIN(Z.ROWNO) FROM TMP_COSTLEDGER Z WHERE
Z.ROWNO <> @ROWNO AND Z.ITEMID IN (@ITEMID, @SRC_ItemId)
AND Z.TYPE IN ('R') AND (@ITEMTYPEID <> 1 OR Z.SHADE = @SHADE)
AND Z.USED_QTY < (Z.ISS_QTY + Z.REC_QTY + Z.OPEN_QTY)
AND Z.REF = @REF
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END,0) <> 0.0
AND CASE WHEN Z.TYPE = 'R' THEN Z.DEPT ELSE Z.ACT_DEPT END = @DEPT
AND Z.CALC_QTY >= ABS(Z.CB_QTY)
IF (@ROWFOUND IS NULL)
SELECT @ROWFOUND = MIN(Z.ROWNO) FROM TMP_COSTLEDGER Z WHERE
Z.ROWNO <> @ROWNO AND Z.ITEMTYPEID = @ITEMTYPEID
AND Z.TYPE IN ('R') AND (@ITEMTYPEID <> 1 OR Z.SHADE = @SHADE)
AND Z.USED_QTY < (Z.ISS_QTY + Z.REC_QTY + Z.OPEN_QTY)
AND Z.REF = @REF
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END,0) <> 0.0
AND CASE WHEN Z.TYPE = 'R' THEN Z.DEPT ELSE Z.ACT_DEPT END = @DEPT
AND Z.CALC_QTY >= ABS(Z.CB_QTY)
IF (@ROWFOUND IS NULL)
SELECT @ROWFOUND = MIN(Z.ROWNO) FROM TMP_COSTLEDGER Z WHERE
Z.ROWNO <> @ROWNO AND Z.SRC_ITEMID IN (@ITEMID, @SRC_ItemId)
AND Z.TYPE IN ('R') AND (@ITEMTYPEID <> 1 OR Z.SHADE = @SHADE)
AND Z.USED_QTY < (Z.ISS_QTY + Z.REC_QTY + Z.OPEN_QTY)
AND Z.REF = @REF
AND ISNULL(CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END,0) <> 0.0
AND CASE WHEN Z.TYPE = 'R' THEN Z.DEPT ELSE Z.ACT_DEPT END = @DEPT
AND Z.CALC_QTY >= ABS(Z.CB_QTY) AND Z.SRC_ITEMID IS NOT NULL
END --NOT FOUND
IF (@ROWFOUND IS NOT NULL)
BEGIN
SET @bRecordFound = 1
SELECT @FOUND_VALUE = CASE WHEN Z.TYPE = 'R' THEN Z.CB_VALUE ELSE Z.ISS_VALUE END
, @FOUND_RATE = CASE WHEN Z.TYPE = 'R' THEN Z.RATE ELSE Z.ISS_RATE END
, @FOUND_QTY = CASE WHEN Z.TYPE = 'R' THEN Z.CB_QTY ELSE Z.ISS_QTY END
, @FOUND_USEDQTY = Z.USED_QTY
FROM TMP_COSTLEDGER Z WHERE Z.ROWNO = @ROWFOUND
IF (@FOUND_RATE IS NULL)
RAISERROR ('RATE IS NULL', 16, 1)
If ((@FOUND_QTY - @FOUND_USEDQTY) >= @QTYBAL)
SET @CURRUSED = @QTYBAL
Else
SET @CURRUSED = (@FOUND_QTY - @FOUND_USEDQTY)
SET @QTYBAL = @QTYBAL - @CURRUSED
UPDATE TMP_COSTLEDGER SET USED_QTY = USED_QTY + @CURRUSED WHERE ROWNO = @ROWFOUND
SET @VALUE = (@VALUE + (@CURRUSED * @FOUND_RATE))
If (@CURRUSED > 0.0)
BEGIN
INSERT INTO TMP_COSTLEDGER_DETAIL (ROWFK, REF_ROWFK, COSTTYPEID, STAGEID, ITEMTYPEID, QTY, RATE, VALUE,
ACTUAL_COST, WIP, REMARKS, INDIRECT, OPENING_ENTRY)
SELECT @ROWNO, @ROWFOUND, 1 AS [COSTTYPEID], NULL STAGEID, @ITEMTYPEID,
@CURRUSED, @FOUND_RATE, @CURRUSED * @FOUND_RATE AS VALUE, 0 AS ACTUAL_COST, 0 AS WIP,
'MAT FIFO ' + CAST(@iLoopCounter AS VARCHAR(5)), 0 AS INDIRECT, 0 AS OPENING_ENTRY
UPDATE TMP_COSTLEDGER SET
@TOTAL_CALCQTY = CALC_QTY + @CURRUSED
, CALC_QTY = CALC_QTY + @CURRUSED
, REC_VALUE = CASE WHEN TYPE IN ('R') THEN @VALUE ELSE ISNULL(REC_VALUE,0) END
, ISS_VALUE = CASE WHEN TYPE IN ('I') THEN @VALUE ELSE ISNULL(ISS_VALUE,0) END
, REC_RATE = CASE WHEN TYPE IN ('R') THEN @VALUE / @QTY ELSE ISNULL(REC_RATE,0) END
, ISS_RATE = CASE WHEN TYPE IN ('I') THEN @VALUE / @QTY ELSE ISNULL(ISS_RATE,0) END
, RATE = @VALUE / @QTY
, CB_VALUE = CASE WHEN TYPE IN ('I') THEN -1 ELSE 1 END * @VALUE
, CB_RATE = @VALUE / @QTY
WHERE ROWNO = @ROWNO
END --CURRUSED > 0.0
END --FOUND
ELSE IF (@ROWFOUND IS NULL)
GOTO INNER_SKIP1
END -- QTYBAL
IF (ROUND(@QtyBal, 4) <= 0) AND (ABS(@TOTAL_CALCQTY - @QTY) > 0)
BEGIN
UPDATE TMP_COSTLEDGER SET @CALC_QTY = @QTY, CALC_QTY = @QTY WHERE ROWNO = @ROWNO
SET @QtyBal = 0
SET @TOTAL_CALCQTY = @QTY
END
IF ((@TYPE = 'I') AND (@DOC NOT IN ('ADJ','')) AND (@QTY <> 0.0))
BEGIN
SET @b-2 = 0
IF ((@TOTAL_CALCQTY >= @QTY) OR (@B = 1))
BEGIN
IF ((@ACT_FGWAREHOUSE = 0) OR (@ITEMTYPEID = 4))
BEGIN
SET @@USED_QTY_IN_REF = 0
SELECT @RATE = RATE, @USED_QTY = ISNULL(USED_QTY,0), @CALC_QTY = CALC_QTY FROM TMP_COSTLEDGER WHERE ROWNO = @ROWNO
EXEC CostProc_UpdateRefCost @ROWNO , @DEPT, @ACT_DEPT ,
@TYPE , @ITEMTYPEID , @ITEMID , @SRC_ITEMID ,
@SHADE , @REF , @DOC , @DO_SERIAL ,
@VALUE , @RATE , @QTY , @CALC_QTY , @USED_QTY ,
@@USED_QTY_IN_REF OUTPUT
, @iLoopCounter
IF (ISNULL(@@USED_QTY_IN_REF,0) <> 0)
UPDATE TMP_COSTLEDGER SET USED_QTY = @@USED_QTY_IN_REF WHERE ROWNO = @ROWNO
END --NOT TO FWH OR MUM
END --UPDATE RECEIVING
END --TYPE = 'I'
SET @b-2 = CASE WHEN (@ROWFOUND IS NULL) THEN 1 ELSE 0 END
IF (@B = 0)
SET @b-2 = CASE WHEN ABS(@QTY) - @TOTAL_CALCQTY <= 0 THEN 1 ELSE 0 END
IF (@B = 1)
GOTO INNER_SKIP1 --ESCAPE FROM INFINITE LOOP & GOTO MAIN RECORD LOOP
END --INNERLOOP
INNER_SKIP1:
FETCH NEXT FROM CUR
INTO @ROWNO, @TYPE, @DEPT, @ACT_DEPT, @ITEMTYPEID, @ITEMID, @SRC_ITEMID, @SHADE, @REF, @DOC, @DO_SERIAL, @VALUE, @RATE, @QTY, @QTYBAL, @RMWAREHOUSE , @WPDWAREHOUSE , @FINISHINGWAREHOUSE , @TWISTINGWAREHOUSE , @WBCWAREHOUSE , @DCWAREHOUSE , @MUMWAREHOUSE , @ISMILLSTORE , @ISCOLORLAB , @ISVENDOR , @ISQCD , @FGWAREHOUSE, @ACT_FGWAREHOUSE
END --CURSOR
CLOSE CUR
DEALLOCATE CUR
END -- @iLoopCounter <= 2
The procedure also transfer computed cost to other production area until in Finished form, by exeucting another stored procedure write after completion of every single transaction. Right now the server is executing 3 transactions per second. Approx I have 50000 transaction to compute viz 5 Hrs.
Please help me to boost this thing.
Regards,
Govind Bhavan
April 6, 2007 at 6:02 am
Additionally is Sql 2005 CLR integration can be a good solution for this problem w.r.t performance ?
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply