I need to create a sql stored procedure (Sql Server 2008 - T-SQL) which copies a node in an adjacency model.
Table can be seen as having two columns, Id and ParentId (FK to Id). Copying means that also all subordinates need to be copied.
I think that using WITH is a good start, but I'm curious if I can do this copy without using Cursors.
The fundamental problem with adjacency lists is there is no general way in SQL to extract an entire sub tree, so you already have a problem of identifying all the rows you need to duplicate without resorting to a cursor.
If possible migrate your adjacency list to a nested set model which allows you to easily identify all the nodes of a subtree. However, the maintenance of a nested set model is more complex for general inserts and deletes.
EDIT: As pointed out by 'a_horse_with_no_name' there is a way in general SQL to process adjacency lists, recursive common table expressions.
Copying a whole sub-tree is a bit of a problem because when you copy your sub-tree you are either
denormalizing data or
using it as a template of some sorts.
In either case you are dragging data through inconsistent state at some point - which indicates some problems with your design (for example do your records need to have multiple parents or not? if yes, then you should consider redesigning).
So, you should update the answer with a more complete example of what you are trying to do.
One solution would be to have a temporary table, selecting for the insert should not be a problem, it is just updating the referenced IDs that would be a problem.
So
WITH INSERT into temporary table
UPDATE the IDs
INSERT into original table
DELETE temp records
The procedure needs to go like this because it would be hard to change the IDs (both record IDs and ID referring to parent) in initial WITH INSERT. However it might be possible, if there was a nice function that depended only on max_id or only on old IDs.
Related
My question comes from what is more efficient when making queries and insert, since the number of registers(data) in my table will grow a lot.
I would like to know what is more efficient to do if all the data is placed within a single table or is the partition and through a View and trigger is more efficient to obtain and enter registers(data).
As already mentioned take a look at database normalization.
SQL is a way to work with relational databases and is built on the idea that we should have many tables that are linked with each other trough relationships. Thus I recommend multiple tables, because you will be able to reuse data (for example user name and surname) through specific IDs rather than copying that data each time a user performs some action on your platform and you need to insert or update some information.
Hope this helps!
I'm trying to figure out how I can store hierarchical type information in a MS Access DB so that queries will be faster. An use case example might make more sense.
I have a table that has two fields
a name
a hierarchy
a hierarchy is an X # of level folder structure:
\a\b\c\d
\a\b\c\d\e
\a\b\c\d\f\g
\a\b\h
\a\b\i\j
you get the idea
the table will be filled with 300,000 rows
each row will have a name and a hierarchy
At this point:
if I want to find all the names that are in a hierarchy, including sub-hierarchies I can run a like query: where [hierarchy] like '\a\b\*'
I can even do wildcard joins even though MS Access's query design GUI doesn't handle it and I have to use the SQL view: join on [hierarchy] like '\a\b\*'.
But it can be very slow. Especially if my joins get complex.
So I thought maybe there is a way to create another table that would all the hierarchies and it would maintain parent/child relationships and the first table would reference a row in it. And then, somehow, I could use it to find rows in the first table that match hierarchies and sub-hierarchies in the second table.
However, I have no clue if this is even possible and how I would go about it. Any advice is appreciated.
In Oracle we use the hierarchal structure where each row has a reference to its parent. Then with the CONNECT BY clause you can connect these rows to each-other.
You should take a look here: simulation of connect-by in sql-server
TASK
I am currently trying to work out a viable structure for a simple application for the costing of jobs. I have decided to create one table to house all the operations and then link the operation together via a ParentID field. Below is a simplified structure of this table:
As you can see, the primary key is an integer field that does auto increment to keep it unique. Any operations that stem off another operation will have it under the parent ID field to create a simplistic breakdown of work flow. Also on this data table is a field for costs, this is a field that I am most interested in.
THE PROBLEM
I would like to run a query where I could throw in an operation ID and it would recursively run through that operation AND all of its children and its children's children etc. This would then accumulate all of the cost fields in the records that it retrieves. The only way I can think to do this is through recursive loops which in my opinion are not the best way to do this.
THE QUESTION
So, my question is, is there a way to do this without recursive loops? If there is not, can anyone suggest the cleanest and quickest way with the loops?
This kind of query is recursive by definition. There is no way to get that information using that table structure.
You could make another table in which you would store all hierarchy information. On inserting an Operation you would have to add a parent, grandparent, grand-...-parent recursively, which may also not be a good idea, because the table would grow very large very quickly. It would make the queries much simpler though.
And a side note: I'd suggest naming the ParentID ParentOperationID. ParentID is too general.
I have a need to build a schema structure to support table of contents (so the level of sections / sub-sections could change for each book or document I add)...one of my first thoughts was that I could use a recursive table to handle that. I want to make sure that my structure is normalized, so I was trying to stay away from deonormalising the table of contents data into a single table (then have to add columns when there are more sub-sections).
It doesn't seem right to build a recursive table and could be kind of ugly to populate.
Just wanted to get some thoughts on some alternate solutions or if a recursive table is ok.
Thanks,
S
It helps that SQL Server 2008 has both the recursive WITH clause and hierarchyid to make working with hierarchical data easier - I was pointing out to someone yesterday that MySQL doesn't have either, making things difficult...
The most important thing is to review your data - if you can normalize it to be within a single table, great. But don't shoehorn it in to fit a single table setup - if it needs more tables, then design it that way. The data & usage will show you the correct way to model things.
When in doubt, keep it simple. Where you've a collection of similar items, e.g. employees then a table that references itself makes sense. Whilst here you can argue (quite rightly) that each item within the table is a 'section' of some form or another, unless you're comfortable with modelling the data as sections and handling the different types of sections through relationships to these entities, I would avoid the complexity of a self-referencing table and stick with a normalized approach.
I've got a database table that represents a bunch of trees. The first three columns are GUIDs that look like this:
NODE_ID (PK)
PARENT_NODE_ID (FK to same table, references NODE_ID)
TREE_ID (FK to another table)
It's possible to move a node to a different tree. The tricky part is bringing all its child-nodes with it. That takes a recursive update. (And yes, I realize this is kinda bad design in the first place. I didn't design it. I just have to maintain it, and I can't change the database schema.)
It would be nice if I could do the update in SQL, as a stored procedure. But I can't think of how to implement the recursive operation required in set logic, without employing a cursor. Does anyone know of a reasonably simple way to pull this off?
If you are using Postgres or MS SQL 2005 you can use a recursive update, otherwise, you may want to consider using a method other than an adjacency list. I saw a presentation a few weeks ago speaking about these issues and storing hierarchical data. Here is a link:
http://www.slideshare.net/billkarwin/practical-object-oriented-models-in-sql
Start # slide 40