Olá! Seja bem-vindo!

Executar um update sem where é uma das situações mais desagradáveis que pode acontecer na área de tecnologia, então o assunto de hoje é extremamente relevante: Como EVITAR UPDATE sem WHERE.

 

Se você já fez o treinamento de “Transact-SQL” para desenvolvedores, disponível em meu site, aprendeu meus 3 segredos para garantir que essa situação desastrosa nunca ocorra com você, porém nem todos que trabalham com o banco que você cuida fizeram o treinamento.

 

Por essa razão, hoje veremos uma forma de você definitivamente evitar update sem where nos bancos que você administra.

 

Como EVITAR UPDATE sem WHERE

Para impedir que desavisados façam update sem where em nosso banco usaremos triggers e a propriedade contexto_info. Abaixo o script da aula de hoje para você testar e usar como base na sua implementação:

 

[sociallocker id=”5114″]



-------------------------------------------------------------------------------
-- Como evitar UPDATE sem WHERE
-------------------------------------------------------------------------------
--------------------------------------------------------
-- Requisitos para nosso teste
--------------------------------------------------------
-- Banco de testes
use master
if db_id('curso') is not null 
	drop database curso
go
create database curso
go
use curso
go

-- cria a tabela amigos 
if object_id('amigos') is not null drop table amigos
create table amigos (id int primary key, nome varchar(100), email varchar(100), dt_nascimento date) 
insert into amigos values (1, 'Zézão', '[email protected]', '1990-01-02') 
insert into amigos values (2, 'Zezinho', '[email protected]', '1990-02-01')
insert into amigos values (3, 'Abismail', '[email protected]', '1991-03-04')
insert into amigos values (4, 'Lazarildo', '[email protected]', '1991-03-04')
insert into amigos values (5, 'Febril', '[email protected]', '1992-03-04')
insert into amigos values (6, 'Falsiane', '[email protected]', null)
go


--------------------------------------------------------
-- O que ocorre em geral :S
--------------------------------------------------------
-- Consultar amigos
select * from amigos

-- Atualizar a data de aniversário do amigo...
update amigos set dt_nascimento = '1980-02-01'


--------------------------------------------------------
-- SOLUÇÃO 1: Trigger para impedir rowcount = count(*)
--------------------------------------------------------
-- Trigger para impedir
if object_id('tr_amigos_impede_sem_where') is not null drop trigger tr_amigos_impede_sem_where 
go
create trigger tr_amigos_impede_sem_where on amigos for update, delete 
as begin
	declare @count int = @@rowcount
	if @count = (select sum(row_count) from sys.dm_db_partition_stats where object_id = object_id('amigos') and index_id in (0,1))
		begin
			raiserror('ATENÇÃO: Não é permitido atualizar todos os registros de uma só vez. A transação foi cancelada.', 16, 1)
			rollback transaction
		end
end
go

-- TR permite somente update "COM where":
update amigos set dt_nascimento = '1980-02-01' where id = 6
update amigos set dt_nascimento = '1980-02-01'
select * from amigos
go

-- Permitir update sem where temporário para ADMINS
alter table amigos disable trigger all
update amigos set dt_nascimento = '1980-02-01'
alter table amigos enable trigger all
go

--------------------------------------------------------
-- SOLUÇÃO 2: Permitir sem where via codigo da TR
--------------------------------------------------------
if object_id('tr_amigos_impede_sem_where') is not null drop trigger tr_amigos_impede_sem_where 
go
create trigger tr_amigos_impede_sem_where on amigos WITH ENCRYPTION for update, delete 
as begin
	declare @count int = @@rowcount
	if context_info() = 0x1234567890
		begin
			set context_info 0x -- reinicia o context_info para permitir apenas 1 execução sem where
			print 'Contexto admin, verificação de update/delete sem where não realizada.'
		end
	else
		if @count = (select sum(row_count) from sys.dm_db_partition_stats where object_id = object_id('amigos') and index_id in (0,1))
			begin
				raiserror('ATENÇÃO: Não é permitido atualizar todos os registros de uma só vez. A transação foi cancelada.', 16, 1)
				rollback transaction
			end
end


-- TR é desativada no "context_info administrativo":
select context_info from sys.dm_exec_sessions where session_id = @@spid;
set context_info 0x1234567890;
update amigos set dt_nascimento = '1980-02-01' where id = 6
update amigos set dt_nascimento = '1980-02-01' where id between 1 and 3
update amigos set dt_nascimento = '1980-02-01'
select * from amigos
go


[/sociallocker]

 

Se você quiser, pode inclusive melhorar essa trigger para que ela registre em um log as tentativas de update sem where. Se esse for o caso, consulte o meu artigo “Como descobrir quem mexeu no seu SQL” para entender melhor como você pode registrar informações em um log usando uma trigger. Somando o conhecimento de hoje com o do artigo que indiquei você terá a base necessária para fazer essa implementação com maestria.

CONCLUSÃO

Update sem where só é engraçado em memes da internet…

 

Brincadeiras a parte, espero muito que você que acompanha o blog e já fez meus treinamentos NUNCA passe por uma dessas. Alias, em poucas ocasiões podemos de verdade usar as palavras NUNCA e/ou SEMPRE, mas acho que para esse caso é apropriado:

– NUNCA deixe de usar as técnicas que lhe ensinei no curso evitar update sem where;

– SEMPRE preocupe-se em evitar que outros façam update sem where nos bancos que você cuida.

 

Espero que também tenha gostado desse conteúdo.

 

Abraço do seu amigo Josué 🙂

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *