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?
Cursor é melhor que SELECT INTO?
- MuLtAnI
- 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
- 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
- MuLtAnI
- 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
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
- dr_gori
- 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
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
Este é um exemplo do que eu estou falando: Guardar registro numa variável
[]´s
- MuLtAnI
- 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
o código além de mais rápido acaba ficando mais elegante
[]'s
-
- 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...
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...
-
- 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.
-
- 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...
Obrigado a todos...
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...
-
- 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.
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;
-
- 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.
Vou tentar criar o ambiente em uma outra instancia do Oracle e verificar se o problema continua.
De qualquer forma obrigado pela dica.
Abs...
Vou tentar criar o ambiente em uma outra instancia do Oracle e verificar se o problema continua.
De qualquer forma obrigado pela dica.
Abs...
- CharlieHorse
- 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
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
- dr_gori
- 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
Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered
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)CharlieHorse escreveu:Cursores explícitos (previamente declarados) sempre serão mais performáticos do que os implícitos
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.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.
FONTE: http://download.oracle.com/docs/cd/A911 ... 15devg.pdf
-
- 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".
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".
- dr_gori
- 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
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
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
-
- 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
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
Mas sempre ficara a duvida no ar
-
- 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:
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.
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:
Segundo procedimento:
Após isso executei várias vezes ambos:
E obtive os seguintes tempos (considerei o cache para avaliar, ignorei a primeira execução):
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.
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:
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) );
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;
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:
-- 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;
-- 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:
Set serveroutput on size 10000
Exec Prc_Select_Into
Exec Prc_Select_Cursor
Procedimento com SELECT-INTO..: 170
Procedimento com SELECT-CURSOR: 235
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.
-
- Informação
-
Quem está online
Usuários navegando neste fórum: Bing [Bot] e 7 visitantes