I've encountered some strange behavior in a recursive procedure I'm
writing for a bill of materials. First let me ask directly if what I
think is happening is even possible:
It seems like the procedure is not following the recursion in serial
order, but in parallel. In other words, after one instance of the
procedure calls itself, it continues executing lines below the
recursion before the recursion is done. Is that possible? I looked
for SQL Server Options that might deal with recursion or threading but
I couldn't find anything.
Now let me explain what's happening in terms of the BoM. All the rows
I expect are returned, but not in the correct order. Let's assume the
following tree:
1
|-2
| |-5
| | |-7
| | \-8
| \-6
| \-9
|-3
| |-10
| |-11
| | |-13
| | \-14
| | |-15
| | |-16
| | \-17
| \-12
| \-18
| \-19
| \-20
| |-21
| \-22
\-4
\-23
|-24
\-25
\-26
This is stored in table P using MemberID and ParentID fields. For
example,
MemberID ParentID
-------- --------
1 NULL
2 1
3 1
4 1
5 2
6 2
(etc...)
Based on how I wrote the recursion (I will provide the procedure
below), I would expect output when starting from MemberID of 1 to look
like this:
MemberID Depth Sort
-------- ----- ----
2 1 1
5 2 2
7 3 3
8 3 4
6 2 5
9 3 6
(etc... basically, the line order of the graphical tree above, or a
counter-clockwise traverse around the tree)
Instead, I get this (I'll provide the whole thing because I don't see
a pattern):
MemberID Depth Sort
-------- ----- ----
2 1 1
5 2 2
3 1 2
10 2 3
7 3 3
4 1 3
6 2 3
9 3 4
23 2 4
8 3 4
11 2 4
13 3 5
12 2 5
24 3 5
25 3 6
18 3 6
14 3 6
15 4 7
19 4 7
26 4 7
20 5 8
16 4 8
17 4 9
21 6 9
22 6 10
Call me crazy, but it looks like my tree was parsed in the same order
that a set of dominos arranged in the same shape would topple. The
only way I could see that happening is if the recursion is non-linear,
allowing both children and siblings to be parsed simultaneously. It
would also explain why my sort counter didn't increment properly, but
the depth counter is always correct.
Now here are the procedures. There's also a Qty column, since this is
a BoM after all, but I didn't need to mention it for my illustration
of the problem above.
CREATE PROC makebom @root bigint
--
-- This would be called by the client to find all the parts and
quantities
-- under a specific part (@root)
--
AS
SET NOCOUNT ON
CREATE TABLE #result (MemberID bigint, Qty bigint, Depth bigint, sort
bigint)
EXEC bomrecurse @root, 1, 0
SET NOCOUNT OFF
SELECT MemberID, Qty, Depth, sort FROM #result ORDER BY sort
GO
CREATE PROC bomrecurse @root bigint, @depthcounter bigint,
@sortcounter bigint
--
-- This is the recursive procedure, called once by makebom, but
recalling
-- itself until the whole tree is parsed, filling the #result table
--
AS
DECLARE @memberid bigint, @qty bigint, @nextdepth bigint
DECLARE children_cursor CURSOR LOCAL FOR
SELECT MemberID, Qty FROM P
WHERE ParentID = @root
ORDER BY MemberID
OPEN children_cursor
FETCH NEXT FROM children_cursor
INTO @memberid, @qty
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sortcounter = @sortcounter + 1
INSERT INTO #result VALUES (@memberid, @qty, @depthcounter,
@sortcounter)
SET @nextdepth = @depthcounter + 1
EXEC bomrecurse @memberid, @nextdepth, @sortcounter
FETCH NEXT FROM children_cursor
INTO @memberid, @qty
END
CLOSE children_cursor
DEALLOCATE children_cursor
GO
I'm surprised this even worked as well as it did because I'm a newbie
when it comes to stored procedures and I put this together from
examples I found around this group, online and in the T-SQL Help. So
feel free to comment on other aspects of my code or approach, but I'm
most interested in understanding the behavior of this recursion. 4 2580
Dan (th*******@gmai l.com) writes: I've encountered some strange behavior in a recursive procedure I'm writing for a bill of materials. First let me ask directly if what I think is happening is even possible:
It seems like the procedure is not following the recursion in serial order, but in parallel. In other words, after one instance of the procedure calls itself, it continues executing lines below the recursion before the recursion is done. Is that possible?
No, it is not.
You included the code to your procedures, but unfortunately you did
not include any CREATE TABLE statements or INSERT statements with
sample data. (Thus, I would have to type those myself, and I am lazy.)
Then again, there is something in your code that I don't understand:
CREATE PROC bomrecurse @root bigint, @depthcounter bigint, @sortcounter bigint ... DECLARE children_cursor CURSOR LOCAL FOR SELECT MemberID, Qty FROM P WHERE ParentID = @root ORDER BY MemberID
OPEN children_cursor
FETCH NEXT FROM children_cursor INTO @memberid, @qty
WHILE @@FETCH_STATUS = 0 BEGIN SET @sortcounter = @sortcounter + 1 INSERT INTO #result VALUES (@memberid, @qty, @depthcounter, @sortcounter)
SET @nextdepth = @depthcounter + 1 EXEC bomrecurse @memberid, @nextdepth, @sortcounter
Say that you have a simple tree of two nodes A and B, which both have four
children that are leaf nodes. When you start with A, @sortcounter is 0,
which you increment and insert 1 into the table. Then you recurse, for
the four children you insert the values 2, 3, 4 and 5. Then you come back,
and for the B you insert 2 into #result and then 3, 4, 5 and 6 into
#result. It may be the late hour over here, but I don't really see what
the purpose might be with this. If I guess, shouldn't you make @sortcounter
an OUTPUT parameter, so that you get the value back from the recursion?
(Note that you need to specify OUTPUT both in CREATE PROCEDURE and in the
EXEC statement.)
--
Erland Sommarskog, SQL Server MVP, es****@sommarsk og.se
Books Online for SQL Server SP3 at http://www.microsoft.com/sql/techinf...2000/books.asp
On Mon, 9 Aug 2004 22:31:52 +0000 (UTC), Erland Sommarskog
<es****@sommars kog.se> wrote: You included the code to your procedures, but unfortunately you did not include any CREATE TABLE statements or INSERT statements with sample data. (Thus, I would have to type those myself, and I am lazy.)
I would have if I knew how to generate the INSERT with sample data.
(Have the server generate it, I mean. I'm not typing it all myself
either!) I could do the CREATE TABLE statement but without the data
that's rather useless. CREATE PROC bomrecurse @root bigint, @depthcounter bigint, @sortcounter bigint ... DECLARE children_cursor CURSOR LOCAL FOR SELECT MemberID, Qty FROM P WHERE ParentID = @root ORDER BY MemberID
OPEN children_cursor
FETCH NEXT FROM children_cursor INTO @memberid, @qty
WHILE @@FETCH_STATUS = 0 BEGIN SET @sortcounter = @sortcounter + 1 INSERT INTO #result VALUES (@memberid, @qty, @depthcounter, @sortcounter)
SET @nextdepth = @depthcounter + 1 EXEC bomrecurse @memberid, @nextdepth, @sortcounter
Say that you have a simple tree of two nodes A and B, which both have four children that are leaf nodes. When you start with A, @sortcounter is 0, which you increment and insert 1 into the table. Then you recurse, for the four children you insert the values 2, 3, 4 and 5. Then you come back, and for the B you insert 2 into #result and then 3, 4, 5 and 6 into #result. It may be the late hour over here, but I don't really see what the purpose might be with this.
Good eye. My intent was to simply give each row a "sort" value equal
to its row number in the result table. This is unnecessary if the end
client doesn't REsort it, but I didn't wan to count on that. You're
right - it won't work as I wrote it.
If I guess, shouldn't you make @sortcounter an OUTPUT parameter, so that you get the value back from the recursion?
(Note that you need to specify OUTPUT both in CREATE PROCEDURE and in the EXEC statement.)
That sounds like the way to do it - thanks.
Still no idea why the tree is being parsed like dominos though?
Dan <th*******@goog le.com> wrote in message news:<s3******* *************** **********@4ax. com>... On Mon, 9 Aug 2004 22:31:52 +0000 (UTC), Erland Sommarskog <es****@sommars kog.se> wrote: If I guess, shouldn't you make @sortcounter an OUTPUT parameter, so that you get the value back from the recursion?
(Note that you need to specify OUTPUT both in CREATE PROCEDURE and in the EXEC statement.)
That sounds like the way to do it - thanks.
Still no idea why the tree is being parsed like dominos though?
Nevermind. I suddenly see the light. :) The loss of @sortcounter's
value when it stepped out of recursion was what caused not only the
duplicate values but subsequently the apparent domino-order parsing.
I would've seen this sooner if I hadn't sorted by @sortcounter's
column.
Making the @sortcounter an OUTPUT parameter solved everything.
Thanks!
Dan (th*******@goog le.com) writes: I would have if I knew how to generate the INSERT with sample data. (Have the server generate it, I mean. I'm not typing it all myself either!)
This is moot point now, since you were able to resolve your problem, but
permit me to point out that for this case an example of 10 rows should
probably do, which should not be a problem for you type if you were
interesting in getting assistance with the problem.
If you would need to script out many rows for some reason, there is
no builtin tool for this in SQL Server, however SQL Server MVP Vyas
Kondreddi has a nifty utility for this on his site, http://vyaskn.tripod.com/code.htm#inserts
--
Erland Sommarskog, SQL Server MVP, es****@sommarsk og.se
Books Online for SQL Server SP3 at http://www.microsoft.com/sql/techinf...2000/books.asp This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: mike420 |
last post by:
I think everyone who used Python will agree that its syntax is
the best thing going for it. It is very readable and easy
for everyone to learn. But, Python does not a have very good
macro capabilities, unfortunately. I'd like to know if it may
be possible to add a powerful macro system to Python, while
keeping its amazing syntax, and if it could be possible to
add Pythonistic syntax to Lisp or Scheme, while keeping all
of the...
|
by: Rick Snagglehimer |
last post by:
I keep getting an error from the following SP snippet
"Line 11: Incorrect syntax near 'BY'."
It runs fine without the ORDER BY clause.
>>>>>>>>>>>>>>>
WHERE
.clientID = .userID
|
by: dinesh prasad |
last post by:
I'm trying to use a servlet to process a form, then send that data to
an SQL server stored procedure. I'm using the WebLogic 8 App. server.
I am able to retrieve database information, so I know my application
server can talk to the database.
I've determined the failure occurs when the the following statement is
executed: cstmt.execute(); (due to the failure of println statements
placed afterwards). I get the following error after trying to...
|
by: Alex Vorobiev |
last post by:
hi there,
i am using sql server 7. below is the stored procedure that is giving
me grief. its purpose it two-fold, depending on how it is called:
either to return a pageset (based on page number and page size), or to
return IDs of previous and next records (based on current record id).
the problem is, that the order in which records are inserted into the
temp table is inconsistent, even though the calling statement and the
order by is...
|
by: Icarus |
last post by:
Is it possible to have to ORDER BY statements in the same stored
procedure?
I am trying to use the same stored procedure for two different pages
but the data returned needs to sorted DESC on one page and ASC on
another. Below is my SP:
CREATE procedure sp_getLeads
@p_SortType int,
@p_PropID int
| |
by: Irishmaninusa |
last post by:
Hello Everyone,
I am populating a dropdown control from a database where the data is
datetime values. In my stored procedure I am ordering them by where the most
recent is at the top and the earliest is the last. So the following is
displayed in SQL Query Analyzer
7/28/2004
7/1/2004
6/302004
|
by: Beowulf |
last post by:
I have the view below and if I use vwRouteReference as the rowsource
for a combo box in an MS Access form or run "SELECT * FROM
vwRouteReference" in SQL Query Analyzer, the rows don't come through
sorted by Numb.
Everything I've read on the web suggests that including the TOP
directive should enable ORDERY BY in views. Does someone have an idea
why the sorting is not working correctly for this particular view? thanks.
CREATE VIEW...
|
by: balabaster |
last post by:
Hi,
I have a couple of tables:
Units(
Unit_PKey Int Identity(1,1) Primary Key,
Unit_Name nvarchar(8),
Unit_Description nvarchar(32)
)
|
by: Muzammil |
last post by:
int harmonic(int n) {
if (n=1) {
return 1;
}
else {
return harmonic(n-1)+1/n;
}
}
can any help me ??
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |