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
  

Mensagemem Ter, 30 Nov 2004 9:51 am

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?
tfg
Localização: Novo Hamburgo - RS

Mensagemem Qua, 01 Dez 2004 8:56 am

Acredito que seja pelo motivo de quando não existir registro na tabela que você esta fazendo select dar erro de NO DATA FOUND.
guerton
Localização: Sapiranga - Rs

Mensagemem Qua, 19 Jan 2005 10:47 am

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
MuLtAnI
Localização: Videira - SC


Mensagemem Qua, 19 Jan 2005 1:33 pm

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
MuLtAnI
Localização: Videira - SC


Mensagemem Qua, 19 Jan 2005 1:42 pm

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
dr_gori
Localização: Portland, OR USA

Thomas F. G

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

Mensagemem Qua, 19 Jan 2005 1:50 pm

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
MuLtAnI
Localização: Videira - SC


Mensagemem Qua, 12 Abr 2006 12:26 pm

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...
Kaizzaer
Localização: Rio de Janeiro - RJ

Mensagemem Qua, 12 Abr 2006 4:58 pm

Kaizzaer, seria interessante se você pudesse publicar sua rotina para podermos avaliar melhor e tentar ajuda-lo.
Marlon Pasquali
Localização: Erechim - RS

Mensagemem Qua, 12 Abr 2006 5:16 pm

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

Código: Selecionar todos
CREATE OR REPLACE PROCEDURE CUSTEIO_PRODUCAO_F1(P_ANO_REF TOR501.ANO_REFERENCIA%TYPE,
                       P_VERSAO TOR501.NR_VERSAO%TYPE,
                            P_ANO_MES_BASE TOR000.ANO_MES_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_MES      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_MES      DATE;

V_ANO_MES_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_MES      T_ANO_MES;

-- 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_MES_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_MES_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_MES_ORCADO > P_ANO_MES_BASE
GROUP BY ANO_MES_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_MES_ORCADO > P_ANO_MES_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_MES_BASE) + 1
   INTO V_ULTIMO_MES, V_MESES
   FROM DUAL;
   
   --DBMS_OUTPUT.PUT_LINE ('1 - QT_MESES '|| v_meses);   

   -- MONTA ARRAY DE MESES PARA PESQ. DE INDICES
   I_ANO_MES(1) := TO_CHAR(P_ANO_MES_BASE, 'YYYYMM');
   FOR IX IN 2..V_MESES LOOP
      I_ANO_MES(IX) := TO_CHAR(ADD_MONTHS(P_ANO_MES_BASE, IX-1),'YYYYMM');   
      --DBMS_OUTPUT.PUT_LINE ('1.1 - i_ano_mes '|| i_ano_mes(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_MES(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_MES(2) );   
               GOTO ERRO;

            ELSE

               FOR IZ IN 1..V_MESES LOOP   
               
                  IF V_ANOMES = I_ANO_MES(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_MES_C2, V_CONTA, V_CD_MOEDA, V_VL_ORCADO;
      
      WHILE C2%FOUND LOOP      

         FOR IX IN 1..V_MESES LOOP
         
            IF V_ANO_MES_C2 = I_ANO_MES(IX) THEN
               IZ := IX;
               --DBMS_OUTPUT.PUT_LINE ('6 - PESQ MESES '|| IZ || ' ' || V_ANO_MES_C2 || ' ' || I_ANO_MES(IX));   
            END IF;
            
            --DBMS_OUTPUT.PUT_LINE ('6 - PESQ MESES '|| IZ || ' ' || V_ANO_MES_C2 || ' ' || I_ANO_MES(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_MES_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_MES_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...
Kaizzaer
Localização: Rio de Janeiro - RJ

Mensagemem Qua, 12 Abr 2006 5:42 pm

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.

Código: Selecionar todos
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;
Marlon Pasquali
Localização: Erechim - RS

Mensagemem Qui, 13 Abr 2006 10:57 am

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...
Kaizzaer
Localização: Rio de Janeiro - RJ

Mensagemem Qui, 01 Jun 2006 3:33 pm

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
CharlieHorse
Localização: PORTO ALEGRE - RS

Analista/Desenvolvedor Oracle há 12 anos.

Mensagemem Qui, 10 Jul 2008 5:32 pm

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
dr_gori
Localização: Portland, OR USA

Thomas F. G

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

Mensagemem Qui, 28 Out 2010 2:28 pm

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".
nunes
Localização: Parobe - RS

Andre Nunes

Mensagemem Qui, 28 Out 2010 4:06 pm

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 :-(
dr_gori
Localização: Portland, OR USA

Thomas F. G

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

Mensagemem Qui, 28 Out 2010 4:15 pm

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
gfkauer
Localização: Sapiranga - RS

Quem falou que programar era fácil??

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

Acessem: www.gfkauer.com.br

Mensagemem Sex, 29 Out 2010 1:18 pm

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:
Código: Selecionar todos
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.
Código: Selecionar todos
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:
Código: Selecionar todos
-- 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:
Código: Selecionar todos
-- 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:
Código: Selecionar todos
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):
Código: Selecionar todos
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.
nunes
Localização: Parobe - RS

Andre Nunes


  • Veja também
    Respostas
    ExibiÇões
    Última mensagem