Como é que uma barata validar a existência de uma coluna em uma tabela em outro esquema com o Oracle?
-
22-07-2019 - |
Pergunta
O ambiente é o Oracle 9 e 10. Eu não tenho acesso ao nível DBA.
O problema é verificar se uma coluna específica existe em uma tabela específica, em outro esquema.
Existem dois casos para lidar com eles.
- Outro esquema na mesma instância
- Um esquema em uma instância diferente, usando uma db_link
Dado o meu esquema de Fred e outro esquema BARNEY, eu tentei algo assim
SELECT 1
FROM BARNEY.USER_TAB_COLS
WHERE TABLE_NAME = 'SOME_TABLE'
AND COLUMN_NAME = 'SOME_SPECIFIC_COLUMN'
o que rendeu
Depois de vegging sobre isso por algum tempo, percebi que USER_TAB_COLS, não é realmente uma mesa. É uma visão. Fui selecionando a partir de tabelas tempo todo, mas não a partir de um ponto de vista.
Eu tentei a mesma coisa com o meu db_link, e ficou surpreso ao ver os dados voltar. A db_link tem uma schema_name incorporado / senha nele, por isso parece-me razoável que ele trabalhou, como ele efetivamente faz logon para o outro esquema, o que deve tornar os pontos de vista acessível.
Depois de ter Googled ao redor, e desgastado meus globos oculares em na montanha da Oracle doc, Eu estou procurando alguém para me apontar na direção correta, ou pelo menos apontar o que estou em falta.
Que técnicas estão disponíveis para obter tabela de usuário metadados relacionados a partir de um esquema na mesma instância para validar que existe uma coluna específica?
Agradecemos antecipadamente.
Evil.
+1 para boas respostas. Obrigado.
Solução
Tal como acontece com as outras respostas, normalmente eu uso ALL_TAB_COLUMNS para uma consulta como esta. Mas isso só irá mostrar colunas em tabelas onde você tem SELECT. E é selecionar nessa coluna - no caso improvável de que eles implementaram privilégios de nível de coluna para a tabela, você pode ser capaz de ver a mesa, mas não vir a coluna específica de interesse. Para a maioria de nós, isso é extremamente raro.
DBA_TAB_COLUMNS irá mostrar todas as colunas, mas você vai precisar selecionar nele concedido ao seu esquema pelo seu DBA. (Na verdade, você vai precisar de uma subvenção em ALL_TAB_COLUMNS para usá-la, mas isso é comum na maioria das lojas). O DBMS_METADATA PL / SQL embutido pacote também pode ser usado, com limitações semelhantes, mas eu acho que você vai encontrá-lo mais complicado.
É claro, você também pode simplesmente tentar selecionar um registro de barney.some_table.some_column@my_dblink (ou o que quer que peças de que você está em interessado). E, em seguida, tratar a exceção. Feio, eu não recomendo na maioria das situações.
Outras dicas
Você pode usar a seguinte consulta:
SELECT 1
FROM ALL_TAB_COLS
WHERE TABLE_NAME = 'SOME_TABLE'
AND COLUMN_NAME = 'SOME_SPECIFIC_COLUMN'
AND OWNER = 'BARNEY';
(USER_TABLES e User_Tab_Cols são apenas pontos de vista sobre ALL_TABLES e all_tab_coumns com um where owner = <Current User>
ligado a ele)
Se você está autorizado a ver some_table do Barney (ou seja, você tem sido concedida pelo menos privilégios SELECT sobre ele), então você vai saber se a coluna está lá. Se você não tem direitos sobre a mesa, você não será capaz de obter informações meta sobre ele.
Você usaria all_tab_columns para isso.
Mas cuidado que você só vai ver o que você está autorizado a ver.
O mesmo exemplo, esquema diferente:
Select Count(*)
From all_tab_cols
Where owner = 'BARNEY' and
table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';
A contagem (*) tem a vantagem de sempre retornando uma única linha com um valor de 1 ou 0, para que você não tem que lidar com erros NO_DATA_FOUND
em PL / SQL.
Através de um DB link, mesmo esquema que o que você conectar como:
Select Count(*)
From user_tab_cols@MY_DB_LINK
Where table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';
Através de um DB link, esquema diferente do que aquele que você se conectar como:
Select Count(*)
From all_tab_cols@MY_DB_LINK
Where owner = 'BARNEY' and
table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';