¿Cómo se valida de forma económica la existencia de una columna en una tabla en otro esquema con Oracle?
-
22-07-2019 - |
Pregunta
El entorno es Oracle 9 & amp; 10. No tengo acceso a nivel DBA.
El problema es verificar que existe una columna específica en una tabla específica, en otro esquema.
Hay dos casos para tratar.
- Otro esquema en la misma instancia
- Un esquema en una instancia diferente, usando un db_link
Dado mi esquema FRED y otro esquema BARNEY, intenté algo como esto
SELECT 1
FROM BARNEY.USER_TAB_COLS
WHERE TABLE_NAME = 'SOME_TABLE'
AND COLUMN_NAME = 'SOME_SPECIFIC_COLUMN'
Que produjo [1]: (Error): ORA-00942: la tabla o vista no existe
Después de vegging por un tiempo, me di cuenta de que USER_TAB_COLS, no es realmente una tabla. Es una vista. He estado seleccionando desde tablas todo el tiempo, pero no desde una vista.
Intenté lo mismo con mi db_link, y me sorprendió ver que los datos regresaban. Un db_link tiene un nombre / contraseña de esquema incorporado, por lo que me parece razonable que funcionó, ya que efectivamente se conecta al otro esquema, lo que debería hacer que las vistas sean accesibles.
Habiendo buscado en Google y agotado mis ojos en la montaña de Oracle doc, Estoy buscando a alguien que me señale en la dirección correcta, o al menos señale lo que me falta.
¿Qué técnicas están disponibles para obtener metadatos relacionados con la tabla de usuario de un esquema en la misma instancia para validar que existe una columna específica?
Gracias de antemano.
Mal.
+1 para buenas respuestas. Gracias.
Solución
Al igual que con las otras respuestas, normalmente uso ALL_TAB_COLUMNS para una consulta como esta. Pero eso solo mostrará columnas en las tablas donde tiene SELECT. Y se selecciona en esa columna: en el improbable caso de que hayan implementado privilegios a nivel de columna para esa tabla, es posible que pueda ver la tabla, pero no ver la columna específica de interés. Para la mayoría de nosotros, eso es extremadamente raro.
DBA_TAB_COLUMNS mostrará todas las columnas, pero tendrá que seleccionar en su esquema otorgado por su DBA. (En realidad, necesitará una subvención en ALL_TAB_COLUMNS para usarlo, pero eso es común en la mayoría de las tiendas). El paquete incorporado DBMS_METADATA PL / SQL también se puede utilizar, con limitaciones similares, pero creo que lo encontrará más complicado.
Por supuesto, también puede intentar seleccionar un registro de barney.some_table.some_column@my_dblink (o cualquier parte de eso que le interese). Y luego maneja la excepción. Feo, no lo recomendaría en la mayoría de las situaciones.
Otros consejos
Puede usar la siguiente consulta:
SELECT 1
FROM ALL_TAB_COLS
WHERE TABLE_NAME = 'SOME_TABLE'
AND COLUMN_NAME = 'SOME_SPECIFIC_COLUMN'
AND OWNER = 'BARNEY';
(User_Tables y User_Tab_Cols son solo vistas en all_tables y all_tab_coumns con un where owner = <Current User>
adjunto)
Si se le permite ver la tabla_algo de Barney (es decir, se le OTORGÓ al menos privilegios SELECT), entonces sabrá si la columna está allí. Si no tiene derechos sobre la tabla, no podrá obtener metainformación sobre ella.
Usaría all_tab_columns para eso.
Pero tenga cuidado de que solo verá lo que puede ver.
Misma instancia, esquema diferente:
Select Count(*)
From all_tab_cols
Where owner = 'BARNEY' and
table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';
El recuento (*) tiene la ventaja de devolver siempre una sola fila con un valor de 1 o 0, por lo que no tiene que lidiar con NO_DATA_FOUND
errores en PL / SQL.
A través de un enlace de base de datos, el mismo esquema que el que conecta:
Select Count(*)
From user_tab_cols@MY_DB_LINK
Where table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';
A través de un enlace de base de datos, esquema diferente al que se conecta como:
Select Count(*)
From all_tab_cols@MY_DB_LINK
Where owner = 'BARNEY' and
table_name = 'SOME_TABLE' and
column_name = 'SOME_SPECIFIC_COLUMN';