Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Delete clears the table instead of erroring

I have a piece of SQL which (you would think) wouldn't compile, but which instead deletes all rows from the target table.

Consider this setup:

create table TableA (ColumnA varchar(200));
create table TableB (ColumnB varchar(200));

insert TableA values ('A'),('B'),('C');
insert TableB values ('A');

Then the following sql:

--Returns all rows from TableA
select * from TableA;

--Does not error (ColumnA does not exist on TableB)
delete TableA where ColumnA in (select ColumnA from TableB)

--No Rows are returned
select * from TableA;

The delete statement above causes all rows to be removed from TableA, rather than erroring that ColumnA doesn't exist in TableB

There's a SQL Fiddle demontrating this here: http://www.sqlfiddle.com/#!3/9d883/6

It seems that the ColumnA from TableA is being picked up, but expected it to be "out of scope".

Why is this?

like image 666
Jon Egerton Avatar asked Oct 11 '12 17:10

Jon Egerton


People also ask

Why can't I delete a table in SQL?

The reason SQL won't let you drop a table in this situation is because the allocation pages/extent chain appears to be damaged or cross-linked in some way. So SQL Server thinks that there is actually data from other tables in pages/extents belonging to the problem object.

Does deleting from CTE delete from table?

We run a delete against a CTE in SQL Server and the table's values are affected – this differs from taking data from a table to a temp table and removing data from the temp table. The source table still has the records. This logic does not carry over to using these with joined delete statements.

Does delete statement maintains any lock on table?

By default, a DELETE statement always acquires an exclusive (X) lock on the table it modifies, and holds that lock until the transaction completes.


1 Answers

That works as expected, due to the correlation between ColumnA in the inner query to the outer.

This commonly used correlated query pattern is valid

DELETE TableA WHERE NOT EXISTS (select * from TableB where TableB.ID=TableA.ID)

It removes TableA entries that don't have a dependent record in TableB.

It shows that you can reference TableA columns in a correlated query. In your query

delete TableA where ColumnA in (select ColumnA from TableB)

The inner query is producing

  • one row for each record in TableB
  • one column for each row, whose value is ColumnA from outer query

So the DELETE goes through

like image 52
RichardTheKiwi Avatar answered Sep 29 '22 01:09

RichardTheKiwi