Cursor é melhor que SELECT INTO?

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
Avatar do usuário
tfg
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 83
Registrado em: Seg, 03 Mai 2004 3:38 pm
Localização: Novo Hamburgo - RS

Pessoal... Lanço uma dúvida minha:

Tenho trabalhado ultimamente em algumas Packages onde quase não é usado SELECTs INTO...
Pra qualquer coisa, os caras abriram um cursor, mesmo quando o cursor deve retornar apenas uma linha!

Tem algum motivo especial em se usar cursores em vez de SELECT diretos?
guerton
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 11
Registrado em: Ter, 26 Out 2004 12:44 pm
Localização: Sapiranga - Rs

Acredito que seja pelo motivo de quando não existir registro na tabela que você esta fazendo select dar erro de NO DATA FOUND.
Avatar do usuário
MuLtAnI
Moderador
Moderador
Mensagens: 90
Registrado em: Ter, 01 Jun 2004 9:21 am
Localização: Videira - SC
Contato:

acho que é porque com o cursor você tem as propriedades do objeto que podem ser tratadas com condições, tipo:

- CURSOR%ROWCOUNT
- CURSOR%FOUND
- CURSOR%ISOPEN
- CURSOR%%NOTFOUND

dae essas por exemplo retornam valores e você pode comparar e tal, uma instrução SQL como o colega falou, se ela não retornar nada ela retorna uma EXCEPTION.

[]'s
Avatar do usuário
MuLtAnI
Moderador
Moderador
Mensagens: 90
Registrado em: Ter, 01 Jun 2004 9:21 am
Localização: Videira - SC
Contato:

Aproveitando o tópico:

oque é mais rápido?

por exemplo um select into

supomos que para este select into eu tenha que criar 10 variáveis para a cláusula, não seria mais rápido criar um tipo record que contenha as definições dos campos e atibuir na cláusula into.

gostaria de saber qualquer vocês me dizem a respeito.

[]'s
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Quando tem muitos campos, eu gosto de abrir um cursor justamente pra isso - pra não precisar declarar todas variáveis.

Este é um exemplo do que eu estou falando: Guardar registro numa variável


[]´s
Avatar do usuário
MuLtAnI
Moderador
Moderador
Mensagens: 90
Registrado em: Ter, 01 Jun 2004 9:21 am
Localização: Videira - SC
Contato:

eu particularmente acho que é melhor trabalhar com uma variável do tipo Record doq N variáveis para um cursor. acho que fica mais eficiente o acesso por referência e depois se você precisar passar os valores como parâmetro para algum método, passa apenas uma variável ao invés de N.

o código além de mais rápido acaba ficando mais elegante

[]'s
Kaizzaer
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qui, 17 Jun 2004 12:15 pm
Localização: Rio de Janeiro - RJ

Aproveitando a discussão sobre cursores...

:? Estou com um problema atroz em um dos sistemas em que faço manutenção.
Tenho um cursor que está travando no momento da execução do FETCH.
Este cursor retorna dois campos e cerca de cinqüenta registros.

O mais perturbador é que quando executo o mesmo select que gera o cursor por fora da PL,
o mesmo retorna todas as linhas em menos de 2 segundos.
Já avaliei os índices e está tudo OK, só que ao debugar a PL utilizando o PL/SQL Developer,
a linha do FETCH gera mais de 1 bilhão e 800 milhões de "Logical Reads", ou seja, trava tudo.

Algum dos colegas do fórum tem alguma idéia do que pode estar acontecendo? Porque nem o DBA da empresa sabe o que é.

Obrigado a todos...
Marlon Pasquali
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 28
Registrado em: Seg, 20 Mar 2006 3:40 pm
Localização: Erechim - RS

Kaizzaer, seria interessante se você pudesse publicar sua rotina para podermos avaliar melhor e tentar ajuda-lo.
Kaizzaer
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qui, 17 Jun 2004 12:15 pm
Localização: Rio de Janeiro - RJ

Esta é minha procedure onde estou com o problema relatado acima, ele ocorre no cursor C0...

Selecionar tudo

CREATE OR REPLACE PROCEDURE CUSTEIO_PRODUCAO_F1(P_ANO_REF TOR501.ANO_REFERENCIA%TYPE,
					        P_VERSAO TOR501.NR_VERSAO%TYPE,
                            P_ANO_mês_BASE TOR000.ANO_mês_BASE%TYPE,
						    P_RESPOSTA IN OUT VARCHAR2,
							P_QTD_ANOS_ORC IN TOR000.QTD_ANOS_ORC%TYPE)
AS

--p_resposta		varchar2(200);

TYPE T_PERCENT_RATEIO	IS TABLE OF TOR053.VL_PERCENTUAL_RATEIO%TYPE	INDEX BY BINARY_INTEGER;
TYPE T_ANO_mês		IS TABLE OF CHAR(6)				INDEX BY BINARY_INTEGER;

V_DIMENSAO		CHAR(6);
V_DESTINO		TOR053.CD_PROCESSO_DESTINO%TYPE;
V_ANOMES		CHAR(6);
V_PERC_RATEIO		TOR053.VL_PERCENTUAL_RATEIO%TYPE;
V_MESES			NUMBER;
V_ULTIMO_mês		DATE;

V_ANO_mês_C2		CHAR(6);
V_CONTA			CHAR(6);
V_VL_ORCADO		NUMBER;

V_CD_MOEDA		NUMBER;

V_VL_RATEADO		NUMBER;

IX			NUMBER;
IZ			NUMBER;

I_PERCENT_RATEIO	T_PERCENT_RATEIO;
I_ANO_mês		T_ANO_mês;

-- SELECIONA CENTRO DE CUSTOS DE MANUTENCAO DISTRIBUIDA (MD) /ORIGEM E DESTINO/
CURSOR C0 IS
SELECT DISTINCT A.CD_DIMENSAO_CR, B.CD_PROCESSO_DESTINO
FROM TOR501 A, TOR053 B, TOR025 C
WHERE A.ANO_REFERENCIA = B.ANO_REFERENCIA AND
A.ANO_REFERENCIA = P_ANO_REF AND
A.NR_VERSAO = P_VERSAO AND
B.ANO_REFERENCIA = A.ANO_REFERENCIA AND
B.NR_VERSAO = A.NR_VERSAO AND
B.CD_DIMENSAO_ORIGEM = A.CD_DIMENSAO_CR AND
C.ANO_REFERENCIA = A.ANO_REFERENCIA AND
C.NR_VERSAO = A.NR_VERSAO AND
C.CD_DIMENSAO = A.CD_DIMENSAO_CR AND
C.TP_DIMENSAO = 'MD'
ORDER BY A.CD_DIMENSAO_CR;

-- OBTEM PERCENTUAIS E CR (DIMENSAO) A DISTRIBUIR
CURSOR C1 IS
SELECT TO_CHAR(P_ANO_mês_BASE,'YYYYMM'), VL_PERCENTUAL_RATEIO
FROM TOR053
WHERE ANO_REFERENCIA = P_ANO_REF AND
CD_DIMENSAO_ORIGEM = V_DIMENSAO AND
CD_PROCESSO_DESTINO = V_DESTINO
ORDER BY 1;

-- CALCULA TOTAL DE GASTOS CR MANUTENCAO DISTRIBUIDA
CURSOR C2 IS
SELECT TO_CHAR(ANO_mês_ORCADO,'YYYYMM'), CD_CONTA, CD_MOEDA, SUM(VL_CORTE)
FROM TOR501
WHERE ANO_REFERENCIA = P_ANO_REF AND
NR_VERSAO = P_VERSAO AND
CD_DIMENSAO_CR = V_DIMENSAO AND
ANO_mês_ORCADO > P_ANO_mês_BASE
GROUP BY ANO_mês_ORCADO, TOR501.CD_CONTA, CD_MOEDA
ORDER BY 1;

BEGIN
--select to_char(sysdate,'hh:mi:ss') into v_hora from dual;
--dbms_output.put_line(v_hora);

	P_RESPOSTA := ' ';

	SELECT COUNT(*)
	INTO IX
	FROM TOR501
	WHERE ANO_REFERENCIA = P_ANO_REF AND
	NR_VERSAO = P_VERSAO AND
	CT_UTILIZADO NOT IN('0','9');

	IF IX > 0 THEN
		P_RESPOSTA := 'ATENÇÃO!! CUSTEIO DA PRODUÇÃO JÁ CALCULADO';
		GOTO ERRO;
	END IF;
  
  SELECT COUNT(DISTINCT T.CD_PRODUTO)
  INTO IX
  FROM TOR302 T
  WHERE T.ANO_REFERENCIA = P_ANO_REF
  AND   T.NR_VERSAO = P_VERSAO
  AND   T.ANO_mês_ORCADO > P_ANO_mês_BASE
  AND   T.QT_PRODUCAO > 0
  AND   NOT EXISTS (SELECT S.NR_SEQUENCIA
                    FROM TOR122 S
                    WHERE S.ANO_REFERENCIA = T.ANO_REFERENCIA
                    AND   S.NR_VERSAO      = T.NR_VERSAO
                    AND   S.CD_PRODUTO     = T.CD_PRODUTO);

	IF IX > 0 THEN
		P_RESPOSTA := 'ATENÇÃO!! EXISTEM PRODUTOS FORA DA SEQUENCIA DE CUSTEIO';
		GOTO ERRO;
	END IF;
  
	DELETE FROM TOR504 WHERE ANO_REFERENCIA= P_ANO_REF AND NR_VERSAO = P_VERSAO;
	COMMIT;

	-- CALCULA QUANTIDADE DE MESES
	SELECT TO_DATE(TO_CHAR(P_ANO_REF + P_QTD_ANOS_ORC,'0000')||'12','YYYYMM'),
	MONTHS_BETWEEN (TO_DATE(TO_CHAR(P_ANO_REF + P_QTD_ANOS_ORC,'0000')||'12','YYYYMM'), P_ANO_mês_BASE) + 1
	INTO V_ULTIMO_mês, V_MESES
	FROM DUAL;
	
	--DBMS_OUTPUT.PUT_LINE ('1 - QT_MESES '|| v_meses);	

	-- MONTA ARRAY DE MESES PARA PESQ. DE INDICES
	I_ANO_mês(1) := TO_CHAR(P_ANO_mês_BASE, 'YYYYMM');
	FOR IX IN 2..V_MESES LOOP
		I_ANO_mês(IX) := TO_CHAR(ADD_MONTHS(P_ANO_mês_BASE, IX-1),'YYYYMM');	
		--DBMS_OUTPUT.PUT_LINE ('1.1 - i_ano_mês '|| i_ano_mês(ix));		
	END LOOP;	

	--INICIA ARRAY I_PERCENT_RATEIO COM ZEROS
	FOR IX IN 1..V_MESES LOOP
		I_PERCENT_RATEIO(IX) := 0;
	END LOOP;

	OPEN C0;
	FETCH C0 INTO V_DIMENSAO, V_DESTINO;[/color][/b] [b][color=green]AQUI OCORRE O PROBLEMA[/color][/b]

	[b][color=red]WHILE C0%FOUND LOOP
		
		--DBMS_OUTPUT.PUT_LINE ('2 - ORIGEM '|| V_DIMENSAO || ' DESTINO ' || V_DESTINO);	

		-- MONTA I_PERCENT_RATEIO
		OPEN C1;
		FETCH C1 INTO V_ANOMES, V_PERC_RATEIO;
		IX := 1;
		WHILE C1%FOUND LOOP
		
			IF V_ANOMES = I_ANO_mês(1) THEN
				I_PERCENT_RATEIO(IX) := V_PERC_RATEIO;				
			ELSE
				
				IF IX = 1 THEN
				
					--DBMS_OUTPUT.PUT_LINE ('3 - erro '|| ix || ' ' || V_ANOMES || ' ' || I_ANO_mês(2) );	
					GOTO ERRO;

				ELSE

					FOR IZ IN 1..V_MESES LOOP	
					
						IF V_ANOMES = I_ANO_mês(IZ) THEN
							IX := IZ;
						END IF;
					
					END LOOP;

					I_PERCENT_RATEIO(IX) := V_PERC_RATEIO;
				
				END IF;
												
			END IF;

			--DBMS_OUTPUT.PUT_LINE ('4 - rateio '|| I_PERCENT_RATEIO(ix));	
		
			FETCH C1 INTO V_ANOMES, V_PERC_RATEIO;
		
			--DBMS_OUTPUT.PUT_LINE ('5 - rateio '|| v_PERC_RATEIO);	

			IX := IX + 1;
		END LOOP;
		CLOSE C1;
		
		-- PREENCHE ARRAY DE RATEIO OS MESES EM BRANCO		
		FOR IX IN 2..V_MESES LOOP

			--DBMS_OUTPUT.PUT_LINE ('5 - ZERO '|| ix);	

			IF I_PERCENT_RATEIO(IX) = 0 THEN
				I_PERCENT_RATEIO(IX) := I_PERCENT_RATEIO(IX - 1);
			END IF;
		
		END LOOP;

		--DBMS_OUTPUT.PUT_LINE ('5 - ZERO FIM');

		-- MONTA I_VALOR_ORCADO		
		OPEN C2;
		FETCH C2 INTO V_ANO_mês_C2, V_CONTA, V_CD_MOEDA, V_VL_ORCADO;
		
		WHILE C2%FOUND LOOP		

			FOR IX IN 1..V_MESES LOOP
			
				IF V_ANO_mês_C2 = I_ANO_mês(IX) THEN
					IZ := IX;
					--DBMS_OUTPUT.PUT_LINE ('6 - PESQ MESES '|| IZ || ' ' || V_ANO_mês_C2 || ' ' || I_ANO_mês(IX));	
				END IF;
				
				--DBMS_OUTPUT.PUT_LINE ('6 - PESQ MESES '|| IZ || ' ' || V_ANO_mês_C2 || ' ' || I_ANO_mês(IX));	
				
			END LOOP;

			-- INSERE NA TABELA TOR504
					
			V_VL_RATEADO := V_VL_ORCADO * I_PERCENT_RATEIO(IZ);

			--DBMS_OUTPUT.PUT_LINE ('7 - RATEIO '|| V_VL_RATEADO || ' ' || V_VL_ORCADO || ' ' || I_PERCENT_RATEIO(IZ));

			INSERT INTO TOR504 VALUES (P_ANO_REF, P_VERSAO, TO_DATE(V_ANO_mês_C2,'YYYYMM'), V_DESTINO, V_DIMENSAO, V_CD_MOEDA, 
						   V_CONTA, 'M', V_VL_RATEADO);	

			--DBMS_OUTPUT.PUT_LINE ('8 - INSERT NA TOR504 '|| ix);		
			FETCH C2 INTO V_ANO_mês_C2, V_CONTA, V_CD_MOEDA, V_VL_ORCADO;
		
		END LOOP;				
		
		CLOSE C2;
      COMMIT; 

		UPDATE TOR501
		SET CT_UTILIZADO = '1'
		WHERE ANO_REFERENCIA = P_ANO_REF AND
		NR_VERSAO = P_VERSAO AND
		CD_DIMENSAO_CR = V_DIMENSAO;

		-- INICIA ARRAY I_PERCENT_RATEIO COM ZEROS
		FOR IX IN 1..V_MESES LOOP
			I_PERCENT_RATEIO(IX) := 0;
		END LOOP;

		FETCH C0 INTO V_DIMENSAO, V_DESTINO;
	END LOOP;

	CLOSE C0;

	COMMIT;
	GOTO FIM;
<<ERRO>>
	ROLLBACK;
<<FIM>>
--CORRIGE_VALORES_TOR504(P_ANO_REF, P_VERSAO);
NULL;
EXCEPTION
WHEN OTHERS THEN
P_RESPOSTA := SQLERRM;
END CUSTEIO_PRODUCAO_F1;

Obrigado a todos...
Marlon Pasquali
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 28
Registrado em: Seg, 20 Mar 2006 3:40 pm
Localização: Erechim - RS

tente utilizar a estrutura For Loop em vez de Fetch. Sei que parece besteira, mas acho mais facil de rastrear os dados do cursor. Coloque apelido nas colunas do seu select e utilize o exemplo abaixo para ver o que a rotina está trazendo do cursor.

Selecionar tudo

FOR r_CO in CO LOOP
   V_DIMENSAO := r_CO.CD_DIMENSAO;
   V_DESTINO    := r_CO.CD_DESTINO;
   DBMS_OUTPUT.PUT_LINE ('2 - ORIGEM '|| V_DIMENSAO || ' DESTINO ' || V_DESTINO);    
END LOOP;
Kaizzaer
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qui, 17 Jun 2004 12:15 pm
Localização: Rio de Janeiro - RJ

Olá Marlon, Testei a dica que você passou, mas continuo com o problema, o travamento continua ocorrendo no momento que a procedure tenta ler o cursor. :cry:

Vou tentar criar o ambiente em uma outra instancia do Oracle e verificar se o problema continua.

De qualquer forma obrigado pela dica.

Abs...
Avatar do usuário
CharlieHorse
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 5
Registrado em: Qui, 01 Jun 2006 3:28 pm
Localização: PORTO ALEGRE - RS
Analista/Desenvolvedor Oracle há 12 anos.

Pessoal
Cursores explícitos (previamente declarados) sempre serão mais performáticos do que os implícitos (select into) por que uma vez previstos (declarados), o compilador já consegue prever e criar as áreas temporárias que conterão os dados que as queries irão retornar, dimensionar o esforço e reservar a memória necessária.

Nunca utilizem "SELECT into", prefiram utilizar cursores explícitos
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

CharlieHorse escreveu:Cursores explícitos (previamente declarados) sempre serão mais performáticos do que os implícitos
Eu achei essa semana algo num manual da ORACLE que explica esse fenômeno dos cursores EXPLICITOS serem mais rápidos que um select direto. (é claro, isso se o usuário quer retornar apenas 1 linha)
All SELECT statements should use an explicit cursor. Implicit
SELECT statements actually cause 2 fetches to execute: one to get
the data, and one to check for the TOO_MANY_ROWS
exception. You can avoid this by FETCHing just a single record
from an explicit cursor.
Ou seja, ele faz duas buscas! Uma pra buscar a informação e outra pra testar o TOO_MANY_ROWS - caso venha mais uma linha.

FONTE: http://download.oracle.com/docs/cd/A911 ... 15devg.pdf
nunes
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 2
Registrado em: Qui, 28 Out 2010 2:17 pm
Localização: Parobe - RS
Andre Nunes

Olá Pessoal,

Alguém chegou a testar na prática se há alguma diferença de desempenho entre os 2 casos (SELECT-INTO e CURSOR) ??

Fiz alguns testes nas versões 9i, 10g e 11g e em ambos os casos obtive melhor tempo de resposta com SELECT-INTO.

Resolvi fazer este teste depois que li em uma apresentação de boas práticas de empresa que presta consultoria na área.

Na dica pede que seja feito justamente o contrário do que vem sendo dito aqui: "Prefira cursor implícito".
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

O TOM KYTE também falou sobre usar cursor IMPLICITO sempre que puder na sua visita ao brasil no GUOB TECH DAY 2010. (isso pra cursores, pois ele ainda prefere que seja feito um SELECT INTO direto).

Ele falou bastante na facilidade de uso (não precisa ficar declarando, nem lembrando de fechar, nem testando se foi NOT FOUND, etc).

EM RESUMO: temos um manual falando que explícito é melhor porque ele não faz 2 fetch, e temos o TOM KYTE dizendo que é bom fazer SELECT INTO...

TOPICO AINDA SEM SOLUÇÃO :-(
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

Pois é eu também sempre fico me perguntando, já li em dois ou três manuais/livros que Cursor seria a melhor opção, mas já o mestre Tom já comentou algumas vezes o contrátio. Por questões de reusabilidade e de melhor controle de excessões eu constumo usar o Cursor. Até que se prove que ele tem performance inferior não vejo motivos para mudar...

Mas sempre ficara a duvida no ar
nunes
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 2
Registrado em: Qui, 28 Out 2010 2:17 pm
Localização: Parobe - RS
Andre Nunes

Pessoal,

Para aumentar um pouco a dúvida, criei um cenário de teste para simular, talvez tenha sido tendencioso. Mas acredito que é válido.

Abaixo o código, caso queiram testar.

Criei uma tabela:

Selecionar tudo

create table Empregado
( IDEmpregado    INTEGER      NOT NULL,
  Nome           VARCHAR2(50) NOT NULL,
  DataNascimento DATE         NOT NULL,
  CodigoTeste    INTEGER      NOT NULL,
  NomeMae        VARCHAR2(50),
  NomePai        VARCHAR2(50) );
Em seguida executei um bloco PL/SQL para carregá-la com valores randômicos e também algumas exclusões, para forçar o erro NO_DATA_FOUND com Select-Into.

Selecionar tudo

begin
  for i in 1..70000 loop
     Insert into Empregado 
         (IDEmpregado, Nome, DataNascimento, CodigoTeste, NomeMae, NomePai)
     Values
         (i, 
         dbms_random.string('X', TRUNC(DBMS_RANDOM.value(25,45)) ),
         add_months(sysdate,-200) + DBMS_RANDOM.value(-50,50),
         dbms_random.value(1,70000),
         dbms_random.string('X', TRUNC(DBMS_RANDOM.value(25,45)) ),
         dbms_random.string('X', TRUNC(DBMS_RANDOM.value(25,45)) )
         );
  end loop;
  Commit;

  -- Cria chave primária para a tabela!
  Execute immediate 'alter table Empregado add constraint PK_Empregado primary key (IDEmpregado)';

  -- FORÇAR A OCORRENCIA DE ERROS (NO_DATA_FOUND) --
  for i in 1..8000 loop
     Delete Empregado Where IDEmpregado = TRUNC( DBMS_RANDOM.VALUE(1,70000) );
  end loop; 
  Commit;
end;
E então criei 2 procedimentos, um que utilizará o SELECT-INTO e outro SELECT-CURSOR.

Utilizei um exemplo onde não existirá a ocorrência do TOO_MANY_ROWS, já que estarei utilizando a PK para identificar o registro, acredito que se a consulta pode retornar mais de 1 registro realmente não deve ser utilizado o SELECT-INTO, por uma questão de lógica.

Primeiro procedimento:

Selecionar tudo

-- PROCEDIMENTO QUE FARÁ O SELECT INTO PARA TODOS OS REGISTROS DA TABELA EMPREGADO 
create procedure Prc_Select_Into is
  vTimeStart number;
  vTimeEnd   number;
  v_nome empregado.nome%type;
begin
  vTimeStart := dbms_utility.get_time;
  
  for i in 1..70000 loop
     begin
        select nome
        into   v_nome
        from   Empregado
        Where  IDEmpregado = i;
     exception
        when no_data_found then null; 
     end;
  end loop;
  
  vTimeEnd := dbms_utility.get_time;
  dbms_output.put_line('Tempo processamento: '|| to_char(vTimeEnd-vTimeStart) );
end;
Segundo procedimento:

Selecionar tudo

-- PROCEDIMENTO QUE UTILIZARÁ O CURSOR PARA TODOS OS REGISTROS DA TABELA EMPREGADO
create procedure Prc_Select_Cursor is
  vTimeStart number;
  vTimeEnd   number;
  v_nome     Empregado.nome%type;
  cursor c_nome (pIDEmpregado in integer) is
     Select nome
     from   Empregado
     Where  IDEmpregado = pIDEmpregado;
begin
  vTimeStart := dbms_utility.get_time;
  
  for i in 1..70000 loop
     for w in c_nome(i) loop
       v_nome := w.nome;
     end loop;
  end loop;
  
  vTimeEnd := dbms_utility.get_time;
  dbms_output.put_line('Tempo processamento: '||to_char(vTimeEnd-vTimeStart));
end;

Após isso executei várias vezes ambos:

Selecionar tudo

Set serveroutput on size 10000
Exec Prc_Select_Into
Exec Prc_Select_Cursor
E obtive os seguintes tempos (considerei o cache para avaliar, ignorei a primeira execução):

Selecionar tudo

Procedimento com SELECT-INTO..: 170
Procedimento com SELECT-CURSOR: 235
Executei este teste em Oracle Database 11g (11.2.0.1.0).
Fiz o mesmo teste em um Oracle 10g XE e também a vantagem foi do SELECT-INTO.

Se alguém tiver algum consideração quanto ao método utilizado para avaliar.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 8 visitantes