Em bancos de dados relacionais, criamos tabelas para armazenar dados em diversos formatos. O SQL Server armazena dados em um formato de linha e coluna que contém um valor associado a cada tipo de dados. Quando projetamos tabelas SQL, definimos tipos de dados como integer, float, decimal, varchar e bit. Por exemplo, uma tabela que armazena dados do cliente pode ter campos como nome do cliente, email, endereço, estado, país e assim por diante. Vários comandos SQL são executados em uma tabela SQL e podem ser divididos nas seguintes categorias:
- Linguagem de definição de dados (DDL): Esses comandos são usados para criar e modificar os objetos de banco de dados em um banco de dados.
- Criar: Cria objetos
- Alterar: Modifica objetos
- Descartar: Exclui objetos
- Truncar: Exclui todos os dados de uma tabela
- Linguagem de manipulação de dados (DML): Esses comandos inserem, recuperam, modificam, excluem e atualizam dados no banco de dados.
- Selecione: Recupera dados de uma única ou várias tabelas
- Inserir: Adiciona novos dados em uma tabela
- Atualização: Modifica dados existentes
- Excluir: Exclui registros existentes em uma tabela
- Linguagem de controle de dados (DCL): Esses comandos estão associados a controles de direitos ou permissões em um banco de dados.
- Subsídio: Atribui permissões a um usuário
- Revogar: Revoga as permissões de um usuário
- Linguagem de controle de transações (TCL): Esses comandos controlam as transações em um banco de dados.
- Comprometer-se: Salva as alterações feitas pela consulta
- Reversão: Reverte uma transação explícita ou implícita para o início da transação ou para um ponto de salvamento dentro da transação
- Salvar transações: Define um ponto de salvamento ou marcador em uma transação
Suponha que você tenha dados de pedidos de clientes armazenados em uma tabela SQL. Se você continuasse inserindo dados nessa tabela continuamente, a tabela poderia conter milhões de registros, o que causaria problemas de desempenho em seus aplicativos. A manutenção do índice também pode se tornar extremamente demorada. Muitas vezes, você não precisa reter pedidos com mais de três anos. Nesses casos, você pode excluir esses registros da tabela. Isso economizaria espaço de armazenamento e reduziria seus esforços de manutenção.
Você pode remover dados de uma tabela SQL de duas maneiras:
- Usando uma instrução SQL delete
- Usando um truncado
Veremos a diferença entre esses comandos SQL mais tarde. Vamos primeiro explorar a instrução SQL delete.
Uma instrução de exclusão SQL sem quaisquer condições
Em instruções de linguagem de manipulação de dados (DML), uma instrução SQL delete remove as linhas de uma tabela. Você pode excluir uma linha específica ou todas as linhas. Uma instrução delete básica não requer nenhum argumento.
Vamos criar uma tabela Orders SQL usando o script abaixo. Esta tabela tem três colunas [OrderID], [ProductName] e [ProductQuantity].
Create Table Orders
( OrderID int,
ProductName varchar(50),
ProductQuantity int
)
Insira alguns registros nesta tabela.
Insert into Orders values (1,'ABC books',10),
(2,'XYZ',100),
(3,'SQL book',50)
Agora, suponha que queremos excluir os dados da tabela. Você pode especificar o nome da tabela para remover dados usando a instrução delete. Ambas as instruções SQL são iguais. Podemos especificar o nome da tabela a partir da palavra-chave (opcional) ou especificar o nome da tabela diretamente após a exclusão.
Delete Orders
Go
Delete from Orders
GO
Uma instrução de exclusão SQL com dados filtrados
Essas instruções SQL delete excluem todos os dados da tabela. Normalmente, não removemos todas as linhas de uma tabela SQL. Para remover uma linha específica, podemos adicionar uma cláusula where com a instrução delete. A cláusula where contém os critérios de filtro e eventualmente determina quais linhas remover.
Por exemplo, suponha que queremos remover o ID de pedido 1. Depois de adicionar uma cláusula where, o SQL Server primeiro verifica as linhas correspondentes e remove essas linhas específicas.
Delete Orders where orderid=1
Se a condição da cláusula where for falsa, ela não removerá nenhuma linha. Por exemplo, removemos o pedido 1 da tabela de pedidos. Se executarmos a instrução novamente, ela não encontrará nenhuma linha que satisfaça a condição da cláusula where. Nesse caso, ele retorna 0 linhas afetadas.
Instrução de exclusão SQL e cláusula TOP
Você também pode usar a instrução TOP para excluir as linhas. Por exemplo, a consulta abaixo exclui as 100 principais linhas da tabela Pedidos.
Delete top (100) [OrderID]
from Orders
Como não especificamos nenhum 'ORDER BY', ele seleciona linhas aleatórias e as exclui. Podemos utilizar a cláusula Order by para classificar os dados e excluir as linhas superiores. Na consulta abaixo, ele classifica o [OrderID] em ordem decrescente e o exclui da tabela [Orders].
Delete from Orders where [OrderID] In
(
Select top 100 [OrderID] FROM Orders
order by [OrderID] Desc
)
Excluindo linhas com base em outra tabela
Às vezes, precisamos excluir linhas com base em outra tabela. Essa tabela pode existir no mesmo banco de dados ou não.
- Pesquisa de tabela
Podemos usar o método de pesquisa de tabela ou a junção SQL para excluir essas linhas. Por exemplo, queremos excluir linhas da tabela [Orders] que satisfaçam a seguinte condição:
Deve ter linhas correspondentes na tabela [dbo].[Customer].
Veja a consulta abaixo, aqui temos uma instrução select na cláusula where da instrução delete. O SQL Server primeiro obtém as linhas que satisfazem a instrução select e, em seguida, remove essas linhas da tabela [Orders] usando a instrução SQL delete.
Delete Orders where orderid in
(Select orderid
from Customer)
- União SQL
Alternativamente, podemos usar junções SQL entre essas tabelas e remover as linhas. Na consulta abaixo, juntamos as tabelas [Pedidos]] com a tabela [Cliente]. Uma junção SQL sempre funciona em uma coluna comum entre as tabelas. Temos uma coluna [OrderID] que une as duas tabelas.
DELETE Orders
FROM Orders o
INNER JOIN Customer c ON o.orderid=c.orderid
Para entender a declaração de exclusão acima, vamos ver o plano de execução real.
De acordo com o plano de execução, ele executa uma varredura de tabela em ambas as tabelas, obtém os dados correspondentes e os exclui da tabela Orders.
- Expressão de tabela comum (CTE)
Também podemos usar uma expressão de tabela comum (CTE) para excluir as linhas de uma tabela SQL. Primeiro, definimos um CTE para encontrar a linha que queremos remover.
Em seguida, juntamos o CTE com a tabela SQL Orders e excluímos as linhas.
WITH cteOrders AS
(SELECT OrderID
FROM Customer
WHERE CustomerID = 1 )
DELETE Orders
FROM cteOrders sp
INNER JOIN dbo.Orders o ON o.orderid = sp.orderid;
Impactos no intervalo de identidade
As colunas de identidade no SQL Server geram valores sequenciais exclusivos para sua coluna. Eles são usados principalmente para identificar exclusivamente uma linha na tabela SQL. Uma coluna de chave primária também é uma boa opção para um índice clusterizado no SQL Server.
No script abaixo, temos uma tabela [Employee]. Esta tabela tem um id de coluna de identidade.
Create Table Employee
(
id int identity(1,1),
[Name] varchar(50)
)
Inserimos 50 registros nesta tabela que geraram os valores de identidade para a coluna id.
Declare @id int=1
While(@id<=50)
BEGIN
Insert into Employee([Name]) values('Test'+CONVERT(VARCHAR,@ID))
Set @id=@id+1
END
Se excluirmos algumas linhas da tabela SQL, isso não redefine os valores de identidade para os valores subsequentes. Por exemplo, vamos excluir algumas linhas que possuem valores de identidade de 20 a 25.
Delete from employee
where id between 20 and 25
Agora, visualize os registros da tabela.
Select * from employee where id>15
Ele mostra a lacuna no intervalo de valores de identidade.
Instrução de exclusão SQL e o log de transações
A exclusão do SQL registra cada exclusão de linha no log de transações. Suponha que você precise excluir milhões de registros de uma tabela SQL. Você não deseja excluir um grande número de registros em uma única transação porque isso pode fazer com que seu arquivo de log cresça exponencialmente e seu banco de dados também fique indisponível. Se você cancelar uma transação no meio, pode levar horas para reverter uma instrução de exclusão.
Nesse caso, você deve sempre excluir linhas em pequenos blocos e confirmar esses blocos regularmente. Por exemplo, você pode excluir um lote de 10.000 linhas por vez, confirmá-lo e passar para o próximo lote. Quando o SQL Server confirma a parte, o crescimento do log de transações pode ser controlado.
Práticas recomendadas
- Você deve sempre fazer um backup antes de excluir os dados.
- Por padrão, o SQL Server usa transações implícitas e confirma os registros sem perguntar ao usuário. Como prática recomendada, você deve iniciar uma transação explícita usando Begin Transaction. Ele lhe dá o controle para confirmar ou reverter a transação. Você também deve executar backups de log de transações frequentes se seu banco de dados estiver no modo de recuperação total.
- Você deseja excluir dados em pequenos pedaços para evitar o uso excessivo do log de transações. Também evita bloqueios para outras transações SQL.
- Você deve restringir as permissões para que os usuários não possam excluir dados. Somente os usuários autorizados devem ter acesso para remover dados de uma tabela SQL.
- Você deseja executar a instrução delete com uma cláusula where. Ele remove dados filtrados de uma tabela SQL. Se seu aplicativo requer exclusão frequente de dados, é uma boa ideia redefinir os valores de identidade periodicamente. Caso contrário, você poderá enfrentar problemas de esgotamento do valor de identidade.
- Caso você queira esvaziar a tabela, é aconselhável usar a instrução truncate. A instrução truncate remove todos os dados de uma tabela, usa log de transações mínimo, redefine o intervalo de valores de identidade e é mais rápida que a instrução SQL delete porque desaloca todas as páginas da tabela imediatamente.
- Caso você use restrições de chave estrangeira (relacionamento pai-filho) para suas tabelas, você deve excluir a linha de uma linha filha e depois da tabela pai. Se você excluir a linha da linha pai, também poderá usar a opção cascata ao excluir para excluir automaticamente a linha de uma tabela filha. Você pode consultar o artigo: Excluir cascata e atualizar cascata na chave estrangeira do SQL Server para obter mais informações.
- Se você usar a instrução top para excluir as linhas, o SQL Server excluirá as linhas aleatoriamente. Você deve sempre usar a cláusula top com a cláusula Order by e Group by correspondentes.
- Uma instrução delete adquire um bloqueio de intenção exclusivo na tabela de referência; portanto, durante esse período, nenhuma outra transação pode modificar os dados. Você pode usar a dica NOLOCK para ler os dados.
- Você deve evitar usar a dica de tabela para substituir o comportamento de bloqueio padrão da instrução SQL delete; ele deve ser usado apenas por DBAs e desenvolvedores experientes.
Considerações importantes
Há muitos benefícios em usar instruções SQL delete para remover dados de uma tabela SQL, mas, como você pode ver, isso requer uma abordagem metódica. É importante sempre excluir dados em pequenos lotes e proceder com cautela ao excluir dados de uma instância de produção. Ter uma estratégia de backup para recuperar dados no menor tempo possível é essencial para evitar tempo de inatividade ou impactos futuros no desempenho.