Here's an idea: build your "expansion table" with something like this:
expanded_table (id number, parent_src char(1), parent_id number, ...)
The parent_src
column should indicate where the parent comes from, e.g. you could use 'O'
of original, 'E'
for expansion. (Add a primary key on id
, of course.)
To handle the querying, use a view defined like this (pseudo-sql):
select 'O' source, o.id, 'O' parent_src, o.parent_id, [...] from original_table
union all
select 'E' source, e.id, e.parent_src, e.parent_id, [...] from expanded_table
You can do hierarchical queries based on (source,id)
/(parent_src,parend_id)
pairs.
No problem with duplicate/overlapping id
s, the source info disambiguates them.
Now data integrity is going to be very problematic.
You can't have check constraints that reference other tables, and I don't know of a way of building a "conditional foreign key" that would work here.
You could use triggers to make sure DML on the expanded table is coherent, but even with those and triggers on the original table (if you could do that, which doesn't seem to be the case), that would be very tricky to get right.
Having all DML to this "structure" go through PL/SQL that you control could do it, but that doesn't appear to be possible given the information in your post.
OK, enough brain cells are dead.
SQL Fiddle
WITH cte AS
(
SELECT
[ICFilterID],
[ParentID],
[FilterDesc],
[Active],
CAST(0 AS varbinary(max)) AS Level
FROM [dbo].[ICFilters]
WHERE [ParentID] = 0
UNION ALL
SELECT
i.[ICFilterID],
i.[ParentID],
i.[FilterDesc],
i.[Active],
Level + CAST(i.[ICFilterID] AS varbinary(max)) AS Level
FROM [dbo].[ICFilters] i
INNER JOIN cte c
ON c.[ICFilterID] = i.[ParentID]
)
SELECT
[ICFilterID],
[ParentID],
[FilterDesc],
[Active]
FROM cte
ORDER BY [Level];
Best Answer
I'm assuming (from the fact you considered adding a parentId column) that each Node has a single parent.
Two things to do:
So your design becomes simply:
Node
Now you can indeed enforce unique names among siblings by adding a unique constraint on parent + name.
You can derive the ancestor/descendent relationship and level that was previously in NodeClosure using queries against the Node table. Syntax for this varies depending on database.