valor una todas toda tablas tabla registro procedimiento para las datos dato columnas columna campo buscar bases almacenado sql oracle search plsql database-table

sql - una - Buscar todos los campos en todas las tablas para un valor específico(Oracle)



buscar una tabla en todas las bases de datos sql (15)

¿Es posible buscar en cada campo de cada tabla un valor particular en Oracle?

Hay cientos de tablas con miles de filas en algunas tablas, así que sé que esto puede llevar mucho tiempo para realizar consultas. Pero lo único que sé es que un valor para el campo que me gustaría consultar es el 1/22/2008P09RR8 . <

Intenté usar esta declaración a continuación para encontrar una columna adecuada en función de lo que creo que debería llamarse pero no arrojó resultados.

SELECT * from dba_objects WHERE object_name like ''%DTN%''

No hay absolutamente ninguna documentación en esta base de datos y no tengo idea de dónde se extrae este campo.

¿Alguna idea?


--se ejecuta completo - sin error

SET SERVEROUTPUT ON SIZE 100000 DECLARE v_match_count INTEGER; v_counter INTEGER; v_owner VARCHAR2 (255) := ''VASOA''; v_search_string VARCHAR2 (4000) := ''99999''; v_data_type VARCHAR2 (255) := ''CHAR''; v_sql CLOB := ''''; BEGIN FOR cur_tables IN ( SELECT owner, table_name FROM all_tables WHERE owner = v_owner AND table_name IN (SELECT table_name FROM all_tab_columns WHERE owner = all_tables.owner AND data_type LIKE ''%'' || UPPER (v_data_type) || ''%'') ORDER BY table_name) LOOP v_counter := 0; v_sql := ''''; FOR cur_columns IN (SELECT column_name, table_name FROM all_tab_columns WHERE owner = v_owner AND table_name = cur_tables.table_name AND data_type LIKE ''%'' || UPPER (v_data_type) || ''%'') LOOP IF v_counter > 0 THEN v_sql := v_sql || '' or ''; END IF; IF cur_columns.column_name is not null THEN v_sql := v_sql || ''upper('' || cur_columns.column_name || '') ='''''' || UPPER (v_search_string)||''''''''; v_counter := v_counter + 1; END IF; END LOOP; IF v_sql is null THEN v_sql := ''select count(*) from '' || v_owner || ''.'' || cur_tables.table_name; END IF; IF v_sql is not null THEN v_sql := ''select count(*) from '' || v_owner || ''.'' || cur_tables.table_name || '' where '' || v_sql; END IF; --v_sql := ''select count(*) from '' ||v_owner||''.''|| cur_tables.table_name ||'' where ''|| v_sql; --dbms_output.put_line(v_sql); --DBMS_OUTPUT.put_line (v_sql); EXECUTE IMMEDIATE v_sql INTO v_match_count; IF v_match_count > 0 THEN DBMS_OUTPUT.put_line (v_sql); dbms_output.put_line(''Match in '' || cur_tables.owner || '': '' || cur_tables.table_name || '' - '' || v_match_count || '' records''); END IF; END LOOP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.put_line ( ''Error when executing the following: '' || DBMS_LOB.SUBSTR (v_sql, 32600)); END; /


Aquí hay otra versión modificada que comparará una coincidencia de subcadena inferior. Esto funciona en Oracle 11g.

DECLARE match_count INTEGER; -- Type the owner of the tables you are looking at v_owner VARCHAR2(255) :=''OWNER_NAME''; -- Type the data type you are look at (in CAPITAL) -- VARCHAR2, NUMBER, etc. v_data_type VARCHAR2(255) :=''VARCHAR2''; -- Type the string you are looking at v_search_string VARCHAR2(4000) :=''%lower-search-sub-string%''; BEGIN FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP EXECUTE IMMEDIATE ''SELECT COUNT(*) FROM ''||t.table_name||'' WHERE lower(''||t.column_name||'') like :1'' INTO match_count USING v_search_string; IF match_count > 0 THEN dbms_output.put_line( t.table_name ||'' ''||t.column_name||'' ''||match_count ); END IF; END LOOP; END; /


Citar:

He intentado utilizar esta declaración a continuación para encontrar una columna adecuada en función de lo que creo que debería llamarse pero no arrojó ningún resultado. *

SELECT * from dba_objects WHERE object_name like ''%DTN%''

Una columna no es un objeto. Si quiere decir que espera que el nombre de columna sea como ''% DTN%'', la consulta que desea es:

SELECT owner, table_name, column_name FROM all_tab_columns WHERE column_name LIKE ''%DTN%'';

Pero si la cadena ''DTN'' es solo una suposición de tu parte, probablemente no ayude.

Por cierto, ¿qué tan seguro está de que ''1/22 ​​/ 2008P09RR8'' sea un valor seleccionado directamente de una sola columna? Si no sabe en absoluto de dónde viene, podría ser una concatenación de varias columnas, o el resultado de alguna función, o un valor sentado en un objeto de tabla anidada. Por lo tanto, podría estar en una búsqueda inútil intentando verificar cada columna por ese valor. ¿No puede comenzar con la aplicación del cliente que muestra este valor y tratar de averiguar qué consulta está utilizando para obtenerlo?

De todos modos, la respuesta de diciu da un método de generación de consultas SQL para verificar cada columna de cada tabla para el valor. También puede hacer cosas similares por completo en una sesión SQL utilizando un bloque PL / SQL y SQL dinámico. Aquí hay un código escrito apresuradamente para eso:

SET SERVEROUTPUT ON SIZE 100000 DECLARE match_count INTEGER; BEGIN FOR t IN (SELECT owner, table_name, column_name FROM all_tab_columns WHERE owner <> ''SYS'' and data_type LIKE ''%CHAR%'') LOOP EXECUTE IMMEDIATE ''SELECT COUNT(*) FROM '' || t.owner || ''.'' || t.table_name || '' WHERE ''||t.column_name||'' = :1'' INTO match_count USING ''1/22/2008P09RR8''; IF match_count > 0 THEN dbms_output.put_line( t.table_name ||'' ''||t.column_name||'' ''||match_count ); END IF; END LOOP; END; /

Hay algunas formas en que podrías hacerlo más eficiente también.

En este caso, dado el valor que está buscando, puede eliminar claramente cualquier columna que sea de tipo NÚMERO o FECHA, lo que reduciría el número de consultas. Tal vez incluso restringirlo a columnas donde el tipo es como ''% CHAR%''.

En lugar de una consulta por columna, puede crear una consulta por tabla como esta:

SELECT * FROM table1 WHERE column1 = ''value'' OR column2 = ''value'' OR column3 = ''value'' ... ;


Estaba teniendo problemas siguientes para la respuesta de @Lalit Kumars,

ORA-19202: Error occurred in XML processing ORA-00904: "SUCCESS": invalid identifier ORA-06512: at "SYS.DBMS_XMLGEN", line 288 ORA-06512: at line 1 19202. 00000 - "Error occurred in XML processing%s" *Cause: An error occurred when processing the XML function *Action: Check the given error message and fix the appropriate problem

La solución es:

WITH char_cols AS (SELECT /*+materialize */ table_name, column_name FROM cols WHERE data_type IN (''CHAR'', ''VARCHAR2'')) SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword", SUBSTR (table_name, 1, 14) "Table", SUBSTR (column_name, 1, 14) "Column" FROM char_cols, TABLE (xmlsequence (dbms_xmlgen.getxmltype (''select "'' || column_name || ''" from "'' || table_name || ''" where upper("'' || column_name || ''") like upper(''''%'' || :val || ''%'''')'' ).extract (''ROWSET/ROW/*'') ) ) t ORDER BY "Table" /


Haría algo como esto (genera todas las selecciones que necesita). Luego puede alimentarlos a sqlplus:

echo "select table_name from user_tables;" | sqlplus -S user/pwd | grep -v "^--" | grep -v "TABLE_NAME" | grep "^[A-Z]" | while read sw; do echo "desc $sw" | sqlplus -S user/pwd | grep -v "/-/-/-/-/-/-" | awk -F'' '' ''{print $1}'' | while read nw; do echo "select * from $sw where $nw=''val''"; done; done;

Cede:

select * from TBL1 where DESCRIPTION=''val'' select * from TBL1 where =''val'' select * from TBL2 where Name=''val'' select * from TBL2 where LNG_ID=''val''

Y lo que hace es - para cada user_tables de user_tables obtener cada campo (de desc) y crear un select * from table donde el campo es igual a ''val''.


Hay algunas herramientas gratuitas que hacen este tipo de búsqueda, por ejemplo, esta funciona bien y el código fuente está disponible: https://sites.google.com/site/freejansoft/dbsearch

Necesitará el controlador Oracle ODBC y un DSN para usar esta herramienta.


Modificar el código para buscar sin distinguir entre mayúsculas y minúsculas con una consulta LIKE en lugar de buscar coincidencias exactas ...

DECLARE match_count INTEGER; -- Type the owner of the tables you want to search. v_owner VARCHAR2(255) :=''USER''; -- Type the data type you''re looking for (in CAPS). Examples include: VARCHAR2, NUMBER, etc. v_data_type VARCHAR2(255) :=''VARCHAR2''; -- Type the string you are looking for. v_search_string VARCHAR2(4000) :=''Test''; BEGIN dbms_output.put_line( ''Starting the search...'' ); FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP EXECUTE IMMEDIATE ''SELECT COUNT(*) FROM ''||t.table_name||'' WHERE LOWER(''||t.column_name||'') LIKE :1'' INTO match_count USING LOWER(''%''||v_search_string||''%''); IF match_count > 0 THEN dbms_output.put_line( t.table_name ||'' ''||t.column_name||'' ''||match_count ); END IF; END LOOP; END;


Modifiqué el código anterior para que funcione más rápido si está buscando solo un propietario. Solo tiene que cambiar las 3 variables v_owner, v_data_type y v_search_string para que se ajusten a lo que está buscando.

SET SERVEROUTPUT ON SIZE 100000 DECLARE match_count INTEGER; -- Type the owner of the tables you are looking at v_owner VARCHAR2(255) :=''ENTER_USERNAME_HERE''; -- Type the data type you are look at (in CAPITAL) -- VARCHAR2, NUMBER, etc. v_data_type VARCHAR2(255) :=''VARCHAR2''; -- Type the string you are looking at v_search_string VARCHAR2(4000) :=''string to search here...''; BEGIN FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP EXECUTE IMMEDIATE ''SELECT COUNT(*) FROM ''||t.table_name||'' WHERE ''||t.column_name||'' = :1'' INTO match_count USING v_search_string; IF match_count > 0 THEN dbms_output.put_line( t.table_name ||'' ''||t.column_name||'' ''||match_count ); END IF; END LOOP; END; /


Modifiqué la secuencia de comandos de Flood para que se ejecutara una vez por cada tabla en lugar de por cada columna de cada tabla para una ejecución más rápida. Requiere Oracle 11g o superior.

set serveroutput on size 100000 declare v_match_count integer; v_counter integer; -- The owner of the tables to search through (case-sensitive) v_owner varchar2(255) := ''OWNER_NAME''; -- A string that is part of the data type(s) of the columns to search through (case-insensitive) v_data_type varchar2(255) := ''CHAR''; -- The string to be searched for (case-insensitive) v_search_string varchar2(4000) := ''FIND_ME''; -- Store the SQL to execute for each table in a CLOB to get around the 32767 byte max size for a VARCHAR2 in PL/SQL v_sql clob := ''''; begin for cur_tables in (select owner, table_name from all_tables where owner = v_owner and table_name in (select table_name from all_tab_columns where owner = all_tables.owner and data_type like ''%'' || upper(v_data_type) || ''%'') order by table_name) loop v_counter := 0; v_sql := ''''; for cur_columns in (select column_name from all_tab_columns where owner = v_owner and table_name = cur_tables.table_name and data_type like ''%'' || upper(v_data_type) || ''%'') loop if v_counter > 0 then v_sql := v_sql || '' or ''; end if; v_sql := v_sql || ''upper('' || cur_columns.column_name || '') like ''''%'' || upper(v_search_string) || ''%''''''; v_counter := v_counter + 1; end loop; v_sql := ''select count(*) from '' || cur_tables.table_name || '' where '' || v_sql; execute immediate v_sql into v_match_count; if v_match_count > 0 then dbms_output.put_line(''Match in '' || cur_tables.owner || '': '' || cur_tables.table_name || '' - '' || v_match_count || '' records''); end if; end loop; exception when others then dbms_output.put_line(''Error when executing the following: '' || dbms_lob.substr(v_sql, 32600)); end; /


No tengo una solución simple en la fuente de SQL. Sin embargo, hay bastantes herramientas como sapo y Desarrollador PL / SQL que tienen una GUI donde un usuario puede ingresar la cadena que se va a buscar y devolverá la tabla / procedimiento / objeto donde se encuentra.


Procedimiento para buscar en toda la base de datos:

CREATE or REPLACE PROCEDURE SEARCH_DB(SEARCH_STR IN VARCHAR2, TAB_COL_RECS OUT VARCHAR2) IS match_count integer; qry_str varchar2(1000); CURSOR TAB_COL_CURSOR IS SELECT TABLE_NAME,COLUMN_NAME,OWNER,DATA_TYPE FROM ALL_TAB_COLUMNS WHERE DATA_TYPE in (''NUMBER'',''VARCHAR2'') AND OWNER=''SCOTT''; BEGIN FOR TAB_COL_REC IN TAB_COL_CURSOR LOOP qry_str := ''SELECT COUNT(*) FROM ''||TAB_COL_REC.OWNER||''.''||TAB_COL_REC.TABLE_NAME|| '' WHERE ''||TAB_COL_REC.COLUMN_NAME; IF TAB_COL_REC.DATA_TYPE = ''NUMBER'' THEN qry_str := qry_str||''=''||SEARCH_STR; ELSE qry_str := qry_str||'' like ''||SEARCH_STR; END IF; --dbms_output.put_line( qry_str ); EXECUTE IMMEDIATE qry_str INTO match_count; IF match_count > 0 THEN dbms_output.put_line( qry_str ); --dbms_output.put_line( TAB_COL_REC.TABLE_NAME ||'' ''||TAB_COL_REC.COLUMN_NAME ||'' ''||match_count); TAB_COL_RECS := TAB_COL_RECS||''@@''||TAB_COL_REC.TABLE_NAME||''##''||TAB_COL_REC.COLUMN_NAME; END IF; END LOOP; END SEARCH_DB;

Ejecutar declaración

DECLARE SEARCH_STR VARCHAR2(200); TAB_COL_RECS VARCHAR2(200); BEGIN SEARCH_STR := 10; SEARCH_DB( SEARCH_STR => SEARCH_STR, TAB_COL_RECS => TAB_COL_RECS ); DBMS_OUTPUT.PUT_LINE(''TAB_COL_RECS = '' || TAB_COL_RECS); END;

Resultados de muestra

Connecting to the database test. SELECT COUNT(*) FROM SCOTT.EMP WHERE DEPTNO=10 SELECT COUNT(*) FROM SCOTT.DEPT WHERE DEPTNO=10 TAB_COL_RECS = @@EMP##DEPTNO@@DEPT##DEPTNO Process exited. Disconnecting from the database test.


Sé que este es un tema viejo. Pero veo un comentario a la pregunta que pregunta si podría hacerse en SQL en lugar de usar PL/SQL . Así que pensé en publicar una solución.

La demostración a continuación es Buscar un VALOR en todas las COLUMNAS de todas las TABLAS en un SCHEMA completo :

  • Buscar un tipo de CARÁCTER

Busquemos el valor KING en el esquema SCOTT .

SQL> variable val varchar2(10) SQL> exec :val := ''KING'' PL/SQL procedure successfully completed. SQL> SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword", 2 SUBSTR (table_name, 1, 14) "Table", 3 SUBSTR (column_name, 1, 14) "Column" 4 FROM cols, 5 TABLE (xmlsequence (dbms_xmlgen.getxmltype (''select '' 6 || column_name 7 || '' from '' 8 || table_name 9 || '' where upper('' 10 || column_name 11 || '') like upper(''''%'' 12 || :val 13 || ''%'''')'' ).extract (''ROWSET/ROW/*'') ) ) t 14 ORDER BY "Table" 15 / Searchword Table Column ----------- -------------- -------------- KING EMP ENAME SQL>

  • Buscar un tipo NUMERIC

Busquemos el valor 20 en el esquema SCOTT .

SQL> variable val NUMBER SQL> exec :val := 20 PL/SQL procedure successfully completed. SQL> SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword", 2 SUBSTR (table_name, 1, 14) "Table", 3 SUBSTR (column_name, 1, 14) "Column" 4 FROM cols, 5 TABLE (xmlsequence (dbms_xmlgen.getxmltype (''select '' 6 || column_name 7 || '' from '' 8 || table_name 9 || '' where upper('' 10 || column_name 11 || '') like upper(''''%'' 12 || :val 13 || ''%'''')'' ).extract (''ROWSET/ROW/*'') ) ) t 14 ORDER BY "Table" 15 / Searchword Table Column ----------- -------------- -------------- 20 DEPT DEPTNO 20 EMP DEPTNO 20 EMP HIREDATE 20 SALGRADE HISAL 20 SALGRADE LOSAL SQL>


Sí, puedes y tu DBA te odiará y te buscará para clavar los zapatos en el piso porque eso causará muchas E / S y reducirá el rendimiento de la base de datos a medida que se purga el caché.

select column_name from all_tab_columns c, user_all_tables u where c.table_name = u.table_name;

para comenzar.

Comenzaría con las consultas en curso, usando v$session y v$sqlarea . Esto cambia según la versión de Oracle. Esto reducirá el espacio y no golpeará todo.


Tomando prestado, mejorando y simplificando ligeramente de esta publicación del blog, la siguiente instrucción SQL simple parece hacer bastante bien el trabajo:

SELECT DISTINCT (:val) "Search Value", TABLE_NAME "Table", COLUMN_NAME "Column" FROM cols, TABLE (XMLSEQUENCE (DBMS_XMLGEN.GETXMLTYPE( ''SELECT "'' || COLUMN_NAME || ''" FROM "'' || TABLE_NAME || ''" WHERE UPPER("'' || COLUMN_NAME || ''") LIKE UPPER(''''%'' || :val || ''%'''')'' ).EXTRACT (''ROWSET/ROW/*''))) ORDER BY "Table";


si conocemos los nombres de tablas y columnas, pero queremos averiguar el número de veces que aparece la cadena para cada esquema:

Declare owner VARCHAR2(1000); tbl VARCHAR2(1000); cnt number; ct number; str_sql varchar2(1000); reason varchar2(1000); x varchar2(1000):=''%string_to_be_searched%''; cursor csr is select owner,table_name from all_tables where table_name =''table_name''; type rec1 is record ( ct VARCHAR2(1000)); type rec is record ( owner VARCHAR2(1000):='''', table_name VARCHAR2(1000):=''''); rec2 rec; rec3 rec1; begin for rec2 in csr loop --str_sql:= ''select count(*) from ''||rec.owner||''.''||rec.table_name||'' where CTV_REMARKS like ''||chr(39)||x||chr(39); --dbms_output.put_line(str_sql); --execute immediate str_sql execute immediate ''select count(*) from ''||rec2.owner||''.''||rec2.table_name||'' where column_name like ''||chr(39)||x||chr(39) into rec3; if rec3.ct <> 0 then dbms_output.put_line(rec2.owner||'',''||rec3.ct); else null; end if; end loop; end;