Verificando se existe um elemento de coleção no Oracle
-
20-09-2019 - |
Pergunta
Eu crio um tipo simples:
create or replace TYPE SIMPLE_TYPE AS OBJECT (ID NUMBER(38), NAME VARCHAR2(20));
Teste simples:
DECLARE
TYPE ObjectList IS TABLE OF SIMPLE_TYPE;
tmp SIMPLE_TYPE := SIMPLE_TYPE(1, 'a');
o ObjectList := new ObjectList(SIMPLE_TYPE(2, 'a'), SIMPLE_TYPE(3, 'a'));
BEGIN
IF tmp.EXISTS(tmp) THEN
dbms_output.put_line('OK, exists.');
END IF;
END;
Tenho uma exceção: pls-00302: o componente 'existe' deve ser declarado
Mas este exemplo de trabalho:
DECLARE
TYPE NumList IS TABLE OF INTEGER;
n NumList := NumList(1,3,5,7);
BEGIN
n.DELETE(2);
IF n.EXISTS(1) THEN
dbms_output.put_line('OK, element #1 exists.');
END IF;
IF n.EXISTS(3) = FALSE THEN
dbms_output.put_line('OK, element #2 has been deleted.');
END IF;
IF n.EXISTS(99) = FALSE THEN
dbms_output.put_line('OK, element #99 does not exist at all.');
END IF;
END;
É possível implementar o método existe no tipo simples_type?
Solução
tmp SIMPLE_TYPEE := SIMPLE_TYPE(1, 'a');
…
IF tmp.EXISTS(tmp) THEN
Você declara tmp
Como SIMPLE_TYPE
, não ObjectList
.
SIMPLE_TYPE
é tipo escalar, não uma coleção.
Provavelmente você queria verificar o.EXISTS
Em vez disso (que é um ObjectList
)?
Atualizar:
EXISTS
Quando aplicado a uma coleção, toma um índice inteiro como um argumento e verifica se o elemento com esse índice existe (não seu valor).
Para verificar isso SIMPLE_TYPE(1, 'a')
Existe em sua mesa, você deve ser o seguinte:
Crio ObjectList
em um dicionário:
CREATE TYPE ObjectList IS TABLE OF SIMPLE_TYPE;
Emitir o SELECT
consulta:
DECLARE
tmp SIMPLE_TYPE := SIMPLE_TYPE(1, 'a');
o ObjectList := new ObjectList(SIMPLE_TYPE(2, 'a'), SIMPLE_TYPE(3, 'a'));
myid INT;
BEGIN
SELECT 1
INTO myid
FROM TABLE(o) q
WHERE SIMPLE_TYPE(q.id, q.name) = tmp
AND rownum = 1;
IF (myid = 1) THEN
dbms_output.put_line('OK, exists.');
END IF;
END;
Outras dicas
Enquanto o Estados da documentação, EXISTS(
) Testes para a existência de uma entrada numerada em uma coleção. Aquilo é, array.exists(3)
afirma que o terceiro elemento de array
é preenchido.
O que você está tentando fazer no seu primeiro exemplo é testar se a instância tmp
combina um elemento em ObjectList
. A partir de 10g, podemos fazer isso usando o MEMBER OF
sintaxe. Infelizmente, para fazer esse trabalho, temos que declarar um MAP
Método, que é bastante desajeitado e ficaria bastante irritante se o objeto tivesse muitos atributos.
SQL> create or replace type simple_type as object
2 ( id number
3 , name varchar2(30)
4 , map member function compare return varchar2);
5 /
Type created.
SQL>
SQL> create or replace type body simple_type as
2 map member function compare return varchar2
3 is
4 return_value integer;
5 begin
6 return to_char(id, '0000000')||name;
7 end compare;
8 end;
9 /
Type body created.
SQL>
Executando o exemplo ...
SQL> set serveroutput on size unlimited
SQL>
SQL> declare
2 type objectlist is table of simple_type;
3 tmp simple_type := simple_type(1, 'a');
4 o objectlist := new objectlist(simple_type(2, 'a'), simple_type(3, 'a'));
5 begin
6 if tmp MEMBER OF o then
7 dbms_output.put_line('ok, exists.');
8 else
9 dbms_output.put_line('search me');
10 end if;
11 end;
12 /
search me
PL/SQL procedure successfully completed.
SQL>