segunda-feira, 14 de abril de 2008

Instrução GO do Editor de Query do SQL Server 2005

Uma novidade do editor de query do SQL Server 2005 é a instrução GO, que agora aceita um número que determina quantas vezes o bloco será executado.

Exemplo:

SELECT GETDATE()
GO 2

Beginning execution loop

-----------------------
2008-04-14 23:12:37.687

(1 row(s) affected)

-----------------------
2008-04-14 23:12:37.700

(1 row(s) affected)

Batch execution completed 2 times.


Outro exemplo:

Select Getdate()
go 2
Select 'Teste da instrução GO'
go 3

Beginning execution loop

-----------------------
2008-04-14 23:14:09.577

(1 row(s) affected)

-----------------------
2008-04-14 23:14:09.577

(1 row(s) affected)

Batch execution completed 2 times.
Beginning execution loop

---------------------
Teste da instrução GO

(1 row(s) affected)

---------------------
Teste da instrução GO

(1 row(s) affected)

---------------------
Teste da instrução GO

(1 row(s) affected)

Batch execution completed 3 times.


Veja que nesse caso ele executou 3 vezes a instrução após o primeiro GO e antes do segundo.

Um exemplo prático:

- Preencher uma tabela com dados aleatórios.

Create Table TesteCarga
(id int identity(1,1), ValorRand int , Flag bit )
go

insert into TesteCarga (ValorRand) values (rand()*100)
go 10

select * from TesteCarga
go
















Vamos criar uma trigger exemplo, somente para verificar um erro que pode ocorrer na atulização de uma tabela e como podemos contornar com a instrução GO.
Essa trigger é somente para demonstração e simular um erro. O seu código não tem funcionalidade que agregue valor de conhecimento.

Create Trigger TRGTeste on TesteCarga
for update
as
begin
declare @id int
set @id = rand(10) + (select valorrand from inserted)
end
go

update TesteCarga set flag = 0
go

Msg 512, Level 16, State 1, Procedure TRGTeste, Line 6
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.

O erro ocorreu por que a subquery dentro da trigger está retornando mais de um valor quando utilizado em uma expressão. Isso ocorreu porque o comando update executou a atulização da coluna FLAG para todas as linhas e gerau o tabela INSERTED com as 10 ocorrências.

Para resolver o problema, o correto é fazer a atualização linha por linha. No exemplo abaixo, isso é possivel com a instrução GO

update TesteCarga set flag = 0
where id in (select top 1 id from TesteCarga where flag is null )
go 10

Como a tabela TesteCarga tem a coluna FLAG com o valor NULL para todas as linhas e ela tem um identificador único, então é selecionado uma única ocorrência dessa tabela para a coluna FLAG igual a NULL.
Essa única ocorrência é passada para o comando update que atualiza apenas uma linha. Quando a instrução GO executa o comando pela segunda vez, ele não carregará mais esse linha, já que a FLAG não tem o valor NULL e sim a próxima que atenda a condição.

select * from TesteCarga

Nenhum comentário: