Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

marceloms

Stored procedure com dois cursores

Recommended Posts

Pessoal

 

Estou tendo um problema com uma stored procedure que trabalha com dois cursores. Para fácil entendimento do problema, suponham as seguintes tabelas (todas fictícias):

 

1) Clientes

2) Endereços

3) Meios de contato.

 

A relação é de um para n entre clientes e endereços e clientes e meios de contato.

A sp precisa pegar os endereços (pode ser mais de um) e meios de contato (podem ser mais de um) de um cliente e copiar para outro cliente. O problema está no fato de a variável @@FETCH_STATUS ter escopo global. A sp precisa dar um "loop" e inserir os endereços e, em seguida, dar outro "loop" (usando o segundo cursor) e inserir os meios de contato.

 

Sei que cursores no MSSQL é pesado pacas, mas tenho um servidor que aguenta o tranco e, até onde sei, não tenho outra opção. Fazer isto no Oracle ou Firebird/Interbase e uma moleza, mas no MS está complicado e pesado. Vou colocar o código real da sp abaixo para os amigos analisarem todo o código.

 

ALTER PROCEDURE [dbo].[SP_COPIAR_ESPECIFICACAO] 	-- Add the parameters for the stored procedure here	@CopyFromEspec int, 	@PasteToEspec intASBEGIN declare @codesp int declare @idmat int declare @tagmat varchar(10) declare @tagcli varchar(10) declare @bitini decimal(5,2) declare @bitfin decimal (5,2) declare @nomser varchar(30) declare @sigser varchar(5) declare @preser smallint declare @unipre char(5) declare @temser smallint declare @unitem char(5) declare @corser int declare @unicor char(5) SET NOCOUNT ON; DECLARE Cur_Especificacao cursor for  select codesp, idmat, tagmat, tagcli, bitini, bitfin from especificacoes_materiais    where codesp = @CopyFromEspec  DECLARE Cur_Servicos cursor for  select nomser, sigser, preser, unipre, temser, unitem, corser, unicor  from servicos where codesp = @CopyFromEspec --Copia as especificações...  Open Cur_Especificacao FETCH NEXT FROM Cur_Especificacao INTO @codesp, @idmat, @tagmat, @tagcli, @bitini, @bitfin	 WHILE @@FETCH_STATUS = 0  BEGIN	insert into especificacoes_materiais (codesp, idmat, tagmat, tagcli, bitini, bitfin)	  values (@PasteToEspec, @idmat, @tagmat, @tagcli, @bitini, @bitfin)			FETCH NEXT FROM Cur_Especificacao INTO @codesp, @idmat, @tagmat, @tagcli, @bitini, @bitfin  END Close Cur_Especificacao Deallocate Cur_Especificacao--Agora copia os serviços.... Open Cur_ServicoFETCH NEXT FROM Cur_Servicos INTO @nomser, @sigser, @preser, @unipre, @temser, @unitem, @corser, @unicor	 WHILE @@FETCH_STATUS = 0  BEGIN	insert into servicos (nomser, sigser, codesp, preser, unipre, temser, unitem, corser, unicor)	  values (@nomser, @sigser, @PasteToEspec, @preser, @unipre, @temser, @unitem, @corser, @unicor)	FETCH NEXT FROM Cur_Servicos INTO @nomser, @sigser, @preser, @unipre, @temser, @unitem, @corser, @unicor  END Close Cur_Servicos Deallocate Cur_ServicosEND

 

Agradeço desde já a ajuda.

 

Marcelo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Marcelo beleza?

 

Aparentemente seu código está correto e enxuto, o fato de ter dois cursores não influi diretamente na performance da sp. A maioria dos servidores suportam tal carga. O segredo de cursores está no select que você faz, ou seja, sempre pesquisar por chaves e índices.

 

Eu alterei um pouco o código mantendo a idéia no que entendi. Eu utilizo MSSQL 2000. você não precisa citar várias vezes DECLARE e sim separar as variáveis com virgulas. coloquei os cursores como variável local (@) é mais rápido e não precisa desalocar memória. (DEALLOCATE).

 

 

Você ainda pode otimizar utilizando o FAST_FORWARD (te aconselho a dar uma olhada no Books on-line, selecione a palavra e depois Shift + f1)

 

ALTER PROCEDURE [dbo].[SP_COPIAR_ESPECIFICACAO]	-- Add the parameters for the stored procedure here	@CopyFromEspec int,	@PasteToEspec intASdeclare @codesp int,@idmat int,@tagmat varchar(10),@tagcli varchar(10),@bitini decimal(5,2),@bitfin decimal (5,2),@nomser varchar(30),@sigser varchar(5),@preser smallint,@unipre char(5),@temser smallint,@unitem char(5),@corser int,@unicor char(5)SET NOCOUNT ONDECLARE @Cur_Especificacao  CURSORSET   @Cur_Especificacao = cursor for  select codesp, idmat, tagmat, tagcli, bitini, bitfin from especificacoes_materiais   where codesp = @CopyFromEspec--Copia as especificações...Open @Cur_EspecificacaoFETCH FROM @Cur_Especificacao INTO @codesp, @idmat, @tagmat, @tagcli, @bitini, @bitfin	WHILE @@FETCH_STATUS = 0  BEGIN	insert into especificacoes_materiais (codesp, idmat, tagmat, tagcli, bitini, bitfin)						values (@PasteToEspec, @idmat, @tagmat, @tagcli, @bitini, @bitfin)			FETCH NEXT FROM @Cur_Especificacao INTO @codesp, @idmat, @tagmat, @tagcli, @bitini, @bitfin  ENDClose @Cur_EspecificacaoDECLARE @Cur_Servicos  CURSOR Set @Cur_Servicos  = cursor for  select nomser, sigser, preser, unipre, temser, unitem, corser, unicor  from servicos where codesp = @CopyFromEspec--Agora copia os serviços....Open @Cur_ServicosFETCH FROM @Cur_Servicos INTO @nomser, @sigser, @preser, @unipre, @temser, @unitem, @corser, @unicor	WHILE @@FETCH_STATUS = 0  BEGIN	insert into servicos (nomser, sigser, codesp, preser, unipre, temser, unitem, corser, unicor)	  values (@nomser, @sigser, @PasteToEspec, @preser, @unipre, @temser, @unitem, @corser, @unicor)	FETCH NEXT FROM Cur_Servicos INTO @nomser, @sigser, @preser, @unipre, @temser, @unitem, @corser, @unicor  ENDClose @Cur_ServicosRETURN

 

Você (pelo menos em MSSQL) assim como muitos programadores e analistas têm dificuldades com SP, Triggers, etc, Enfim qualquer objeto de banco de dados o que faz os mesmos manipular os dados na aplicação. Discordo com esse pensamento, pois um executável fica mais pesado e o servidor de BD fica ocioso, é sempre bom fazer um levantamento dos requisitos e distribuir o processamento entre BD e aplicação.

Os servidores de BD mais comuns têm muitas funcionalidades que deviam ser exploradas antes de sair montando sua tela da aplicação.

 

Vale a pena dar uma estudada em BD's são muito mais do que um repositório de dados.

 

 

Abs.

Qualquer dúvida poste novamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.