Para melhor visualização, recomendo resolução de no mínimo 1280 x 800 e navegador Mozilla Firefox


terça-feira, 29 de abril de 2008

Obtendo informações dos relacionamentos existentes (Foreign Keys) entre tabelas no Oracle ...

Por Eduardo Legatti

Olá,

Dando prosseguimento ao que foi escrito no artigo de Fevereiro sobre os estados das constraints, neste artigo irei mostrar como obter as informações dos relacionamentos existentes entre as tabelas no schema do usuário. Sabemos que uma restrição de PRIMARY KEY é uma coluna ou um conjunto de colunas que identifica exclusivamente cada linha de uma tabela e que uma restrição de FOREIGN KEY, ou restrição de integridade referencial, designa uma coluna ou combinação de colunas com uma chave estrangeira e estabelece um relacionamento entre uma chave primária ou uma chave exclusiva na mesma tabela ou em uma tabela diferente. Como obter do dicionário de dados as informações referentes aos relacionamentos entre estas tabelas? A resposta está nas views de dicionário de dados *_CONSTRAINTS e *_CONS_COLUMNS, onde o * [asterisco] deverá ser substituído por USER_ (objetos de propriedade do usuário), ALL_ (objetos acessíveis ao usuário) ou DBA_ (objetos restritos para usuários com atribuição DBA).

Abaixo irei demonstrar um pequeno exemplo prático de como obter algumas dessas informações via consulta SQL:

C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Seg Abr 28 13:31:40 2008

Copyright (c) 1982, 2004, Oracle.  All rights reserved.

Conectado a:
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> create user scott identified by tiger
  2  default tablespace users quota unlimited on users;

Usuário criado.

SQL> grant connect,resource to scott;

Concessão bem-sucedida.

SQL> connect scott/tiger
Conectado.

SQL> create table tabela_A (id number constraint pk_a primary key);

Tabela criada.

SQL> create table tabela_B (id2 number constraint fk_b_a references tabela_a);

Tabela criada.

SQL> create table tabela_C (id3 number constraint fk_c_a references tabela_a);

Tabela criada.

-- Obtendo informações de quais tabelas fazem referência à tabela_A
SQL> select
  2     r.owner,
  3     r.table_name,
  4     r.constraint_name
  5  from
  6     user_constraints r,
  7     user_constraints o
  8  where
  9     r.r_owner = o.owner and
 10     r.r_constraint_name = o.constraint_name and
 11     o.constraint_type in ('P','U') and
 12     r.constraint_type = 'R' and
 13     o.table_name = 'TABELA_A';

OWNER                TABLE_NAME               CONSTRAINT_NAME
-------------------- ------------------------ --------------------------
SCOTT                TABELA_B                 FK_B_A
SCOTT                TABELA_C                 FK_C_A

-- Obtendo informações das tabelas, colunas e seus relacionamentos
SQL> select
  2     a.table_name||' ('||
  3     rtrim(max(decode(c.position,1,c.column_name))||','||
  4     max(decode(c.position,2,c.column_name))||','||
  5     max(decode(c.position,3,c.column_name))||','||
  6     max(decode(c.position,4,c.column_name)),',')||') referencia '||
  7     b.table_name||' ('||
  8     rtrim(max(decode(d.position,1,d.column_name))||','||
  9     max(decode(d.position,2,d.column_name))||','||
 10     max(decode(d.position,3,d.column_name))||','||
 11     max(decode(d.position,4,d.column_name)),',')||')' relacionamentos
 12  from
 13     user_constraints  a,
 14     user_constraints  b,
 15     user_cons_columns c,
 16     user_cons_columns d
 17  where
 18     a.r_constraint_name=b.constraint_name and
 19     a.constraint_name=c.constraint_name and
 20     b.constraint_name=d.constraint_name and
 21     a.constraint_type='R' and
 22     b.constraint_type in ('P', 'U')
 23  group by a.table_name, b.table_name
 24  order by 1;

RELACIONAMENTOS
------------------------------------------------------------
TABELA_B (ID2) referencia TABELA_A (ID)
TABELA_C (ID3) referencia TABELA_A (ID)
 
Em resumo, para obter informações de quaisquer tipos de restrições (constraints) existentes no schema, as views de dicionário de dados abaixo deverão ser consultadas:

SQL> desc user_constraints
Nome                          Nulo?    Tipo
----------------------------- -------- --------------------
OWNER                         NOT NULL VARCHAR2(30)
CONSTRAINT_NAME               NOT NULL VARCHAR2(30)
CONSTRAINT_TYPE                        VARCHAR2(1)
TABLE_NAME                    NOT NULL VARCHAR2(30)
SEARCH_CONDITION                       LONG
R_OWNER                                VARCHAR2(30)
R_CONSTRAINT_NAME                      VARCHAR2(30)
DELETE_RULE                            VARCHAR2(9)
STATUS                                 VARCHAR2(8)
DEFERRABLE                             VARCHAR2(14)
DEFERRED                               VARCHAR2(9)
VALIDATED                              VARCHAR2(13)
GENERATED                              VARCHAR2(14)
BAD                                    VARCHAR2(3)
RELY                                   VARCHAR2(4)
LAST_CHANGE                            DATE
INDEX_OWNER                            VARCHAR2(30)
INDEX_NAME                             VARCHAR2(30)
INVALID                                VARCHAR2(7)
VIEW_RELATED                           VARCHAR2(14) 


SQL> desc user_cons_columns
Nome                          Nulo?    Tipo
----------------------------- -------- --------------------
OWNER                         NOT NULL VARCHAR2(30)
CONSTRAINT_NAME               NOT NULL VARCHAR2(30)
TABLE_NAME                    NOT NULL VARCHAR2(30)
COLUMN_NAME                            VARCHAR2(4000)
POSITION                               NUMBER
 



4 comentários:

Unknown disse...

Ola Eduardo,

Permita me fazer uma observacao - utilizei seu script para detectar o que propoe porem em um cenario real ele traz mais linhas .. sugestao filtrar pelas tabelas para permitir o que seu exemplo propoe ..

abs!

Eduardo Legatti disse...

Olá André,

Dando um passeio aqui no blog? :-) Assim que possivel, irei reavaliar as instruções SQL do artigo.

Abraços e obrigado!

Legatti

Eduardo Legatti disse...

Olá André,

Foi verificado que o SQL está retornando os registros dos relacionamentos existentes entre as tabelas sem duplicação. Foi feito um teste em um schema com mais de 700 integridades referenciais.

Abraços,

Legatti

Anônimo disse...

Boa tarde,

Muito bom, funcionou perfeitamente e me quebrou um galho.

Postagens populares