Search All Fields In All Tables For A Specific Value (Oracle)

前端 未结 16 2073
一整个雨季
一整个雨季 2020-11-22 01:05

Is it possible to search every field of every table for a particular value in Oracle?

There are hundreds of tables with thousands of rows in some tables so I know th

相关标签:
16条回答
  • 2020-11-22 01:37

    There are some free tools that make these kind of search, for example, this one works fine and source code is available: https://sites.google.com/site/freejansoft/dbsearch

    You'll need the Oracle ODBC driver and a DSN to use this tool.

    0 讨论(0)
  • 2020-11-22 01:37

    --it run completed -- no 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;
    /
    
    0 讨论(0)
  • 2020-11-22 01:39

    I did some modification to the above code to make it work faster if you are searching in only one owner. You just have to change the 3 variables v_owner, v_data_type and v_search_string to fit what you are searching for.

    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;
    /
    
    0 讨论(0)
  • 2020-11-22 01:39

    I would do something like this (generates all the selects you need). You can later on feed them to 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;
    

    It yields:

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

    And what it does is - for each table_name from user_tables get each field (from desc) and create a select * from table where field equals 'val'.

    0 讨论(0)
  • 2020-11-22 01:39

    if we know the table and colum names but want to find out the number of times string is appearing for each schema:

    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;
    
    0 讨论(0)
  • 2020-11-22 01:40

    I modified Flood's script to execute once for each table rather than for every column of each table for faster execution. It requires Oracle 11g or greater.

        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;
    /
    
    0 讨论(0)
提交回复
热议问题