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 |
jay_snow
Starting Member
3 Posts |
Posted - 2013-08-30 : 05:31:17
|
Hi ,I have inherrited a system with a lot of hideously unoptimized code, i am currently trying to remove a cursor from a job that takes a LONG time to run every night. However i dont seem to be able to replicate what its doing with set based logic. I know what i want to do, get the data into a temp table and use a case statement to determine which rows should have the proc executed. However i have not been able to get this to work yet...............does anyone have any examples for code i can use as an alternative to this cursor.............any tips pointers or examples would be greatly appreciated.-- INFLATE THE STOCK IN MOMIF (@SYNCTYPE='INCREMENT')BEGIN DECLARE C1 CURSOR FOR -- SHOW THE RESULTS SELECT NUMBER, MOM_AVAIL_STOCK, MOM_PHYS_STOCK, WH_PHYS_STOCK, WH_PHYS_STOCK - MOM_PHYS_STOCK AS DIFF FROM @RES WHERE MOM_PHYS_STOCK != WH_PHYS_STOCK AND (WH_PHYS_STOCK - MOM_PHYS_STOCK) > 0 ORDER BY NUMBER OPEN C1 FETCH NEXT FROM C1 INTO @N, @MA, @MP, @WP, @D WHILE @@FETCH_STATUS = 0 BEGIN IF (@D != 0) BEGIN EXEC MOM$BRAINTREESTOCKSYNC @NUMBER=@N,@UNITS=@D,@USERID='WEB',@NOTATION='BRAINTREE Stock Sync' END FETCH NEXT FROM C1 INTO @N, @MA, @MP, @WP, @D END CLOSE C1 DEALLOCATE C1END Jay_Snow |
|
bandi
Master Smack Fu Yak Hacker
2242 Posts |
Posted - 2013-08-30 : 05:48:06
|
What is the purpose of stored procedure "MOM$BRAINTREESTOCKSYNC"Depends on the above logic we can make out changes--Chandu |
 |
|
jay_snow
Starting Member
3 Posts |
Posted - 2013-08-30 : 07:56:59
|
Thanks for the reply! This is the code for the proc.........USE [MailOrderManager]GO/****** Object: StoredProcedure [dbo].[MOM$BRAINTREESTOCKSYNC] Script Date: 30/08/2013 11:35:30 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO-- Make changes to the bin quantities -- neilb: 2010-10-14 - First Draft-- neilb: 2010-10-23 - Write to POP..MOM_SUSPENSE and add @NOTATION-- neilb: 2011-03-17 - Convert for use with BRAINTREE Bins-- davidh: 2011-04-06 - If no bin exists we must ALTER oneALTER PROCEDURE [dbo].[MOM$BRAINTREESTOCKSYNC] ( @NUMBER varchar(20), @UNITS int, @USERID varchar(20), @NOTATION varchar(255))ASSET NOCOUNT ON-- ========================================================-- Declare Variables-- ========================================================DECLARE @BIN_ID int -- Bin_id of the bin we are going to inflate / deflateDECLARE @SBIN_ID int -- Suspense Bin_idDECLARE @INVENT_ID int -- Used as the key for the FIFO pricing tableDECLARE @UNITCOST NUMERIC(12,2) -- Unit Cost for FIFO pricingDECLARE @TRANS_ID int -- Used as the key for the transaction tableDECLARE @NEWINVTOTAL NUMERIC(12,2) -- Total Of Units-- ========================================================-- Setup some variables used throughout the script.-- ========================================================SELECT TOP 1 @BIN_ID=BIN_ID FROM BIN WITH (NOLOCK) WHERE BINDESC='BRAINTREE' AND NUMBER=@NUMBERSELECT TOP 1 @NEWINVTOTAL=NEWINVTOT FROM INVTRANS WITH (NOLOCK) WHERE NUMBER=@NUMBER ORDER BY TRANS_ID DESCSELECT TOP 1 @UNITCOST=COLSCOST FROM ST_EXTRA WHERE NUMBER=@NUMBERIF @BIN_ID IS NULLBEGIN -- =========================================== -- Insert a row into the bin table -- =========================================== INSERT INTO MailOrderManager..BIN DEFAULT VALUES SELECT @BIN_ID = @@IDENTITY UPDATE MailOrderManager..BIN SET NUMBER=UPPER(@NUMBER), BINDESC='BRAINTREE', STATUS='A', SELL_PRIOR=1 WHERE BIN_ID = @BIN_IDEND-- ========================================================-- Increase the amount in the bin-- Inflate the stock-- ========================================================IF (@UNITS > 0)BEGIN -- Increase the value of stock we have bound to this bin -- ======================================================== -- Insert New Inventor Row -- ======================================================== INSERT INTO INVENTOR DEFAULT VALUES SELECT @INVENT_ID=@@IDENTITY UPDATE INVENTOR SET NUMBER = @NUMBER, DELIV_DATE = dateadd(dd,0, datediff(dd,0,GETDATE())), UNIT_COST = IsNull(@UNITCOST,0), DELIV_QTY = @UNITS, UNITS = @UNITS, BIN_ID = @BIN_ID WHERE INVENT_ID = @INVENT_ID -- ======================================================== -- UPDATE THE QTY IN THE SOURCE AND TARGET BINS -- ======================================================== UPDATE BIN SET UNITS = UNITS + @UNITS WHERE BIN_ID = @BIN_ID -- ======================================================== -- UPDATE THE QTY IN THE STOCK TABLE -- ======================================================== --UPDATE STOCK SET -- UNITS = UNITS + @UNITS --WHERE -- NUMBER = @NUMBER -- ======================================================== -- INSERT NEW ROW TO THE INVTRANS TABLE -- ======================================================== INSERT INTO INVTRANS DEFAULT VALUES SELECT @TRANS_ID=@@IDENTITY UPDATE INVTRANS SET NUMBER = @NUMBER, INVENT_ID = @INVENT_ID, TRANS_DATE = dateadd(dd,0, datediff(dd,0,GETDATE())), TRANSTYPE = 'A', QUANTITY = @UNITS, UNIT_COST = IsNull(@UNITCOST,0), TOTAL_AMT = IsNull(@UNITCOST,0) * @UNITS, USERID = @USERID, NEWINVTOT = IsNull(@NEWINVTOTAL,0) + @UNITS, NOTATION = @NOTATION, BIN_ID = @BIN_ID WHERE TRANS_ID = @TRANS_IDENDELSEBEGIN -- ======================================================== -- There is enough available units for us to remove the units from the inventor table -- ======================================================== SELECT @INVENT_ID=INVENT_ID FROM INVENTOR WITH (NOLOCK) WHERE NUMBER=@NUMBER AND BIN_ID=@BIN_ID IF (@INVENT_ID IS NULL) BEGIN -- ======================================================== -- Insert New Inventor Row -- ======================================================== INSERT INTO INVENTOR DEFAULT VALUES SELECT @INVENT_ID=@@IDENTITY UPDATE INVENTOR SET NUMBER = @NUMBER, DELIV_DATE = dateadd(dd,0, datediff(dd,0,GETDATE())), UNIT_COST = IsNull(@UNITCOST,0), DELIV_QTY = @UNITS*-1, UNITS = @UNITS*-1, BIN_ID = @BIN_ID WHERE INVENT_ID = @INVENT_ID END -- ======================================================== -- Update The Inventor Row -- ======================================================== UPDATE INVENTOR SET UNITS = @UNITS+UNITS WHERE INVENT_ID = @INVENT_ID -- ======================================================== -- UPDATE THE QTY IN THE SOURCE AND TARGET BINS -- ======================================================== UPDATE BIN SET UNITS = UNITS + @UNITS WHERE BIN_ID = @BIN_ID -- ======================================================== -- UPDATE THE QTY IN THE STOCK TABLE -- ======================================================== --UPDATE STOCK SET -- UNITS = UNITS + @UNITS --WHERE -- NUMBER = @NUMBER -- ======================================================== -- INSERT NEW ROW TO THE INVTRANS TABLE -- ======================================================== INSERT INTO INVTRANS DEFAULT VALUES SELECT @TRANS_ID=@@IDENTITY UPDATE INVTRANS SET NUMBER = @NUMBER, INVENT_ID = @INVENT_ID, TRANS_DATE = dateadd(dd,0, datediff(dd,0,GETDATE())), TRANSTYPE = 'A', QUANTITY = @UNITS, UNIT_COST = IsNull(@UNITCOST,0), TOTAL_AMT = IsNull(@UNITCOST,0) * @UNITS, USERID = @USERID, NEWINVTOT = IsNull(@NEWINVTOTAL,0) + @UNITS, NOTATION = @NOTATION, BIN_ID = @BIN_ID WHERE TRANS_ID = @TRANS_ID END-- =============================================================-- INSERT A ROW INTO THE POP..MOM_SUSPENSE TABLE FOR AUDIT TRAIL-- neilb: 2010-10-23-- =============================================================INSERT INTO POP..MOM_SUSPENSE ([DATE],NUMBER,UNITS,USERID,NOTATION)SELECT GETDATE(),@NUMBER,@UNITS,@USERID,@NOTATIONJay_Snow |
 |
|
ScottPletcher
Aged Yak Warrior
550 Posts |
Posted - 2013-08-30 : 14:55:46
|
I suggest rewriting the [MOM$BRAINTREESTOCKSYNC] procedure to also accept a table as input. That allows you to keep all the SYNC logic in one place but also do set-based INSERTs/UPDATEs to the underlying table rather than having to use a cursor and send each row through individually, which will be vastly slower than a set-based approach. |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2013-08-30 : 17:57:34
|
Something like this?CREATE TABLE #Bin ( Number VARCHAR(100) NOT NULL, Units INT NOT NULL, Bin_ID INT NOT NULL, Notation VARCHAR(100) NOT NULL, UserID VARCHAR(100) NOT NULL );MERGE MailOrderManager.dbo.BIN AS tgtUSING ( SELECT UPPER(Number) AS Number, WH_PHYS_STOCK - MOM_PHYS_STOCK AS Units, 'WEB' AS UserID, 'BRAINTREE Stock Sync' AS Notation, 'BRAINTREE' AS BinDesc, 'A' AS [Status], 1 AS Sell_Prior FROM @RES WHERE WH_PHYS_STOCK > MOM_PHYS_STOCK ) AS src ON src.BinDesc = tgt.BinDesc AND src.Number = tgt.NumberWHEN NOT MATCHED BY TARGET THEN INSERT ( Number, BinDesc, [Status], Sell_Prior, Units ) VALUES ( src.Number, src.BinDesc, src.[Status], src.Sell_Prior, src.Units )WHEN MATCHED THEN UPDATE SET tgt.Units += src.UnitsOUTPUT src.Number, src.Units, inserted.Bin_ID, src.Notation, src.UserIDINTO #Bin ( Number, Units, Bin_ID, Notation, UserID );CREATE TABLE #Invent ( Number VARCHAR(100) NOT NULL, Invent_ID INT NOT NULL, Units INT NOT NULL, Unit_Cost MONEY NOT NULL, Bin_ID INT NOT NULL, Notation VARCHAR(100) NOT NULL, UserID VARCHAR(100) NOT NULL );MERGE dbo.Inventor AS tgtUSING ( SELECT s.Number, CAST(GETDATE() AS DATE) AS Deliv_Date, COALESCE(w.UnitCost, 0) AS Unit_Cost, s.Units AS Deliv_Qty, s.Units, s.Bin_ID, Notation, UserID FROM #Stage AS s LEFT JOIN ( SELECT Number, MAX(ColsCost) AS UnitCost FROM dbo.ST_EXTRA GROUP BY Number ) AS w ON w.Number = s.Number ) AS src ON src.Number = tgt.Number AND src.Bin_ID = tgt.Bin_IDWHEN NOT MATCHED BY TARGET THEN INSERT ( Number, Deliv_Date, Unit_Cost, Deliv_Qty, Units, Bin_ID ) VALUES ( src.Number, src.Deliv_Date, src.Unit_Cost, src.Deliv_Qty, src.Units, src.Bin_ID )WHEN MATCHED THEN UPDATE SET tgt.Units += src.UnitsOUTPUT src.Number, inserted.Invent_ID, src.Units, src.Unit_Cost, src.Bin_ID, src.Notation, src.UserIDINTO #Invent ( Number, Invent_ID, Units, Unit_Cost, Bin_ID, Notation, UserID );DROP TABLE #Bin;INSERT dbo.INVTRANS ( Number, Invent_ID, Trans_Date, TransType, Quantity, Unit_Cost, Total_Amt, UserID, NewInvTot, Notation, Bin_ID )OUTPUT inserted.Trans_Date AS [Date], inserted.Number, inserted.Units, inserted.UserID, inserted.NotationINTO POP..MOM_SUSPENSE ( [Date], NUMBER, UNITS, USERID, NOTATION )SELECT i.Number, i.Invent_ID, CAST(GETDATE() AS DATE) AS Trans_Date, 'A' AS TransType, i.Units AS Quantity, i.Unit_Cost, i.Unit_Cost * i.Units AS Totalt_Amt, i.UserID AS UserID, COALESCE(q.NewInvTotal, 0) + i.Units AS NewInvTot, i.Notation AS Notation, i.Bin_IDFROM #Invent AS iOUTER APPLY ( SELECT TOP(1) x.NewInvTot AS NewInvTotal FROM dbo.INVTRANS AS x WITH (NOLOCK) WHERE x.Number = i.Number ORDER BY x.Trans_ID DESC ) AS q(NewInvTotal);DROP TABLE #Invent; Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
 |
|
jay_snow
Starting Member
3 Posts |
Posted - 2013-09-03 : 03:48:34
|
Thanks very much for the advice, and the example........i will have a go at using that approach and let you know if it works! :)Jay_Snow |
 |
|
|
|
|
|
|