III - Oracle9i Apontadores – Tipo de Dado (REF) Identificador de Objeto • A todo objeto de uma “object table” é associado um OID (“Object IDentifier”) lógico e globalmente único, que identifica internamente o objeto • Por default, o OID é gerado pelo sistema (”system-generated”), e ocupa 16 bytes • Não há interface para o acesso à estrutura interna de um OID • OID é uma coluna invisível de uma “object table”, com cada valor ocupando 16 bytes Identificador de Objeto (2) • Um OID pode também ser definido como sendo o valor do atributo chave primária do objeto chave do objeto • Isto é possível em um ambiente em que um identificador local pode ser também assumido como sendo globalmente único (“object table” não distribuída, ou não duplicada) • Uma vantagem indiscutível de chave primária sobre OID é a seguinte: a criação dos objetos é mais rápida, pois não há perda de tempo com a geração de OIDs Identificador de Objeto (3) • Tanto OID como chave primária oneram o acesso aos objetos: em um caso e outro os endereços são lógicos, necessitando portanto de ser mapeados para endereços físicos dos objetos – Os mapeamentos são feitos com a ajuda de índices, quer para OID quer para chave primária, os quais são automaticamente mantidos pelo sistema Identificador de Objeto (4) • Em termos de economia de espaço, qual seria a melhor escolha, “systemgenerated” ou chave primária? – Note que, se o OID for a chave de um objeto, a coluna OID da tabela é economizada, ou deixa de existir – Entretanto, não é sempre certo que haverá economia de espaço com chave primária (ver adiante) Tipo de Dado REF • REFs e coleções de REFs modelam associações entre objetos, usando OIDs como apontadores – Fácil mecanismo para navegação entre objetos – Colunas de tabelas híbridas podem ser do tipo REF • Valor de um tipo REF – OID do objeto referenciado (16 bytes), ou chave (tamanho definido pelo usuário) – OID da “object table” (16 bytes) – ROWID (10 bytes) • REF IS ROWID Tipo de Dado REF • Espaço – Caso cada chave (OID) requeira mais de 16 bytes, e havendo um grande número de valores tipo REF, então chave primária será pior que OID com relação a espaço em disco, pois neste caso as chaves vão ser duplicadas nos valores REF REF com Escopo • Pode ser necessário declarar que um valor REF deva conter somente referências a objetos de uma “object table” específica – REF com escopo (“scoped REF”) CREATE TABLE pessoas ( id NUMBER(4), nome VARCHAR2(60), ref_endereco REF endereço_objtyp SCOPE IS endereço_objtab, fones_ntab fone_ntabtyp) NESTED TABLE fones_ntab STORE AS fones_ntab2 REF com Escopo (2) • Se a “object table” do escopo for de um subtipo (herança), o escopo é estendido para compreender também as “object table”s dos subtipos do subtipo • REFS com escopo são armazenados de maneira mais eficiente do que REFs sem escopo – OID (gerado pelo sistema ou chave primária) – Opção WITH ROWID não é válida • Somente colunas REF com escopo podem ser indexadas • REFs com escopo facilitam a tarefa do Otimizador de Consultas Indexação de Colunas REF com Escopo CREATE TABLE endereco_objtab OF endereco_objtyp CREATE TABLE pessoas ( id NUMBER(4) PRIMARY KEY, nome VARCHAR2(60), ref_endereco REF endereço_objtyp SCOPE IS endereço_objtab, fones_ntab fone_ntabtyp) NESTED TABLE fones_ntab STORE AS fones_ntab2 Indexação de Colunas REF com Escopo (3) CREATE INDEX endereco_ref_ind ON pessoas (ref_endereco) SELECT id FROM pessoas p WHERE p.ref_endereco.estado = ‘PB’ REF IS ROWID • Restrições de uso – Não pode ser usada com REF com escopo – Nem com REF com regra de integridade referencial – Nem com REF baseado em chave primária REF ‘Sujo’ • É possível que um objeto identificado por um REF se torne indisponível remoção do objeto, mudança nos privilégios de acesso ao objeto – Tal REF torna-se então ‘sujo’ (“dangling”) – Para testar se um REF é sujo, usa-se o predicado IS DANGLING Funções com REF • -- Tratamento de OIDs SQL> CREATE TYPE t_emp AS OBJECT 2 (mat NUMBER, nome VARCHAR(20), salario NUMBER) 3 / Tipo criado. SQL> CREATE TABLE tab_emp OF t_emp 2 (PRIMARY KEY (mat)) 3 / Tabela criada. Funções com REF (2) SQL> INSERT INTO tab_emp VALUES (10, 'Joao', 5000) 2 / 1 linha criada. SQL> -- Funcao REF (retorna um valor do tipo REF) SQL> SELECT REF(e) FROM tab_emp e 2 / REF(E) 000028020922C58AF8D1054214AA0129C4B2F76373609AE5 0203BB46158870504B45770248004084A00000 Funções com REF (3) SQL> CREATE TABLE tab_depto 2 (cod NUMBER, 3 gerente REF t_emp SCOPE IS tab_emp) 4 / Tabela criada. SQL> INSERT INTO tab_depto 2 SELECT 10, REF(e) FROM tab_emp e 3 / 1 linha criada. SQL> -- Funcao DEREF SQL> SELECT DEREF(d.gerente) FROM tab_depto d 2 / DEREF(D.GERENTE)(MAT, NOME, SALARIO) T_EMP(10, 'Joao', 5000) Funções com REF (4) SQL> SELECT DEREF(d.gerente).nome FROM tab_depto d 2 / DEREF(D.GERENTE).NOM -------------------Joao SQL> SELECT d.gerente.nome FROM tab_depto d 2 / GERENTE.NOME -------------------Joao Funções com REF (5) SQL> -- Funcao VALUE SQL> SELECT value(e) FROM tab_emp e 2 / VALUE(E)(MAT, NOME, SALARIO) T_EMP(10, 'Joao', 5000) SQL> SELECT value(e).nome FROM tab_emp e 2 / VALUE(E).NOME Joao REF WITH ROWID create type teste as object (x number) / tipo criado. create type teste2 as object(y REF teste) / tipo criado. create table teste_tab of teste / tabela criada. create table teste2_tab of teste2 ( y WITH ROWID) / tabela criada.