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 |
mmckimson
Starting Member
6 Posts |
Posted - 2013-08-03 : 16:23:43
|
Background:I am creating a routine that is automating the creation of invoices that inserts the data from one of our SQL Server tables to a table in a linked server. Due to the limitation of the ODBC driver / underlying application used to create the linked server, I can't simply INSERT a SET of data but must instead create the invoices customer by customer and iterate through the records for each customer.Code:Hence, what I've done is create a test routine that first creates a loop that determines the customer, and within that loop, runs another loop that processes the data for that customer and writes something to the console for each customer transaction. The relevant code is as follows:SET NOCOUNT ONDeclare @i int --iterator to determine number of customer records to be processedDeclare @iCount int --rowcount for number of customer records to be processedDeclare @QB_ID varchar(100) --value to determine number of customers to be processedDeclare @i2 int -- iterator for detail transactionsDeclare @iCount2 int --rowcount for detail transactionsDeclare @QB_ID2 varchar(100) --the customer to be processedDeclare @TransQty varchar(100) -- quantityDeclare @ItemID varchar(100) -- QB Item IDSET @i = 1 --initializeCREATE TABLE ID_COUNT(ID int identity(1,1), QB_ID varchar(100))INSERT INTO ID_COUNT(QB_ID) SELECT DISTINCT(QB_ID) FROM QB_INVOICELINES WHERE QB_ID IS NOT NULLSET @iCount = @@ROWCOUNT --SCOPE_IDENTITY() would also workCREATE CLUSTERED INDEX IDX_TMP on ID_COUNT(ID) WITH FILLFACTOR = 100WHILE @i <= @iCountBEGINSELECT @QB_ID = QB_ID FROM ID_COUNT WHERE ID = @i--begin sub routine SET @i2 = 1 CREATE TABLE TRANS_COUNT(TRANS_ID int identity(1,1), QB_TRANS_ID varchar(100)) INSERT INTO TRANS_COUNT(QB_TRANS_ID)SELECT QB_ID FROM QB_INVOICELINES WHERE QB_ID = @QB_ID SET @iCount2 = @@ROWCOUNT CREATE CLUSTERED INDEX IDX_TMP on TRANS_COUNT(TRANS_ID) WITH FILLFACTOR = 100 WHILE @i2 <= @iCount2 BEGIN SELECT @QB_ID2 = QB_TRANS_ID FROM TRANS_COUNT WHERE TRANS_ID = @i2 Select @TransQty = Qty, @ItemID = QB_ITEM_ID from QB_INVOICELINES WHERE QB_ID = @QB_ID2 PRINT 'Transaction quantity of ' + @TransQty + ' for item ID ' + @ItemID + ' for customer ID ' + @QB_ID2 + ' is now posted' SET @i2 = @i2 + 1 END DROP TABLE TRANS_COUNT--end sub routine SET @i = @i + 1ENDDROP TABLE ID_COUNT Issue:While this routine seemingly runs correctly and does recognize the appropriate number of transactions for each of the 3 customers in the underlying table, the "inner" loop seems to repeat the last transaction of the series for each customer X number of times, with X being the correct number of customer transactions, as opposed to having each transaction.The following images display the data from the table I am using to test as well as the console messages returned:Data:Console message:I've looked at this until I'm blue in the face, and can't figure out what is wrong. Any help would be appreciated!Cheers!Mike |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2013-08-03 : 17:07:08
|
[code]INSERT INTO TRANS_COUNT(QB_TRANS_ID)SELECT QB_ID FROM QB_INVOICELINES WHERE QB_ID = @QB_IDINSERT INTO TRANS_COUNT(QB_TRANS_ID)SELECT QB_TRANS_ID FROM QB_INVOICELINES WHERE QB_ID = @QB_ID[/code] Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2013-08-03 : 17:15:02
|
Wouldn't this be easier?SET NOCOUNT ONDECLARE curOutput CURSOR FOR SELECT QTY, QB_ITEM_ID, QB_TRANS_ID FROM dbo.QB_INVOICELINES WHERE QB_ID IS NOT NULL ORDER BY QB_TRANS_ID, QB_ITEM_ID;DECLARE @Quantity INT, @ItemID VARCHAR(100), @CustomerID VARCHAR(100);OPEN curOutputFETCH NEXTFROM curOutputINTO @Quantity, @ItemID, @CustomerID;WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Transaction quantity of ' + CAST(@Quantity AS VARCHAR(12)) + ' for item ID ' + @ItemID + ' for customer ID ' + @CustomerID + ' is now posted.' FETCH NEXT FROM curOutput INTO @Quantity, @ItemID, @CustomerID; ENDCLOSE curOutputDEALLOCATE curOutput Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2013-08-03 : 17:20:02
|
Or, if you insist in keeping your loops, there is no need to recreate TRANS_COUNT table over and over again.Declare @i int --iterator to determine number of customer records to be processedDeclare @iCount int --rowcount for number of customer records to be processedDeclare @QB_ID varchar(100) --value to determine number of customers to be processedDeclare @i2 int -- iterator for detail transactionsDeclare @iCount2 int --rowcount for detail transactionsDeclare @QB_ID2 varchar(100) --the customer to be processedDeclare @TransQty varchar(100) -- quantityDeclare @ItemID varchar(100) -- QB Item IDSET @i = 1 --initializeCREATE TABLE #ID_COUNT ( ID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED, QB_ID VARCHAR(100) NOT NULL );INSERT #ID_COUNT ( QB_ID )SELECT DISTINCT QB_IDFROM dbo.QB_INVOICELINESWHERE QB_ID IS NOT NULL;SET @iCount = @@ROWCOUNT;CREATE TABLE #TRANS_COUNT ( TRANS_ID INT IDENTITY(1, 1), QB_TRANS_ID VARCHAR(100) NOT NULL );WHILE @i <= @iCount BEGIN SELECT @QB_ID = QB_ID FROM #ID_COUNT WHERE ID = @i; --begin sub routine SET @i2 = 1; TRUNCATE TABLE #TRANS_COUNT; INSERT #TRANS_COUNT ( QB_TRANS_ID ) SELECT QB_TRANS_ID FROM dbo.QB_INVOICELINES WHERE QB_ID = @QB_ID; SET @iCount2 = @@ROWCOUNT; WHILE @i2 <= @iCount2 BEGIN SELECT @QB_ID2 = QB_TRANS_ID FROM #TRANS_COUNT WHERE TRANS_ID = @i2; SELECT @TransQty = Qty, @ItemID = QB_ITEM_ID FROM dbo.QB_INVOICELINES WHERE QB_ID = @QB_ID2; PRINT 'Transaction quantity of ' + @TransQty + ' for item ID ' + @ItemID + ' for customer ID ' + @QB_ID2 + ' is now posted.' SET @i2 = @i2 + 1 END --end sub routine SET @i = @i + 1 ENDDROP TABLE #ID_COUNT, #TRANS_COUNT; Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
|
|
mmckimson
Starting Member
6 Posts |
Posted - 2013-08-03 : 18:47:11
|
Indeed... after modifying to order the cursor output by QB_ID (how the invoice is generated, it worked perfectly. Thanks for your help!Mikequote: Originally posted by SwePeso Wouldn't this be easier?SET NOCOUNT ONDECLARE curOutput CURSOR FOR SELECT QTY, QB_ITEM_ID, QB_TRANS_ID FROM dbo.QB_INVOICELINES WHERE QB_ID IS NOT NULL ORDER BY QB_TRANS_ID, QB_ITEM_ID;DECLARE @Quantity INT, @ItemID VARCHAR(100), @CustomerID VARCHAR(100);OPEN curOutputFETCH NEXTFROM curOutputINTO @Quantity, @ItemID, @CustomerID;WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'Transaction quantity of ' + CAST(@Quantity AS VARCHAR(12)) + ' for item ID ' + @ItemID + ' for customer ID ' + @CustomerID + ' is now posted.' FETCH NEXT FROM curOutput INTO @Quantity, @ItemID, @CustomerID; ENDCLOSE curOutputDEALLOCATE curOutput Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA
|
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2013-08-03 : 19:16:50
|
You meanORDER BY QB_ID, InvoiceLine_ID to have a deterministic order? Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
|
|
|
|
|
|
|