Procedure deleting related rows - sql

I want to implement procedure that will delete rows from 3 related table.
I have table, A, B, and C.
Table A
ID
Table B
ID
tableAId
Table C
ID
tablceBId
relation table A - B is one to many and relation B - C is one to many.
Now I want to implement a procedure that would delete all rows that are related with Table A. I do not want to make these delete on the cascade. Can I achieve this in one query?
I pass ID of row in Table A.

CREATE PROCEDURE delTableA
#tableA_ID int
AS
BEGIN
DELETE C
FROM C
INNER JOIN B ON C.ID = B.tableCId
INNER JOIN A ON B.ID = A.tableBId
WHERE A.ID = #tableA_ID
DELETE B
FROM B
INNER JOIN A ON B.ID = A.tableBId
WHERE A.ID = #tableA_ID
DELETE FROM A
WHERE A.ID = #tableA_ID
END
GO
As in,
CREATE TABLE C (ID int)
CREATE TABLE B (ID int, tableCId int)
CREATE TABLE A (ID int, tableBId int)
GO
INSERT INTO c VALUES (1)
INSERT INTO b VALUES (1, 1)
INSERT INTO a VALUES (1, 1)
GO
CREATE PROCEDURE delTableA
#tableA_ID int
AS
BEGIN
DELETE C
FROM C
INNER JOIN B ON C.ID = B.tableCId
INNER JOIN A ON B.ID = A.tableBId
WHERE A.ID = #tableA_ID
DELETE B
FROM B
INNER JOIN A ON B.ID = A.tableBId
WHERE A.ID = #tableA_ID
DELETE FROM A
WHERE A.ID = #tableA_ID
END
GO
EXEC delTableA 1
GO
If you run this query, all are empty:
select * from A
select * from B
select * from C

Related

Multiple Joins and Subquery with Not Exists

I want to delete records from the BETA TABLE that doesn't exist in the ALPHA Table as well as excludes the records obtained by the inner join of CHARLIE and DELTA tables.
This is the query for A & B
SELECT B.* from ALPHA A right join
BETA B ON A.ID= B.ID
where A.ID is NULL
This gives me the records of BETA Table that don't exist in Alpha Table
Now my second query is
SELECT C.* FROM CHARLIE C INNER JOIN
DELETE D ON
C.ID=D.ID
This gives me the records from the inner join of CHARLIE AND DELTA
I have tried using the query below, but it doesn't work and doesn't delete anything
DELETE B
From ALPHA A right join
BETA B ON A.ID = B.ID
where A.ID is NULL AND NOT EXISTS
( SELECT C.* FROM CHARLIE C INNER JOIN DELTA D ON
C.ID = D.ID WHERE B.ID = C.ID )
I would really appreciate any help.
I have solutions for you using "IN" and "Exists". Please check and let me know.
DECLARE #ALPHA TABLE( ID INT,VAL1 DECIMAL(18,2),VAL2 DECIMAL(18,2));
DECLARE #BETA TABLE( ID INT,VAL1 DECIMAL(18,2),VAL2 DECIMAL(18,2));
DECLARE #CHARLIE TABLE( ID INT,VAL1 DECIMAL(18,2),VAL2 DECIMAL(18,2));
DECLARE #DELTA TABLE( ID INT,VAL1 DECIMAL(18,2),VAL2 DECIMAL(18,2));
------------------------USING IN-------------------------------
DELETE FROM #BETA
WHERE ID IN (SELECT B.ID from #ALPHA A right join #BETA B ON A.ID= B.ID
WHERE A.ID is NULL )
OR ID IN (SELECT C.ID FROM #CHARLIE C INNER JOIN #DELTA D ON C.ID=D.ID)
-------------------Using Exists--------------------
DELETE FROM #BETA
WHERE Exists (SELECT B.* from #ALPHA A right join #BETA B ON A.ID= B.ID
where A.ID is NULL )
OR Exists (SELECT C.* FROM #CHARLIE C INNER JOIN #DELTA D ON C.ID=D.ID)
Note: I have used Sql table variables instead of Normal table.
Just use not exists/exists for both. I am not sure what "as well as excludes the records obtained by the inner join of CHARLIE and DELTA tables".
If you want to delete records where both conditions are met, then
DELETE B FROM BETA B
WHERE NOT EXISTS (SELECT 1 FROM ALPHA A WHERE A.id = B.ID
) OR
EXISTS (SELECT 1
FROM CHARLIE C INNER JOIN
DELTA D
ON C.ID = D.ID
WHERE B.ID = C.ID
) ;
If you don't want the CHARLIE/DELTA records to be excluded, then use AND NOT EXISTS rather than OR EXISTS.

How to insert into a SQL table column using SELECT query?

I have tables A, B, and C.
I want to insert UserRoleName values in table C, into UserRoleName column in table A for the corresponding UserId. UserId in Table A, is a foreign key from Table B. UserRoleId is a foreign key in table B from table C. How can I do that?
I tried using this query,
insert into A (UserRoleName)
(
select C.UserRoleName
from C
inner join B on B.UserRoleId = C.UserRoleId
inner join A on A.UserId = B.UserId
)
But this is giving:
Cannot insert the value NULL into column 'Z
which is a non-nullable in column A. I didn't specify that column in picture of the table A though. Can you help me figure out what I am doing wrong?
You need to use update as follows:
Update a
Set a.userrolename = c.rolename
From b join c on b.userroleid = b.userroleid and b.userid = a.userid
Where a.userrolename is null
Or using standard sql (subquery) as follows:
Update a
Set a.userrolename =
(Select c.userrolename
From b join c on b.userroleid = c.userroleid
Where b.userid = a.userid)
Where a.userrolename is null;

is there a syntactic shortcut similar to coalesce for union?

What I'm trying to do is:
select
A.Fuzz
,A.Fizz
,B.Whiz
from A
left outer join B
on A.Fuzzy B=Wuzzy
To replace:
select
A.Fuzz
,A.Fizz
,B.Whiz
from A
left outer join B
on A.Fuzzy B=Wuzzy
UNION ALL
select
B.wuzz
,A.Fizz
,B.Whiz
from A
left outer join B
on A.Fuzzy B=Wuzzy
May be this is something "near" what you think (done on MSSQL)?. Pls in every question post sample data, expected result, etc.
CREATE TABLE A (ID INT, DESC_A VARCHAR(10));
INSERT INTO A VALUES (1,'A');
INSERT INTO A VALUES (2,'B');
CREATE TABLE B (ID INT, DESC_B VARCHAR(10));
INSERT INTO B VALUES (2,'Z');
INSERT INTO B VALUES (3,'Y');
SELECT COALESCE(A.ID, B.ID) AS ID
, A.DESC_A
, B.DESC_B
FROM A
FULL JOIN B ON A.ID = B.ID
Output:
ID DESC_A DESC_B
1 A NULL
2 B Z
3 NULL Y

Differences between forms of LEFT JOIN

What is the difference between these query
SELECT
A.AnyField
FROM
A
LEFT JOIN B ON B.AId = A.Id
LEFT JOIN C ON B.CId = C.Id
and this another query
SELECT
A.AnyField
FROM
A
LEFT JOIN
(
B
JOIN C ON B.CId = C.Id
) ON B.AId = A.Id
Original answer:
They are not the same.
For example a left join b left join c will return a rows, plus b rows even if there are no c rows.
a left join (b join c) will never return b rows if there are no c rows.
Added later:
SQL>create table a (id int);
SQL>create table b (id int);
SQL>create table c (id int);
SQL>insert into a values (1);
SQL>insert into a values (2);
SQL>insert into b values (1);
SQL>insert into b values (1);
SQL>insert into c values (2);
SQL>insert into c values (2);
SQL>insert into c values (2);
SQL>insert into c values (2);
SQL>select a.id from a left join b on a.id = b.id left join c on b.id = c.id;
id
===========
1
1
2
3 rows found
SQL>select a.id from a left join (b join c on b.id = c.id) on a.id = b.id;
id
===========
1
2
2 rows found
The first query is going to take ALL records from table a and then only records from table b where a.id is equal to b.id. Then it's going to take all records from table c where the resulting records in table b have a cid that matches c.id.
The second query is going to first JOIN b and c on the id. That is, records will only make it to the resultset from that join where the b.CId and the c.ID are the same, because it's an INNER JOIN.
Then the result of the b INNER JOIN c will be LEFT JOINed to table a. That is, the DB will take all records from a and only the records from the results of b INNER JOIN c where a.id is equal to b.id
The difference is that you may end up with more data from b in your first query since the DB isn't dropping records from your result set just because b.cid <> c.id.
For a visual, the following Venn diagram shows which records are available
SELECT
A.AnyField
FROM
A
LEFT JOIN B ON B.AId = A.Id
LEFT JOIN C ON B.CId = C.Id
In this query you are LEFT JOINing C with B which will give you all records possible with B whether or not there is a match to any records in C.
SELECT
A.AnyField
FROM
A
LEFT JOIN
(
B
JOIN C ON B.CId = C.Id
) ON B.AId = A.Id
In this query you are INNER JOINing C with B which will result in matching B and C records.
Both queries will give you the same result set as you are only pulling records from A so you will not see what records had matches and what did not in regards to B and C.

t-sql insert - select - with parameters

I have a 4 tables. One of the tables we are going to be inserting data into (Table A).
Table A is going to receive misc data from Table B, C, D and also some unknown variable parameter data.
How do I set up the INSERT with a SELECT with also receiving parameters?
Something like this?
Insert INTO TableA (col1, col2,col3,col4)
SELECT b.col1, c.col2, d.col3, #myparam
FROM TableB as b
INNER JOIN TableC as c
ON b.id = c.id
INNER JOIN TableD as d
on c.id = d.id
Something like this:
DECLARE #a int, #b int
SET #a = 5
SET #b = 7
INSERT INTO TableA(Column1, Column2)
SELECT SomeOtherColumn, #a
FROM TableB
UNION
SELECT YetAnotherColumn, #b
FROM TableC