sql query to delete by category - sql

ok guys, may be it's not the best title for my problem. so this is the case
i have 2 table in my database,
Parent table
---------
id name
---------
0 A
1 B
2 C
Child table
-------------------------
id name parent_id
-------------------------
0 child_A 1
1 child_B 0
2 child_C 2
so if record A in parent table deleted, how can i delete all child who have parent_id 0 (A have id 0) ??
i hope you can understand my problem and help me .. :) thanks in adv .. :)
i think i've got the solution, first i try to get all field that not have parent anymore
by this query
SELECT * FROM folders C where NOT EXISTS (select * from folders as A INNER JOIN gis_folders as B on (A.parent_id = B.id) where A.id= C.id )
now i just have to delete all the rows on result from that query .. :)

This is called a cascading delete. When you set up the foreign keys you can specify that child rows are deleted.
See section 4.3 of http://www.sqlite.org/foreignkeys.html for more details.

Do this if you don't have a foreign key set up
DELETE parent, child
FROM parent LEFT JOIN child ON parent.id = child.parent_id
WHERE parent.id = 0

I think the best way is to create a trigger on deleted of parent A
and there you can get the deleted parent id and write query to delete from B
similarly create a trigger on delete of Parent B and there again get id from deleted row and delete all rows from C

Othere way could be create a procedure take a id of parent A as parameter
now writer query like
delete from C where Cid in (select Cid from c where CparentID in (select Bid from B where BparentID = aid))
delete from B where BparentID = aid
delete from A where aid = aid
you can also refere to this
http://msdn.microsoft.com/en-us/library/aa933119%28SQL.80%29.aspx

CREATE TABLE tblparent(
id INTEGER PRIMARY KEY auto_increment,
name VARCHAR(50)
)engine=innodb;
CREATE TABLE tblchild(
id INTEGER PRIMARY KEY auto_increment,
name VARCHAR(50),
parent_id INTEGER,
FOREIGN KEY(parent_id) REFERENCES tblparent(id) ON DELETE CASCADE
)engine=innodb;
In that case, when the parent row is deleted, all the rows on the referenced child table that referred on that id will also deleted.
That is called cascading delete.

Related

How to create SQL constraint on primary key to make sure it could only be referenced once?

How do I add constraint to guard that a primary key could only be referenced once?(It could be referenced in two tables)
Each reference should have a unique value out of the primary key.
Table A
----------------------
id
1
2
3
4
Table B
----------------------
id a_id (foreign key to table A.id)
1 2
2 3
Table C
----------------------
id a_id (foreign key to table A.id)
1 1
I want something to happen to give error when try to insert a_id = 2 into table C as its used in table B already.
You can use an INSERT, UPDATE trigger on each of the child tables to ensure that the PK of the parent table that is about to be inserted or updated does not already exist in the other child table.
What you are trying to do requires another table D, that will help unify the references to A.
Table D will contain its own primary key ( Id ), a reference to table A with a UNIQUE constraint on it (call it AId ), and a third column (called "RowType") to indicate to which of the child tables (B or C) the row corresponds. You can make this column to be of type int, and assign value "0" for B and "1" for C, for example.
Then in table B you add a foreign key to D.Id, AND another column "BRowType" as foreign key to D.RowType; then you define a constraint on this column, so it can only have the value '0' ( or whatever value you have decided to correspond to this table).
For table C your constraint will limit the values to '1'.
Or course, in order to insert a record into B or C you first need to create a record in D. But once you have a record in B that references a record in D, which in turn links to a record in A, you will no longer be able to create a record in C for the same line in A - because of the UNIQUE constraint on D.AId AND the constraint on C.BRowType.
If I understand the question correctly, it sounds like you need to add a unique constraint on the column of each table that references your primary key.
For example:
Table A
----------------------
id (primary key)
1
2
3
Table B
----------------------
id a_id (foreign key to table A.id)
1 2
2 3
Set the a_id column to be UNIQUE and that way you can ensure that the primary key from Table A is not used twice. You would do that in each table which references A.id
If you want to avoid using triggers, you could create a table X with id and a unique constraint on it.
In each transaction in which you insert a record into B or C you have to insert into X as well. Both insertions will only be possible if not yet in the other table.

Join query to delete a record both in child class and parent class

I need to delete a record in both child table and parent table with the reference to another column.The primary key of one table is equal to foreign key of another table.eg.table A.pkid=table B.fkid
How do I use join query or cascade to delete it.
I tried couple of queries but it shows invalid syntax.
delete from
table A table B where pkid=(SELECT fk_id from table B)
where name='SEP' from table B
delete from
table A join table B ON table A.fk_id=(SELECT pk_id FROM table B)
where name='SEP' from table B
delete from
table A join table B ON A.fk_id=B.pk_id
where name='SEP' from table B
Could you please refine my query or give me a link where I can get some help on this? Thanks a lot.
It looks like all you need is something simple:
BEGIN WORK;
DELETE FROM A WHERE fk_id IN (SELECT pk_id FROM B WHERE name = 'SEP');
DELETE FROM B WHERE name = 'SEP';
COMMIT WORK;
The alternative is to define the PK-FK relationship in the schema with the ON DELETE CASCADE option, and children will be automatically deleted on deletion of the parent.

How to delete nested child using Trigger in SQLite

I need to delete nested items in my table using triggers. I have a folder table, table have a Id and parrentID. For example
ID FolderName ParentID
--------------------------------
1 A Null
2 B 1
3 C 2
4 D 3
If i delete ID 1 then it will be delete all the record 2,3,4 because 1 is a top parent. There is any way?
The documentation says that
[recursion] cannot be used within a CREATE TRIGGER.
However, if you declare the relationship correctly, you can tell the database to delete the children automatically:
CREATE TABLE MyTable(
ID INTEGER PRIMARY KEY,
FolderName TEXT,
ParentID INTEGER REFERENCES MyTable(ID) ON DELETE CASCADE
);

Can I use select statement with check constraint

My table is parent-child table where it includes two columns. The first column is ID which is auto number. The other column is ParentID which has the special conditions. If the row is parent the ParentID = 0 otherwise it should be related to a ParentID row. For example:
**ID** | **ParentID**
---------------------
1 0
2 0
3 2
4 [it can be 0 or 1 or 2 NOT 3]
The ParentID depends on the ID column, if the ID includes ParentID = 0 then the ParentID can be that ID.
The question is can i do something like this??
constraint ParentID_ck ckeck(ParentID in(0, select ID from table where ParentID = 0;))
Or I should use other solution such as PL/SQL:
DECLARE
--Somthing..
BEGIN
--Somthing..
END;
And put it inside the check constraint.
You need to implement this constraint with combination of foreign key constraint and a trigger
You may use a null-able foreign key from the table to itself.(parentID == null shows the root nodes).
For the part of select ID from table where ParentID = 0 (null) of the constraint you may use a after insert or update DML trigger, some trigger examples could be found here
You can do something like:
insert into TABLE_NAME(PARENT_ID,ID)
(select <THE_PARENT_ID>, <ID> from DUAL where
exists (select 1 from TABLE_NAME where PARENT_ID = <THE_PARENT_ID>))
So that those PARENT_ID's which are actually not in the TABLE_NAME would not be inserted.
You can do this by fixing your data model first. Your table has two kinds of entities - Parents and Children. Create a separate table for your Parents, then you can use ordinary referential constraints.

SQL query to combine existence check and condition check

I have 2 tables, call A and B. A has a foreign key on B. call them A_ID and B_ID respectively. But the constraint not enforced in the design. I am not supposed to change the schema. I need to delete entries from table A based on 2 conditions.
1)If table B doesn't contain A_ID
2)If some condition on B is met.
I have formed a query something like this. But I dont think its optimal. Is there a better way of doing this?
delete from A where A_ID not in (select B_ID from B where status='x' )
or A_ID not in (select B_ID from B)
You could use not exists to delete rows without a matching entry in table B. This one treats status = 'x' as if no match was found, i.e. it will delete those rows:
delete A
where not exists
(
select *
from B
where B.B_ID = A.A_ID
and status <> 'x'
)
JustABitOfCode and UltraCommit told about omitting one part
furthermore, if it's a foreign key, you can say to keep deleting unwanted A in definition:
CREATE TABLE A
(
uniqeidentifire A_ID
, FOREIGN KEY (A_ID) REFERENCES B(B_ID) ON DELETE CASCADE
);
This will Automatically delete each A that does not have a B match
and this is more efficient
As just explained from JustABitOfCode, please remove the condition:
(select B_ID from B where status='x')
because it is redundant: the result set of the previous select, is a SUBSET of the result set of the following select:
(select B_ID from B)