Deletando N últimas linhas no MySQL e no Oracle

Seguindo a idéia apresentada em um tópico de um fórum, onde foi solicitada uma solução para deleção de N últimas linhas de uma tabela no MySQL. A questão é bem simples de resolver, principalmente porque o MySQL fornece tanto ORDER BY como LIMIT para o DELETE, isso mesmo, ORDER BY no DELETE!

Assim fica mole então né? Vamos ao exemplo removendo as últimas 5 linhas de uma tabela através de um campo de valor único crescente.!

mysql> create table teste (id int not null auto_increment primary key);
Query OK, 0 rows affected (0.03 sec)
 
mysql> insert into teste values (null),(null),(null),(null),(null),(null),(null),(null),(null),(null);
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0
 
mysql> select * from teste;
+----+
| id |
+----+
|  1 | 
|  2 | 
|  3 | 
|  4 | 
|  5 | 
|  6 | 
|  7 | 
|  8 | 
|  9 | 
| 10 | 
+----+
10 rows in set (0.00 sec)
 
mysql> delete from teste order by id desc limit 5;
Query OK, 5 rows affected (0.00 sec)
 
mysql> select * from teste;
+----+
| id |
+----+
|  1 | 
|  2 | 
|  3 | 
|  4 | 
|  5 | 
+----+
5 rows in set (0.00 sec)

O ORDER BY veio a solucionar também o problema de não poder-se usar a tabela do DELETE em questão em uma subquery no WHERE, veja o que acontece se tentarmos:

mysql> delete from teste where id > (select id from teste order by id desc limit 5,1);
ERROR 1093 (HY000): You can't specify target table 'teste' for update in FROM clause

Envolvi o Oracle no meio da história, porque nele podemos usar a tabela envolvida no DELETE na subquery, e por outro lado não temos ORDER BY no DELETE, nem muito menos um LIMIT.
Uma das maneiras possíveis de se fazer no Oracle, apesar de várias outras, seria:

SQL>
  1  create table teste as
  2  select level id
  3  from dual
  4* connect by level <= 10
SQL> /
 
Tabela criada.
 
SQL> select * from teste;
 
	ID
----------
	 1
	 2
	 3
	 4
	 5
	 6
	 7
	 8
	 9
	10
 
10 linhas selecionadas.
 
SQL> delete from teste where id >= (select id from (select row_number() over (order by id desc) r, id from teste) where r = 5)
 
5 linhas deletadas.
 
SQL> select * from teste;
 
	ID
----------
	 1
	 2
	 3
	 4
	 5

É isso ae!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options