Reaching the tree END in oracle - sql

I have one requirement...Suppose we have three table
1.A
primary key a_id
2.B
primary key b_id
foreign key a_id
3.C
primary key c_id
foreign key b_id
these tables contain 10 records each.
Need : Now i want to delete a specific record from each table.The record will be delete on a value supplied as a_id(primary key of table A).It will delete from A alright but how i can delete it from c as it does not contain a_id and this is only value known to us.
So how to do it...can anyone please let me know nay approach or anything.I need to delete a specific record from each table.starting point is a_id which is only thing known to us.
I am using oracle 10g and I cannot use any sys table. Thats a requirement as dba has given admin access.

you can do with the help of ON DELETE CASCADE option
see here here

CREATE TABLE A (a_id NUMBER, CONSTRAINT a_pk PRIMARY KEY (a_id));
CREATE TABLE B
(
b_id NUMBER
,a_id
,CONSTRAINT b_pk PRIMARY KEY (b_id)
,CONSTRAINT b_fk FOREIGN KEY (a_id) REFERENCES A (a_id)
);
CREATE TABLE C
(
C_id NUMBER
,b_id
,CONSTRAINT c_pk PRIMARY KEY (c_id)
,CONSTRAINT c_fk FOREIGN KEY (b_id) REFERENCES B (b_id)
);
--creating dummy data
insert into A select level from dual connect by level<11 ;
insert into B(b_id,a_id) select level+10,level from dual connect by level<11;
insert into C(c_id,b_id) select level+20,level+10 from dual connect by level<11;
CREATE OR REPLACE PROCEDURE delete_a(p_a_id IN a.id%TYPE)
IS
BEGIN
--delete record from C first
DELETE FROM C WHERE b_id IN (SELECT b_id from B where a_id =p_a_id);
--delete record from B
DELET FROM B WHERE a_id = p_a_id;
--delete from the main table
DELETE FROM C where a_id = p_a_id;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error while delete the recods '||SQLERRM);
ROLLBACK;
END delete_a;
Note:I have not tested the code ,but will work with this approach

I use the table script as follows:
CREATE TABLE A (a_id NUMBER CONSTRAINT a_pk PRIMARY KEY,a_grade CHAR(1));
CREATE TABLE b
( b_id NUMBER ,
b_grade CHAR(1),
CONSTRAINT b_pk PRIMARY KEY(b_id),
CONSTRAINT b_fk FOREIGN KEY (b_id) REFERENCES A(a_id)
ON DELETE CASCADE );
CREATE TABLE c
( c_id NUMBER,
c_grade CHAR(1),
CONSTRAINT c_pk PRIMARY KEY(c_id),
CONSTRAINT c_fk FOREIGN KEY(c_id)
REFERENCES b(b_id)
ON DELETE CASCADE );
BEGIN
INSERT INTO A VALUES(1,'a');
INSERT INTO b VALUES(1,'b');
INSERT INTO c VALUES(1,'c');
end;
/*below is the query that you provide in the table a to delete */
DELETE FROM A WHERE a_id=1;-- all tables values are deleted (parent and childs)
SELECT * FROM A;
SELECT * FROM b;
SELECT * FROM c;
hope this is what you needed.

Related

oracle sql - on delete cascade in both directions

I have table A and table B, where the primary key of table B references the primary key of table A. If i use on delete cascade on table B how can i ensure that rows of table A are deleted when i delete a row in table B?
Edit:
Merging is unfortunately not the solution to my problem.
In my database i have three tables that are relevant for this situation.
This is what it looks like:
CREATE TABLE TABLE_A
(
TABLE_A_ID INTEGER NOT NULL,
...
PRIMARY KEY(TABLE_A_ID)
);
CREATE TABLE TABLE_B
(
TABLE_B_ID INTEGER REFERENCES TABLE_A(TABLE_A_ID) ON DELETE CASCADE,
...
PRIMARY KEY(TABLE_B_ID)
);
CREATE TABLE TABLE_C
(
TABLE_C_ID INTEGER REFERENCES TABLE_A(TABLE_A_ID) ON DELETE CASCADE,
...
PRIMARY KEY(TABLE_C_ID)
);
Although it is possible to create rows in A on its own i dont want any rows that are only in A.
Now if I delete a row in B, I want the row in A with the same ID deleted too. I dont want any ID that is only in A, or only not in A.

SQL best solution for the delete operation on multiple relationships

I would like to have a clarification on deleting the multiple relationship
I have a schema that has a table 'A' and other tables of schema, that refer to 'A' with the role (Cascade) on delete operation.
There are also tables which refer to 'A' and which also have other references to other tables of 'A', but in this case the elimination must have a null value.
CREATE TABLE A
(A_ID INTEGER PK
...
)
CREATE TABLE B
(B_ID INTEGER PK
A_ID INTEGER NOT NULL
...
FOREIGN KEY A_ID REFERENCES A(A_ID) ON DELETE CASCADE
)
CREATE TABLE C
(C_ID INTEGER PK
A_ID INTEGER NOT NULL
B_ID INTEGER
...
FOREIGN KEY A_ID REFERENCES A(A_ID) ON DELETE CASCADE
FOREIGN KEY B_ID REFERENCES B(B_ID) ON DELETE SET NULL
)
These multiple relationships cause me a problem on the role delete operation.
I would have two options:
The first, and take on the role cascade all relationship with 'A', but that means I have to create a function that when I have to delete values of table 'A', the other value reference with this table delete from the bottom up. In the future I might forget to add a new table.
The second solution and create a table of connection to their reporting obligations have null values:
CREATE TABLE C
(C_ID INTEGER PK
A_ID INTEGER NOT NULL
...
FOREIGN KEY A_ID REFERENCES A(A_ID) ON DELETE CASCADE
)
CREATE TABLE C_B
(C_ID INTEGER PK
B_ID INTEGER PK
...
FOREIGN KEY C_ID REFERENCES C(C_ID) ON DELETE CASCADE
FOREIGN KEY B_ID REFERENCES B(B_ID) ON DELETE CASCADE
)
It involves the creation of several new bridging tables.
There is a different solution to this case?
I currently use Apache Derby and JPA for persistence

SQLite on delete cascade with two foreign keys

If I have two tables and a third table that is the foreign key to the first and second table as follows:
CREATE TABLE A
(
name VARCHAR(255),
PRIMARY KEY(name)
);
CREATE TABLE B
(
number INT,
PRIMARY KEY(number)
);
CREATE TABLE C
(
cname VARCHAR(255),
cnumber INT,
PRIMARY KEY(cname, cnumber),
FOREIGN KEY(cname) REFERENCES A(name) ON DELETE CASCADE,
FOREIGN KEY(cnumber) REFERENCES B(number) ON DELETE CASCADE
);
INSERT INTO A values("John");
INSERT INTO A values("Sam");
INSERT INTO B values(1);
INSERT INTO B values(2);
INSERT INTO C values("John", 1);
INSERT INTO C values("John", 2);
INSERT INTO C values("Sam", 2);
I want to delete 1 such that (1) is deleted from B and the entry (John,1) is also deleted from C and (John) in A is also deleted.
Because there is DELETE CASCADE I should be able to do it but:
DELETE FROM B WHERE number = 1;
only removes 1 from B and (John,1) from C but (John) in A is not deleted.
So far I was only able to delete an entry from 1 table and have the other table with the foreign key to delete its entry, but I'm not sure how to delete another table that also references this table with the foreign key with JUST 1 query.
What you want to achieve is not possible using foreign keys, at least not the way you have set it up.
Table C has a foreign-key on A, so entries from C will be removed if the corresponding key in A is removed, not the other way around.
If you want to delete from A when entries in C are deleted, A would need to have a foreign key on C.
BUT this requires, that cname would be a unique key in C. Sqlite will allow you to set up and insert data, but it won't allow you to delete if there are multiple entries for something that is referenced as foreign-key.
PRAGMA foreign_key = true;
CREATE TABLE B
(
number INT,
PRIMARY KEY(number)
);
CREATE TABLE C
(
cname VARCHAR(255),
cnumber INT,
PRIMARY KEY(cname, cnumber),
FOREIGN KEY(cnumber) REFERENCES B(number) ON DELETE CASCADE
);
CREATE TABLE A
(
name VARCHAR(255),
PRIMARY KEY(name)
FOREIGN KEY(name) REFERENCES C(came) ON DELETE CASCADE
);
INSERT INTO B values(1);
INSERT INTO B values(2);
INSERT INTO C values("John", 1);
INSERT INTO C values("John", 2);
INSERT INTO C values("Sam", 2);
INSERT INTO A values("John");
INSERT INTO A values("Sam");
INSERT INTO C values("John", 1);
INSERT INTO C values("John", 2);
INSERT INTO C values("Sam", 2);
DELETE FROM B where number = 1;
Error: foreign key mismatch - "A" referencing "C"

Foreign Key for either-or column?

Is it possible to have a foreign key that requires either column A or column B to have a value, but not both. And the foreign key for column A matches Table 1 and the foreign key for column B matches Table 2?
A check constraint can handle this. If this is SQL Server, something like this will work:
create table A (Id int not null primary key)
go
create table B (Id int not null primary key)
go
create table C (Id int not null primary key, A_Id int null, B_Id int null)
go
alter table C add constraint FK_C_A
foreign key (A_Id) references A (Id)
go
alter table C add constraint FK_C_B
foreign key (B_Id) references B (Id)
go
alter table C add constraint CK_C_OneIsNotNull
check (A_Id is not null or B_Id is not null)
go
alter table C add constraint CK_C_OneIsNull
check (A_Id is null or B_Id is null)
go
It depends on which database you're working with. If you want a table Foo that has FK relationships to Table1 and to Table2 but only one at a time, then you'll need to set up either some sort of trigger (my links assume SQL Server, but the ideas's the same) or Constraint to enforce your rule that only one column have a value.
it is not necessary that a column have values in it at that time of applying foreign key,but the column name would be same and the data types as well.

Check if data exists in another table on insert?

Table A
(
Table_A_ID int
)
Table B
(
Table_B_ID int
Value int
)
Say I want to insert data into Table B, where 'Value' would be the same as a Table_A_ID.
How would I make a constraint or check that the data actually exists in the table on insertion?
You probably need to enforce data integrity not only on INSERT into Table B, but also on UPDATE and DELETE in both tables.
Anyway options are:
FOREIGN KEY CONSTRAINT on Table B
TRIGGERs on both tables
As a last resort if for some reason 1 and 2 is not an option STORED PROCEDUREs for all insert, delete update operations for both tables
The preferred way to go in most cases is FOREIGN KEY CONSTRAINT.
Yap, I agree with #peterm.
Cause, if your both Table_A_ID and Table_B_Id are primary keys for both tables, then you don't even need two tables to store the value. Since, your two tables are seems to be on 'one-to-one' relationship. It's one of the database integrity issues.
I think you didn't do proper normalisation for this database.
Just suggesting a good idea!
I found this example which demonstrates how to setup a foreign key constraint.
Create employee table
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
Create borrowed table
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Add a constraint to borrowed table
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
NOTE: This tells MySQL that we want to alter the borrowed table by adding a constraint called ‘FK_borrowed’. The employeeid column will reference the id column in the employee table – in other words, an employee must exist before they can borrow a book.
The final two lines are perhaps the most interesting. They state that if an employee ID is updated or an employee is deleted, the changes should be applied to the borrowed table.
NOTE: See the above URL for more details, this is just an excerpt from that article!
Create a foreign key constraint on the column 'Value' on table B that references the 'Table_A_ID' column.
Doing this will only allow values that exist in table A to be added into the 'Value' field of table B.
To accomplish this you first need to make Table_A_ID column the primary key for table A, or it at least has to have some sort of unique constraint applied to it to be a foreign key candidate.
BEGIN TRANSACTION -- REMOVE TRANSACTION AND ROLLBACK AFTER DONE TESTING
--PUT A PRIMARY KEY ON TABLE A
CREATE TABLE A
( Table_A_ID int CONSTRAINT PK_A_Table_A_ID PRIMARY KEY)
--ON VALUE ADD A FOREIGN KEY CONSTRAINT THAT REFERENCEs TABLE A
CREATE TABLE B
( Table_B_ID int,
[Value] int CONSTRAINT FK_B_Value_A REFERENCES A(Table_A_ID)
)
-- TEST VALID INSERT
INSERT A (Table_A_ID) VALUES (1)
INSERT B (Table_B_ID, [Value]) VALUES (1,1)
--NOT ALLOW TO INSERT A VALUE THAT DOES NOT EXIST IN A
--THIS WILL THROW A FOREIGN KEY CONSTRAINT ERROR
INSERT B (Table_B_ID, [Value]) VALUES (1,2) -- 2 DNE in table A
ROLLBACK
Note: there is no magic to 'FK_B_Value_A' or 'PK_A_Table_A_ID' it simply a naming convention and be called anything. The syntax on the foreign key and primary key lines work like this:
column-definition CONSTRAINT give-the-constraint-a-name REFERENCES table-name ( table-column )
column-definition CONSTRAINT give-the-constraint-a-name PRIMARY KEY