DELETE FROM usuarios; Ooops!

Todo mundo já deu um enter antes da hora. Ou esqueceu só um detalhezinho numa linha antes de dar aquele enter gostoso. Não importa o motivo, DELETEs e UPDATEs são instruções perigosas em SQL.

Sempre que for escrever um DELETE no console do banco de dados comece escrevendo o WHERE primeiro.

WHERE spam = true;

Coloque o select:

SELECT subject FROM emails WHERE spam = true;

Confira o resultado, é como se fosse um preview, são as linhas que queria remover?


| subject |
| Ganhe 100 mil reais |
| Ganhe 200 mil reais |
| Ganhe 300 mil reais |

3 results

Por fim, troque o select por delete:

DELETE FROM emails WHERE spam = true;

Assim você evita que um enter acidental apague sua tabela toda.

Claro que é interessante evitar executar tais operações em produção, pelo perigo que elas apresentam, mas mesmo localmente diversas vezes apagamos algo que estamos testando e sofremos para correr atrás do prejuízo, restaurando o banco novamente.

Não só no mundo SQL, em qualquer outro banco de dados onde executamos operações destrutivas é importante conferirmos o resultado de nossas ações primeiro verificando quais elementos serão afetados.

Quer fugir de outros pepinos graves do SQL e facilitar o seu dia a dia com banco de dados? Receba dicas e boas práticas do nosso expert Guilherme Silveira, uma por dia, na série de Dicas e Boas práticas de SQL.

Ou se quer ir direto para um aprendizado mais profundo, não deixe de conhecer os diversos cursos de banco de dados, SQL e NOSql que o Alura possui.

14 Comentários

  1. Leandro 14/10/2015 at 11:10 #

    Você diz que não devemos fazer isso direto em produção. Qual alternativa então para apagar determinadas tuplas em produção caso o sistema não tenha esta opção de remover? Obrigado.

  2. Guilherme 14/10/2015 at 21:19 #

    Quando executo algum comando crítico em produção eu costumo fazer uso de transações. Começo com BEGIN TRAN, executo o comando e então verifico a quantidade de linhas afetadas. Se estiver igual à quantidade de linhas esperada então faço um COMMIT, caso contrário ROLLBACK. Já me salvou algumas vezes! Só não pode demorar muito, senão a transação vai começar a travar outros processos.

  3. Hebert 14/10/2015 at 21:59 #

    Você pode usar comandos de rollback com save point, por exemplo no postgresql eu uso da seguinte maneira

    BEGIN;
    SAVEPOINT meusavepoint;
    delete from log where oid = ‘12345’;

    –neste ponto testo para ver se foi o efeito esperado, se sim rodo o commit, senão rodo o rollback

    ROLLBACK TO SAVEPOINT meusavepoint; –caso queira desfazer
    COMMIT; — caso queira confirmar a alteração

  4. Ricardo Rocha 15/10/2015 at 10:08 #

    Eu gostaria de acrescentar que uma boa prática é desabilitar o auto commit para evitar que ações sejam executadas fora de um contexto transacional. Desta forma você pode até cair na armadilha do enter, mais ainda poderia desfazer a ação via rollback.

  5. Ricardo 15/10/2015 at 13:13 #

    Além de fazer conforme indicado, ainda sim faço dentro de transações 😉

  6. Guilherme Silveira 16/10/2015 at 15:36 #

    Bom dia Leandro, se você não tem acesso nenhum a produção, fica sem ter como remover mesmo. Era isso que quis dizer?

    Guilherme, Hebert, Ricardo, com certeza! Transações e save points são soluções para qualquer alteração de dados, tanto local quanto (evitar evitar evitar) em produção. Juntar as duas técnicas (como vocês mesmo citaram) é melhor ainda: se um falha, ainda temos o outro para nos salvar.

  7. Renato Stoll 19/10/2015 at 22:14 #

    Trabalho direto com Oracle DB usando sempre SQL direto na base de producao. Faço exatamente isso quando vou deletar ou atualizar linhas de uma tabela, primeiro seleciono e vejo se realmente é o que desejo alterar ou excluir, depois troco o select pelo delete from …. Ou update … Set… É uma prática que salva vidas.

  8. Renato Stoll 19/10/2015 at 22:18 #

    Estava esquecendo uma coisa importante, caso seja algo crítico, não custa fazer um backup antes, ex. Usando um

    Create table xxxxxx as select * from …

    Isso para caso de um commit fora do tempo. Hehe

  9. Leandro 20/10/2015 at 10:39 #

    Guilherme, não foi isso que eu quis dizer. É que no seu texto você diz: “Claro que não devemos executar nenhuma dessas operações em produção”. Isso deu a entender, pra mim, que você diz que não devemos usar um comando delete direto em produção. Então, por isso eu perguntei qual alternativa temos então para apagar algo em produção. Já que você disse que não devemos usar um “delete” em produção.

  10. Guilherme Silveira 27/10/2015 at 15:52 #

    Oi Renato!

    Ótima dica do backup. Cada banco acaba oferecendo uma abordagem um pouco diferente, na lista de dicas e boas práticas sugerimos o select like (suportado pelo mysql e postgre), bem parecido. Muito bom.

    Oi Leandro, desculpe, corrigi o texto para deixar mais claro “claro que é interessante evitar executar queries do genero em produção”, ao inves do original que parecia ser “nunca nunca nunca”. O que achou?

  11. Rafael 22/11/2015 at 19:25 #

    Leandro, se você não entendeu o que o autor quis dizer e se fez de desentendido, procure aprender interpretação primeiro, pois desse jeito só deve produzir código ruim.

  12. Leonardo Brito 18/12/2015 at 21:18 #

    No Oracle, podemos usar a flash recovery area, bastando inserir os dados que estavam na tabela antes do delete.

    INSERT INTO emails (SELECT *
    FROM emails AS OF TIMESTAMP (SYSTIMESTAMP – INTERVAL ’60’ MINUTE))
    MINUS SELECT * FROM emails);

    A flash recovery area do Oracle vem configurada por default, 2 horas de retenção, mas que pode ser alterado. Aqui onde trabalho temos uma politica de rentenção de 24 horas.

  13. Dan Jesus 31/12/2015 at 08:26 #

    Bem legal o post, quando tenho que deletar informações em produção costumo deletar com WHERE IN usando um select isso ajuda bastante.

    Então faço uma query de select por exemplo:
    SELECT id FROM users WHERE status = 0;
    Vejo o resultado da query select e aplico a query para remover:
    DELETE FROM users WHERE id IN(SELECT id FROM users WHERE status = 0)

Deixe uma resposta