How to delete items that exist in one table from another? - sql

I have tables A and B. Items of table B might exist also in table A, and I want to delete those items. What would the SQL statements to do this look like?

this is an option
delete from a
where a.key in (select key from b)

Either:
DELETE a
WHERE a.some_field IN (SELECT some_field FROM b)
or
DELETE A
WHERE EXISTS (SELECT 1 FROM b WHERE b.field1 = a.field2)
Depending on your database, you may find one works particularly better than the other. IIRC Oracle tends to prefer WHERE EXISTS to IN but this can depend on a number of factors.

In certain DBs the rather exotic looking DELETE FROM FROM is very efficient
delete from foo from foo as f
where exists
(
select 1 from bar as b where b.field = f.field
)

Something like:
DELETE
FROM TableA as A
WHERE A.ID IN (SELECT ID
FROM TableB AS B
WHERE [your condition here])

If your tables use InnoDB, the easiest way would be to setup table A with foreign keys from table B, and use ON DELETE CASCADE. That way no code changes are necessary, and the integrity of your database is guaranteed.

This is allowed according to the standard.
delete a from a join b on a.id = b.id;

DELETE FROM FIRST_TABLE FT
WHERE EXISTS(
SELECT 1
FROM SECOND_TABLE ST
WHERE ST.PRIMARY_KEY = FT.PRIMARY_KEY
);

delete a
--select a.*
from tablea a
join tableb b on a.someid = b.someid
Make sure that you run the select part first to ensure that you are getting the records you want.

Related

How do I delete all rows in a table which have a null foreign key reference?

I have two tables, A and B. A has a column B_Id which references the Id column of table B.
There are a number of rows in table A that have a value for B_Id, but that value does not exist anywhere in the list of Ids of table B.
I want to delete all of these particular rows.
I've tried
select * from A left join B on A.B_Id = B.Id where B.Id = null
But this doesn't select anything at all. How can I change the select to retrieve the rows I want?
NOT EXISTS comes to mind:
select a.*
from a
where not exists (select 1 from b where b.id = a.b_id);
You can easily incorporate this into a delete if you want to remove the rows:
delete from a
where not exists (select 1 from b where b.id = a.b_id);
BUT . . . you should really fix the problem moving forward by putting in a proper constraints. You seem to want a NOT NULL constraint and a FOREIGN KEY constraint.
You need where b.id is null rather than where b.id = null. In SQL, nothing is equal to null (nor different than null): to compare against null, you need special construct is [not] null.
I think that this is simpler expressed with not exists:
select a.*
from a
where not exists (select 1 from b where b.id = a.b_id)
If you wanted a delete statement:
delete from a
where not exists (select 1 from b where b.id = a.b_id)
You need to use the IS operator, like
select * from A left join B on A.B_Id = B.Id where B.Id is null
the reason is that null is unkown and the language isn't certain whether something is equal to it or not. You can also do it via not exists as Gordon Linoff has already pointed out.
Whatever you try, make sure that you make a full backup of your table.
If B_Id is already a foreign key and foreign key checking is enabled for your database, then you can safely assume that every record that has no pair in B has a B_Id of null in A, which renders the join and checking for existence unnecessary.
You can select the data you want to delete with
SELECT * FROM A
WHERE B_ID NOT IN (SELECT ID FROM B);
To delete these rows just use this
DELETE FROM A
WHERE B_ID NOT IN (SELECT ID FROM B);

Deleting rows from a join of two tables and rownum condition in Oracle DB

Learning PL/SQL with Oracle DB and trying to accomplish the following:
I have two tables a and b. I am joining them on id, add several conditions and then try removing resulting rows only from table a in a batch size of 1000. Base query looks like this:
DELETE (SELECT *
FROM SCHEMA.TABLEA a
INNER JOIN SCHEMA.TABLEB b ON a.b_id = b.id
WHERE par=0 AND ROWNUM <= 1000);
This obviously doesn’t work as I am trying to manipulate a view: “data manipulation operation not legal on this view”
How can I rewrite this?
you can only remote from a table, there now Need to do a join. you can handle it in a where clause if you Need
you delete Statement could be e.g.
DELETE from SCHEMA.TABLEA a
where a.id in (select b.id from SCHEMA.TABLEB b)
and par=0 AND ROWNUM <= 1000
You can write simple query which checks if the rows in TABLEA that are required to be deleted exists in TABLEB.
DELETE
FROM schema.tablea a
WHERE par = 0
AND EXISTS (SELECT 1 FROM schema.tableb b WHERE a.b_id = b.id)
AND rownum <= 1000;

delete functionality incremental load in sql server

I need to delete records that are present in the destination table but not in the source table. The primary key in the destination table is an auto_increment ID which is not there in the source table. Both the source and destination tables contain a set of unique key combinations which can be used to uniquely identify the rows in either tables. What is the approach that I should follow? How can I delete if I am to use multiple column combinations as the unique key and not one primary key(not there in source)?
delete from dest_table
where (uniq_key_col1,uniq_key_col2) not in (
select dest.uniq_key_col1,dest.uniq_key_col2
from dest_table dest
join source_table source
on dest.uniq_key_col1=source.uniq_key_col1
and dest.uniq_key_col2=source.uniq_key_col2
)
This is how it should ideally look (provided just for clarity and please ignore the error in where clause because of multiple columns)
You can use exists. ie:
delete from dest_table
where not exists (
select *
from source_table source
where dest_table.uniq_key_col1=source.uniq_key_col1
and dest_table.uniq_key_col2=source.uniq_key_col2
);
You can do like this :
DELETE
FROM dbo.dest a
WHERE NOT EXISTS (
SELECT 1
FROM dbo.source1 b
WHERE a.id1 = b.ID1 and a.id2 = b.id2
)
It sounds like NOT EXISTS is what you need
DELETE d FROM dest_table d
WHERE NOT EXISTS (SELECT (PUT_APPROPRIATE_COLUMNS_HERE) from source_table s
WHERE d.col1 = s.col
AND d.col2 = s.col2
... etc for other columns
)
Note the table aliasing, you need that. And it might be more appropriate to use an inner join, if that is possible with your data.
Another option for you
DELETE dest_table
FROM dest_table
LEFT JOIN source_table
ON dest_table.uniq_key_col1 = source_table.uniq_key_col1
AND dest_table.uniq_key_col2 = source_table.uniq_key_col2
WHERE source_table.uniq_key_col1 IS NULL

counting abscense or rows

I need to write a stored procedures to update contacts who have no active pledges in our database, I can't seem to find a way of counting contacts with 0 rows on the pledges table.
The external key in the pledges table is supporter_id, I've tried using Count(*), but it only returns 1 or more.
Thanks in advance.
PS: This is on a MS SQL database.
We'd need more information to give you a specific answer, but there are a number of ways to identify non-matching records, here are two:
LEFT JOIN:
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
WHERE b.ID IS NULL
NOT EXISTS:
SELECT *
FROM TableA a
WHERE NOT EXISTS (SELECT *
FROM TableB b
WHERE a.ID = b.ID)
I ended using a subquery so I first determine who has pledges of the type I want and then look for contacts who are not in that list.
thanks for the responses.

How can I compare two tables and delete the duplicate rows in SQL?

I have two tables and I need to remove rows from the first table if an exact copy of a row exists in the second table.
Does anyone have an example of how I would go about doing this in MSSQL server?
Well, at some point you're going to have to check all the columns - might as well get joining...
DELETE a
FROM a -- first table
INNER JOIN b -- second table
ON b.ID = a.ID
AND b.Name = a.Name
AND b.Foo = a.Foo
AND b.Bar = a.Bar
That should do it... there is also CHECKSUM(*), but this only helps - you'd still need to check the actual values to preclude hash-conflicts.
If you're using SQL Server 2005, you can use intersect:
delete * from table1 intersect select * from table2
I think the psuedocode below would do it..
DELETE FirstTable, SecondTable
FROM FirstTable
FULL OUTER JOIN SecondTable
ON FirstTable.Field1 = SecondTable.Field1
... continue for all fields
WHERE FirstTable.Field1 IS NOT NULL
AND SecondTable.Field1 IS NOT NULL
Chris's INTERSECT post is far more elegant though and I'll use that in future instead of writing out all of the outer join criteria :)
I would try a DISTINCT query and do a union of the two tables.
You can use a scripting language like asp/php to format the output into a series of insert statements to rebuild the table the resulting unique data.
try this:
DELETE t1 FROM t1 INNER JOIN t2 ON t1.name = t2.name WHERE t1.id = t2.id