How to delete from 3 tables with one query using where exists - sql

I have four tables Monitoring, Participant, Participant validation group, Validation group,
I would like to delete all monitorings, and there particpants also each particpant possibly (not always) has participant validation group.
Blockquote
but i have the error sql command not properly ended.
NOTE: I am on oracle database and inner joins would not work here.
I would like to achieve an optimized query
that could take only the application number of monitoring and delete all monitorings, participants for each monitoring and participant validation group.
I am not sure if its actually possible in a single query if its not then what could be the optimized way to do this. and I cant use jpa for this at the moment.
Expected results, both monitorings are deleted, and there particpants as well as participant validation groups

You can define foreign keys on child tables to "ON DELETE CASCADE". So when you delete a parent table it will delete associated rows from child tables.
create table parent (
id NUMBER(10),
value varchar2(30),
constraint parent_pk primary key (id)
);
CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id)
ON DELETE CASCADE
);
CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value)
ON DELETE CASCADE
);
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');
insert into child values (1,1);
insert into child values (1,2);
insert into child values (1,3);
insert into child values (2,1);
insert into child values (2,2);
insert into child values (2,3);
insert into child values (3,1);
insert into child values (3,2);
insert into child values (3,3);
insert into grandchild values (1,1);
insert into grandchild values (1,2);
insert into grandchild values (1,3);
insert into grandchild values (2,1);
insert into grandchild values (2,2);
insert into grandchild values (2,3);
insert into grandchild values (3,1);
insert into grandchild values (3,2);
insert into grandchild values (3,3);
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
DELETE from parent where value = 'a';
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
PARENT_CNT CHILD_CNT GRANDCHILD_CNT
2 6 6

Related

SQL doesn't allow me to insert data

creating table and inserting data into a table and now it giving me an error
SQL Error: ORA-02291: integrity constraint (S21403051.SYS_C007300)
violated - parent key not found 02291. 00000 - "integrity
constraint (%s.%s) violated - parent key not found" *Cause:
CREATE TABLE CUSTOMER(
CUSTOMER_ID VARCHAR(10) PRIMARY KEY,
FIRST_NAME VARCHAR(10),
SURNAME VARCHAR(15),
CUSTOMER_TEL VARCHAR(12),
CUSTOMER_EMAIL VARCHAR(30)
)
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_1', 'CUST_102', 'EMP_51');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_3','CUST_101','EMP_51');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_3','CUST_101','EMP_53');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_5','CUST_103','EMP_54');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_5','CUST_107','EMP_54');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_1', 'CUST_106','EMP_55');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_1','CUST_108','EMP_55');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_5','CUST_104','EMP_51');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_3','CUST_109','EMP_51');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_2','CUST_1010','EMP_52');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_2','CUST_1010','EMP_55');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_5','CUST_101','EMP_51');
INSERT INTO CUSTOMER_CRUISES VALUES ( 'CRUISE_5','CUST_103','EMP_51');
When you have defined 6 columns CUSTOMER_ID , FIRST_NAME , SURNAME ,
CUSTOMER_TEL,CUSTOMER_EMAIL and when you try to insert values, it takes in order of table definition. Instead you can try this way
Example:
INSERT INTO CUSTOMER_CRUISES
(column1, clumn2,column3)
values ('xx','xy','yz')
Yet, you can not insert duplicate value into first column as primary key is defined on it. And, it cant be null.
Hope this helps
Cause: A foreign key value has no matching primary key value.
This problem arises when you attempt to insert a record containing the Customer_ID column into the child table (CUSTOMER_CRUISES) and that this Customer_ID is not present in the parent table (CUSTOMER). When the Customer_ID (Foreign key) in CUSTOMER_CRUISES table does not get to reference the Customer_ID (primary key) in CUSTOMER table, an error is raised.
One workaround is to insert and make sure that the value is present in the CUSTOMER table first before inserting the values into the CUSTOMER_CRUISES table.

one parent sys_refcursor record contains a child sys_refcursor type with multiple records

DB: Oracle 11gR2
Hello,
I have 2 tables with parent child relationship (one-to-many) between them. Now I need to return a ref-cursor from a stored procedure which will return one row from the parent table corresponding to the input parameter and the corresponding records (can be an array) from the child tables. Note we don't want to repeat the result set from the parent. So basically we just want to return one record where the detail column is an array of records or a child sys refcursor inside the parent sys recursor. Question is how can I do it?
Below is the sample tables, data and usual procedure (returns multiple rows -- which is not intended):
create table parent
(
class_id varchar2(2),
class_name varchar2(10),
subject_name varchar2(10),
constraint pk_id primary key (class_id)
);
create table child
(
class_id varchar2(10),
student_name varchar2(10),
result varchar2(10),
constraint fk_id Foreign key (class_id) references parent(class_id)
);
insert into parent values('1', 'class_1', 'subject_1');
insert into parent values('2', 'class_2', 'subject_2');
insert into parent values('3', 'class_3', 'subject_3');
insert into parent values('4', 'class_4', 'subject_4');
insert into child values ('1', 'student_1', 'pass');
insert into child values ('1', 'student_2', 'fail');
insert into child values ('1', 'student_3', 'pass');
insert into child values ('2', 'student_1', 'pass');
insert into child values ('2', 'student_4', 'fail');
create or replace PROCEDURE get_data (
class_id_in IN parent.class_id%TYPE,
student_list_cur OUT SYS_REFCURSOR)
AS
BEGIN
OPEN student_list_cur FOR
SELECT p.class_name,
p.subject_name,
c.student_name,
c.result
FROM parent p, child c
WHERE p.class_id = c.class_id
AND p.class_id = class_id_in;
END get_data;
Again note that the sys-refcursor returns:
class_name subject_name student_name result
-------------------------------------------------------
class_1 subject_1 student_1 pass
class_1 subject_1 student_2 fail
class_1 subject_1 student_3 pass
Rather what I want is one record like:
parent.class_name,
parent.subject_name,
child.array_of_records SYS_REFCURSOR
Where child.array_of_records contains multiple of records of child.student_name, child.result corresponding to the same class_id.
Thanks.
You are looking for CURSOR SUBQUERY?
OPEN student_list_cur FOR
SELECT p.class_name,
p.subject_name,
CURSOR(SELECT c.student_name,
c.result
FROM
child c
WHERE p.class_id = c.class_id)
FROM parent p
WHERE p.class_id = class_id_in;

Complex SQL Count Query

Hello I've been stuck with one SQL query for my assignment and was hoping for some help.
I need to get the Project ID for the best executed project -the project where (VERY_GOOD record count + GOOD record count) - (VERY_BAD record count + BAD record count) is greatest
My schema and test records in database (HSQLDB)
CREATE TABLE
PROJECT
(
ID IDENTITY NOT NULL PRIMARY KEY,
PROJECT_NAME VARCHAR(255) NOT NULL
);
CREATE TABLE
RECORD
(
ID IDENTITY NOT NULL PRIMARY KEY,
RESULT VARCHAR(255) NOT NULL,
);
CREATE TABLE
RECORD_PROJECT
(
PROJECT_ID INTEGER NOT NULL,
RECORD_ID INTEGER NOT NULL,
PRIMARY KEY(PROJECT_ID, RECORD_ID),
FOREIGN KEY (PROJECT_ID) REFERENCES PROJECT(ID) ON DELETE CASCADE,
FOREIGN KEY (RECORD_ID) REFERENCES RECORD(ID)
);
And test data:
INSERT INTO PROJECT (PROJECT_NAME) VALUES ('Bake a cake');
INSERT INTO PROJECT (PROJECT_NAME) VALUES ('Clean the house');
INSERT INTO RECORD (RESULT) VALUES ('GOOD');
INSERT INTO RECORD (RESULT) VALUES ('VERY_GOOD');
INSERT INTO RECORD (RESULT) VALUES ('VERY_GOOD');
INSERT INTO RECORD (RESULT) VALUES ('BAD');
INSERT INTO RECORD (RESULT) VALUES ('VERY_BAD');
INSERT INTO RECORD_PROJECT (PROJECT_ID, RECORD_ID) VALUES (0,0);
INSERT INTO RECORD_PROJECT (PROJECT_ID, RECORD_ID) VALUES (1,1);
INSERT INTO RECORD_PROJECT (PROJECT_ID, RECORD_ID) VALUES (1,2);
INSERT INTO RECORD_PROJECT (PROJECT_ID, RECORD_ID) VALUES (0,3);
INSERT INTO RECORD_PROJECT (PROJECT_ID, RECORD_ID) VALUES (1,4);
(I removed unrelated fields from tables)
So with this data I have 3 good records and 2 bad, I would need to get the project which has the highest 'rating', which according to this right now would be Clean the house with 3 good ratings over 2 negative for other project.
Maybe someone would figure this out, thanks!
That should be the (not testet) SQL in MySQL-Dialect:
SELECT rp.PROJECT_ID, p.PROJECT_NAME
SUM(CASE WHEN rp.RECORD_ID < 3 THEN 1 ELSE 0 END) AS rating
FROM RECORD_PROJEKT AS rp
JOIN PROJECT AS p ON p.ID = rp.PROJECT_ID
GROUP BY rp.PROJECT_ID
ORDER BY rating DESC

How to avoid bad data entries in table through proper Key relationship?

I have 3 tables. widgets, widget types, widget type ID. I have created direct relationship between them. How can I avoid bad data going into Widget tables based on Widget_type and Widget_sub_Type. Please see my code. There is just one small thing missing.
Create table widgets (
Widget_ID int not null primary key,
Widget_type_ID int not null,
Widget_Sub_type_ID int,
Widget_Name varchar (50)
)
Create table Widget_Type (
Widget_Type_ID int not null primary key,
)
Create table Widget_Sub_type (
Widget_Sub_Type_ID int not null primary key,
Widget_Type_ID int not null
)
---adding foregin key constraints
Alter table widgets
ADD constraint FK_Widget_Type
FOREIGN KEY (Widget_type_ID)
References Widget_Type (Widget_type_ID)
Alter table widgets
ADD constraint FK_Widget_Sub_Type
FOREIGN KEY (Widget_Sub_type_ID)
References Widget_SUB_Type (Widget_SUB_type_ID)
Alter table widget_Sub_Type
ADD Constraint FK_Widget_Type_Alter
Foreign key (widget_Type_ID)
References Widget_Type (Widget_Type_ID)
---- insert values
insert Widget_Type values (1)
insert Widget_Type values (5)
insert Widget_Sub_type values (3,1)
insert Widget_Sub_type values (4,1)
insert Widget_Sub_type values (7,5)
insert Widget_Sub_type values (9,5)
-- This will error out which is correct
insert Widget_Sub_type values (5,6)
select * from Widget_Sub_type
select * from Widget_type
--Good
insert widgets (Widget_ID,Widget_Name, Widget_type_ID, Widget_Sub_type_ID)
values (1, 'TOY', 1, 3)
select * from widgets
--Good
insert widgets (Widget_ID,Widget_Name, Widget_type_ID, Widget_Sub_type_ID)
values (2, 'BatMan', 5, 7)
-- How to prevenet this, 3 is not sub_type_id of type_ID 5. This is bad data, It should not be inserted.
insert widgets (Widget_ID,Widget_Name, Widget_type_ID, Widget_Sub_type_ID)
values (3, 'Should Not', 5, 3)

Duplicating records efficiently in tsql

I've a scenario where I have a parent table which has '1 to many' relationships with two or three tables. These child tables again have '1 to many' relationships with more tables and so on. This goes up to 5 to 6 levels of hierarchy.
Now, based on single primary key value of the parent table, I want to duplicate all information related to it in database. I wrote a stored procedure which uses cursors and inserts child rows one by one and sets new foreign key values with each insert. But it is consuming some time because number of records in child tables is high.
Is there any other efficient way to do this?
In SQL Server 2008:
CREATE TABLE t_parent (id INT NOT NULL PRIMARY KEY IDENTITY, value VARCHAR(100))
CREATE TABLE t_child (id INT NOT NULL PRIMARY KEY IDENTITY, parent INT NOT NULL, value VARCHAR(100))
CREATE TABLE t_grandchild (id INT NOT NULL PRIMARY KEY IDENTITY, child INT NOT NULL, value VARCHAR(100))
INSERT
INTO t_parent (value)
VALUES ('Parent 1')
INSERT
INTO t_parent (value)
VALUES ('Parent 2')
INSERT
INTO t_child (parent, value)
VALUES (1, 'Child 2')
INSERT
INTO t_child (parent, value)
VALUES (2, 'Child 2')
INSERT
INTO t_grandchild (child, value)
VALUES (1, 'Grandchild 1')
INSERT
INTO t_grandchild (child, value)
VALUES (1, 'Grandchild 2')
INSERT
INTO t_grandchild (child, value)
VALUES (2, 'Grandchild 3')
DECLARE #tt TABLE (oid INT, nid INT)
MERGE
INTO t_parent
USING (
SELECT id, value
FROM t_parent
) p
ON 1 = 0
WHEN NOT MATCHED THEN
INSERT (value)
VALUES (value)
OUTPUT p.id, INSERTED.id
INTO #tt;
MERGE
INTO t_child
USING (
SELECT c.id, p.nid, c.value
FROM #tt p
JOIN t_child c
ON c.parent = p.oid
) c
ON 1 = 0
WHEN NOT MATCHED THEN
INSERT (parent, value)
VALUES (nid, value)
OUTPUT c.id, INSERTED.id
INTO #tt;
INSERT
INTO t_grandchild (child, value)
SELECT c.nid, gc.value
FROM #tt c
JOIN t_grandchild gc
ON gc.child = c.oid
In earlier versions of SQL Server, you will have to do a SELECT followed by an INSERT to find out the new values of the PRIMARY KEY.
You'll have to insert one table at a time, but you can do it by inserting sets instead of rows if you allow the FK values in the new parent's child tables to be the same as the FK values of the original parent.
Say you have a view of your parent table and in your sp you limit it to the row to copy from (pk=1, say).
Then insert that row into the parent table substituting PK=2 for the PK val.
Now use a second view of one of the child tables. In your sp, limit the set of rows to those with PK=1. Again, insert all those rows into that same child table substituting PK=2 for the PK field val.