Select all tables in schema based on their parent-child hierarchy - sql

My requirement is to delete data from couple of table selected dynamically based on search condition.
So my cursor should fetch tables in their parent-child hierarchy so that it will not give exception 'CHILD RECORD FOUND' while deleting records.
lets take exable
Table A is child of Table B
Table B is child of Table C
Table D is child of table G
So it should delete in this sequence.
A then
B or D then
D or G

If you use cascading foreign keys, you don't have to worry about table order. Just delete from the top of the hierarchy (table G in in your example) and then all dependent rows in the descendent tables will be deleted atomically.
Read more about Cascading Referential Integrity Constraints.
Re your comment:
Also it should be generic enough to handle delete even if delete cascade is not there and we do not have knowledge of dependencies.
See these questions for tips on discovering constraints in Oracle:
List of foreign keys and the tables they reference
Oracle - Recursive query (for table dependencies) is not recursing (not as much as I'd like)
Thanks for the question regarding "All Parent - Child tables in the database", version 8.x

Related

How to implement cascading deletes in one -> many *from the many side*

I have a use case where multiple rows in table A are aggregated down to a single row in table B. We represent the origin of rows in table B with a foreign key column in table A, saying "as a row, I contributed to X row in table B".
We want to find the best solution so that once every row from table A which contributed to table B has been deleted, deleted the row in table B as an orphan.
I'm not sure if there's some way to use ON DELETE CASCADE to handle this. But I'm guessing not and that maybe triggers are the best option.
I can't just purge all orphans on a schedule because the changes need to be persisted very soon after occurring.
Using the given schema, what our best option? Alternatively, is there some other schema that better sets us up for the scenario I gave?

Postgresql Locking Rows on a Key/Foreign Key

I'm using postgresql. I have 3 tables.
Table A has an ID column that's a Primary Key
Table B and Table C have ID columns that are foreign key references to A's ID.
In a single process, I would like to lock any rows that have a particular ID and then possibly delete rows and insert rows with that ID in B and C
My current approach is
SELECT FOR UPDATE on A on the ID.
Then I try to delete and insert rows in B and C.
commit/end
Unfortunately, my code deadlocks trying to do the insert.
What am I doing wrong? What is the proper way to prevent other processes from adding, removing, or updating rows with a given ID in B and C (until I am done with my transaction)?
Thanks in advance!
It looks I was doing things correctly from the start. My issue was that I was accidentally creating two different database connections in my code. So, from postgresql's perspective, there were two different transactions - hence the deadlocking.

Deleting rows from multiple tables

I created a query that will delete rows from three tables that has 'Employee'.
When I execute it, it only deletes rows from one table tblEmployeeType. I tried adding Alias of other tables beside DELETE but SQL does not support it. Is there any alternative way of deleting rows from multiple tables? or I forgot some codes on my query or should I just separate delete queries? Thank you.
DELETE a
FROM tblEmployeeType a INNER JOIN
tbl_Selected_AccessType b
ON a.EmpTypeName = b.UserType INNER JOIN
tbl_AccessType_AllFunction c
ON a.EmpTypeName = c.UserType
WHERE a.EmpTypeName = 'Employee'`
INSERT and UPDATE statements can only directly affect one table at a time. If you have foreign keys configured with ON DELETE CASCADE then child records will be deleted along with the parent record. Regardless of using cascade, you should have foreign keys on the table so that your DELETE doesn't leave orphaned child records with broken referential integrity.
Another way to achieve affecting other tables in an INSERT or UPDATE is by using a trigger on the table. This can be desirable when you want to do checks before blindly deleting child records.

Inserting Data into Tables and Integrity

This is my first post, so please excuse me for any obvious or simple questions as I am very new to programming and all my projects are a first to me.
I am currently working on my first database project. A relational database using Oracle sql. I'm new on my course, so I am not sure on all the concepts yet, but working at it.
I have used some modelling software to help me construct a 13 table database. I have setup all my columns and assigned primary and foreign keys to all 13 tables. What I am looking to do now is insert 10 rows of test data into each table. I have done the parent tables but am confused about the child tables. When I assign ID numbers to all the parent tables primary keys, will the child tables foreign keys be populated at the same time?
I have not used sequences yet as I'm not 100% how to make them work, but instead inputted my own values like 100, 101, 102 etc. I know those values need to be in the foreign key, but wouldn't manually inserting them into many tables get confusing?
Is there an easier approach to this or am I over complicating the process?
I will need to use some queries later but I just want to be happy that the data is sound.
Thanks for your help
Rob
No, the child table data won't be populated automatically-- if there is a child table, that implies that there is a 0 or 1 to m relationship between the two. One row in the parent table may have 0 rows in the child table or it may have dozens so nothing could possibly be populated automatically.
If you are manually assigning primary key values, you'd need to hard code those same values as the foreign key values when you insert data into the child tables. In the real world, you wouldn't manually insert data into many tables at once, you'd have an application that did so and that knew what keys to use based on parameters passed in or by getting the currval of the sequence used to populate the primary key after inserting into the parent table.
Its necessary that data for foreign key should be present in parent table, but not the other way around.
If you want to create test data, i suggest you use something like below query.
insert into child_table(fk_column,column1,column2....)
select pk_column,'#dummy_value1#','#dummy_value2#',..
from parent_table
if you have 10 rows in parent, this will add 10 rows in child.
If you want more rows, e.g. 100 for each parent value you need to duplicate the parent data. for that use below query.
insert into child_table(fk_column,column1,column2....)
select pk_column,'#dummy_value1#','#dummy_value2#',..
from parent_table
join (select level from dual connect by level<10)
this will add 100 child values for 10 parent values..

How to Delete all data from a table which contain self referencing foreign key

I have a table which has employee relationship defined within itself.
i.e.
EmpID Name SeniorId
-----------------------
1 A NULL
2 B 1
3 C 1
4 D 3
and so on...
Where Senior ID is a foreign key whose primary key table is same with refrence column EmpId
I want to clear all rows from this table without removing any constraint. How can i do this?
Deletion need to be performed like this
4, 3 , 2 , 1
How can I do this
EDIT:
Jhonny's Answer is working for me but which of the answers are more efficient.
I don't know if I am missing something, but maybe you can try this.
UPDATE employee SET SeniorID = NULL
DELETE FROM employee
If the table is very large (cardinality of millions), and there is no need to log the DELETE transactions, dropping the constraint and TRUNCATEing and recreating constraints is by far the most efficient way. Also, if there are foreign keys in other tables (and in this particular table design it would seem to be so), those rows will all have to be deleted first in all cases, as well.
Normalization says nothing about recursive/hierarchical/tree relationships, so I believe that is a red herring in your reply to DVK's suggestion to split this into its own table - it certainly is viable to make a vertical partition of this table already and also to consider whether you can take advantage of that to get any of the other benefits I list below. As DVK alludes to, in this particular design, I have often seen a separate link table to record self-relationships and other kinds of relationships. This has numerous benefits:
have many to many up AND down instead of many-to-one (uncommon, but potentially useful)
track different types of direct relationships - manager, mentor, assistant, payroll approver, expense approver, technical report-to - with rows in the relationship and relationship type tables instead of new columns in the employee table
track changing hierarchies in a temporally consistent way (including terminated employee hierarchy history) by including active indicators and effective dates on the relationship rows - this is only fully possible when normalizing the relationship into its own table
no NULLs in the SeniorID (actually on either ID) - this is a distinct advantage in avoiding bad logic, but NULLs will usually appear in views when you have to left join to the relationship table anyway
a better dedicated indexing strategy - as opposed to adding SeniorID to selected indexes you already have on Employee (especially as the number of relationship types grows)
And of course, the more information you relate to this relationship, the more strongly is indicated that the relationship itself merits a table (i.e. it is a "relation" in the true sense of the word as used in relational databases - related data is stored in a relation or table - related to a primary key), and thus a normal form for relationships might strongly indicate that the relationship table be created instead of a simple foreign key relationship in the employee table.
Benefits also include its straightforward delete scenario:
DELETE FROM EmployeeRelationships;
DELETE FROM Employee;
You'll note a striking equivalence to the accepted answer here on SO, since, in your case, employees with no senior relationship have a NULL - so in that answer the poster set all to NULL first to eliminate relationships and then remove the employees.
There is a possibly appropriate usage of TRUNCATE depending upon constraints (EmpployeeRelationships is typically able to be TRUNCATEd since its primary key is usually a composite and not a foreign key in any other table).
Try this
DELETE FROM employee;
Inside a loop, run a command that deletes all rows with an unreferenced EmpID until there are zero rows left. There are a variety of ways to write that inner DELETE command:
DELETE FROM employee WHERE EmpID NOT IN (SELECT SeniorID FROM employee)
DELETE FROM employee e1 WHERE NOT EXISTS
(SELECT * FROM employee e2 WHERE e2.SeniorID = e.EmpID
and probably a third one using a JOIN, but I'm not familiar with the SQL Server syntax for that.
One solution is to normalize this by splitting out "senior" relationship into a separate table. For the sake of generality, make that second table "empID1|empID2|relationship_type".
Barring that, you need to do this in a loop. One way is to do it:
declare #count int
select #count=count(1) from table
while (#count > 0)
BEGIN
delete employee WHERE NOT EXISTS
(select 1 from employee 'e_senior'
where employee.EmpID=e_senior.SeniorID)
select #count=count(1) from table
END