ค้นหาฟิลด์ทั้งหมดในตารางทั้งหมดเพื่อหาค่าเฉพาะ (Oracle)


117

เป็นไปได้ไหมที่จะค้นหาทุกฟิลด์ของทุกตารางเพื่อหาค่าเฉพาะใน Oracle

มีหลายร้อยตารางที่มีแถวหลายพันแถวในบางตารางดังนั้นฉันจึงรู้ว่าอาจใช้เวลาในการสืบค้นนานมาก 1/22/2008P09RR8แต่สิ่งเดียวที่ผมรู้คือค่าสำหรับสนามผมอยากจะใช้แบบสอบถามกับเป็น <

ฉันได้ลองใช้คำสั่งด้านล่างนี้เพื่อค้นหาคอลัมน์ที่เหมาะสมตามสิ่งที่ฉันคิดว่าควรตั้งชื่อ แต่กลับไม่มีผลลัพธ์

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

ไม่มีเอกสารใด ๆ ในฐานข้อมูลนี้และฉันไม่รู้ว่าฟิลด์นี้ถูกดึงมาจากที่ใด

ความคิดใด ๆ ?


เราสามารถทำได้โดยใช้แบบสอบถามเดียวแทนที่จะใช้กระบวนงานที่เก็บไว้หรือไม่?
Freakyuser


@LalitKumarB เพจที่คุณระบุไว้ไม่สามารถเข้าถึงได้อีกต่อไป เป็นไปได้ไหมที่จะโพสต์ข้อมูลเพื่อเป็นคำตอบ
Dodzi Dzakuma

@DodziDzakuma หน้านี้สามารถเข้าถึงได้lalitkumarb.wordpress.com/2015/01/06/…นอกจากนี้ฉันได้โพสต์คำตอบแล้วโปรดเลื่อนลงหรือดูstackoverflow.com/a/27794127/3989608
Lalit Kumar B

หากคุณมีปัญหาในการค้นหาคำค้นหา Lalit Kumar ลองใช้การสาธิตนี้: sqlfiddle.com/#!4/76924c/2/0
DxTx

คำตอบ:


94

อ้างถึง:

ฉันได้ลองใช้คำสั่งด้านล่างนี้เพื่อค้นหาคอลัมน์ที่เหมาะสมตามสิ่งที่ฉันคิดว่าควรตั้งชื่อ แต่กลับไม่มีผลลัพธ์ *

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

คอลัมน์ไม่ใช่วัตถุ หากคุณหมายความว่าคุณคาดว่าชื่อคอลัมน์จะเป็นเหมือน '% DTN%' คำค้นหาที่คุณต้องการคือ:

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

แต่ถ้าสตริง 'DTN' เป็นเพียงการคาดเดาในส่วนของคุณนั่นอาจไม่ช่วยอะไรได้

คุณแน่ใจได้อย่างไรว่า '1/22 ​​/ 2008P09RR8' เป็นค่าที่เลือกโดยตรงจากคอลัมน์เดียว ถ้าคุณไม่รู้เลยว่ามันมาจากไหนมันอาจเป็นการต่อกันของหลายคอลัมน์หรือผลลัพธ์ของฟังก์ชันบางอย่างหรือค่าที่อยู่ในวัตถุตารางที่ซ้อนกัน ดังนั้นคุณอาจกำลังไล่ล่าห่านป่าโดยพยายามตรวจสอบค่านั้นทุกคอลัมน์ คุณไม่สามารถเริ่มต้นด้วยแอปพลิเคชันไคลเอนต์ใด ๆ ที่แสดงค่านี้และพยายามหาคำค้นหาที่ใช้เพื่อรับมันได้หรือไม่?

อย่างไรก็ตามคำตอบของ diciu ให้วิธีการหนึ่งในการสร้างแบบสอบถาม SQL เพื่อตรวจสอบทุกคอลัมน์ของทุกตารางเพื่อหาค่า คุณยังสามารถทำสิ่งที่คล้ายกันทั้งหมดในเซสชัน SQL เดียวโดยใช้บล็อก PL / SQL และไดนามิก SQL นี่คือโค้ดที่เขียนขึ้นอย่างเร่งรีบสำหรับสิ่งนั้น:

    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;
    /

มีบางวิธีที่คุณสามารถทำให้มีประสิทธิภาพมากขึ้นได้เช่นกัน

ในกรณีนี้จากค่าที่คุณต้องการคุณสามารถกำจัดคอลัมน์ใด ๆ ที่เป็นประเภท NUMBER หรือ DATE ได้อย่างชัดเจนซึ่งจะช่วยลดจำนวนการสืบค้น อาจจะ จำกัด เฉพาะคอลัมน์ที่ประเภทเป็น '% CHAR%'

แทนที่จะสร้างหนึ่งแบบสอบถามต่อคอลัมน์คุณสามารถสร้างหนึ่งแบบสอบถามต่อตารางดังนี้:

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

คุณควร จำกัด ไว้ที่คอลัมน์ char, varchar และ varchar2 เนื่องจากคอลัมน์ number และ date ไม่สามารถมีสตริงนั้นได้
Erich Kitzmueller

8
@ammoQ - เหมือนที่ผมพูดในย่อหน้าที่สองถึงสุดท้ายหรือเปล่า?
Dave Costa

ฉันรันบน 9i และได้รับข้อผิดพลาดที่ไม่รู้จัก column_name ใครช่วยบอกหน่อยได้ไหมว่าจะต้องมีการปรับเปลี่ยนอะไรในการรันบน 9i
Regmi

@Regmi - ขออภัยนั่นเป็นข้อผิดพลาดในรหัสของฉันไม่ใช่ปัญหาเกี่ยวกับเวอร์ชัน ห่วงควรจะได้รับแรงหนุนจากการไม่ได้all_tab_columns all_tablesฉันได้รับการแก้ไขแล้ว
Dave Costa

@DaveCosta - ขอบคุณสำหรับการแก้ไข แต่ฉันยังคงได้รับข้อผิดพลาด "ตารางหรือมุมมองไม่มีอยู่" ในบรรทัดที่ 6 บรรทัดที่ 6 เป็น "ดำเนินการทันที"
Regmi

34

ฉันได้ทำการแก้ไขโค้ดด้านบนเพื่อให้ทำงานได้เร็วขึ้นหากคุณค้นหาด้วยเจ้าของเพียงคนเดียว คุณต้องเปลี่ยนตัวแปร 3 ตัว v_owner, v_data_type และ v_search_string เพื่อให้เหมาะกับสิ่งที่คุณกำลังค้นหา

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;
/

ฉันต้องแสดงความคิดเห็นในบรรทัดแรกเพื่อให้สามารถเรียกใช้แบบสอบถามนี้ได้ นอกจากนี้ฉันไม่สามารถลบตัวกรองเจ้าของและเรียกใช้การค้นหาได้
Popa Andrei

1
ฉันจำเป็นต้องใส่เครื่องหมายคำพูดคู่รอบชื่อตาราง / ชื่อคอลัมน์เพื่อหลีกเลี่ยงปัญหาเมื่อจำเป็นต้องอ้างอิง:'SELECT COUNT(*) FROM "'||t.table_name||'" WHERE "'||t.column_name||'" = :1'
Steve Chambers

ระวังว่า all_tab_cols ยังมีการดูแม้จะมีชื่อ
phil_w

คืออะไรกันแน่dbms_output? เนื่องจากการสืบค้นได้รับการดำเนินการสำเร็จใน DataGrip แต่ฉันไม่เห็นผลลัพธ์ใด ๆ หลังจากนั้น
ผิด

ฉันรู้ว่ามันเก่าไปหน่อย แต่เมื่อฉันเรียกใช้สิ่งนี้ฉันเพิ่งได้รับ Script Output ของ "anonymous block complete"
JasonWH

8

ฉันรู้ว่านี่เป็นหัวข้อเก่า แต่ฉันเห็นความคิดเห็นของคำถามที่ถามว่าสามารถทำได้SQLแทนที่จะใช้PL/SQLมากกว่าการใช้เลยคิดว่าจะโพสต์วิธีแก้ปัญหา

การสาธิตด้านล่างนี้คือการค้นหาค่าในคอลัมน์ทั้งหมดของตารางทั้งหมดใน SCHEMA ทั้งหมด :

  • ค้นหาประเภท CHARACTER

ลองหาค่าKINGใน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>
  • ค้นหาNUMERIC ประเภท

ลองหาค่า20ใน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>

6
hrmm .... การใช้ xml ดูเหมือน overkill นอกจากนี้:Error occurred in XML processing ORA-00932: inconsistent datatypes: expected NUMBER got BLOB
towi

2
ORA-19202: เกิดข้อผิดพลาดในการประมวลผล XML ORA-00932: ประเภทข้อมูลไม่สอดคล้องกัน: CHAR ที่คาดไว้มี BLOB ORA-06512: ที่ "SYS.DBMS_XMLGEN" บรรทัด 288 ORA-06512: ที่บรรทัด 1 19202 00000 - "เกิดข้อผิดพลาดในการประมวลผล XML % s "* สาเหตุ: เกิดข้อผิดพลาดขณะประมวลผลฟังก์ชัน XML * การดำเนินการ: ตรวจสอบข้อความแสดงข้อผิดพลาดที่ระบุและแก้ไขปัญหาที่เหมาะสม
Mohammad Faisal

ความคิดใด ๆ ? ORA-19202: เกิดข้อผิดพลาดในการประมวลผล XML ORA-22813: ค่าตัวถูกดำเนินการเกินขีด จำกัด ของระบบ ORA-06512: ที่ "SYS.DBMS_XMLGEN" บรรทัด 288 ORA-06512: ที่บรรทัด 1
Menios

7

นี่คือเวอร์ชันแก้ไขอื่นที่จะเปรียบเทียบการจับคู่สตริงย่อยที่ต่ำกว่า ใช้งานได้ใน 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;
/

7

ใช่คุณทำได้และ DBA ของคุณจะเกลียดคุณและจะพบว่าคุณตอกรองเท้าของคุณกับพื้นเพราะจะทำให้ I / O จำนวนมากและทำให้ประสิทธิภาพของฐานข้อมูลลดลงอย่างมากเมื่อล้างแคช

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

สำหรับการเริ่มต้น.

ฉันจะเริ่มต้นด้วยการสืบค้นข้อมูลโดยใช้v$sessionและv$sqlarea. การเปลี่ยนแปลงนี้ขึ้นอยู่กับเวอร์ชันของ oracle สิ่งนี้จะทำให้พื้นที่แคบลงและไม่กระทบทุกอย่าง


5

ฉันจะทำอะไรแบบนี้ (สร้างตัวเลือกทั้งหมดที่คุณต้องการ) คุณสามารถป้อนข้อมูลไปยัง 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;

มันให้ผล:

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

และสิ่งที่มันไม่เป็น - สำหรับแต่ละtable_nameจากuser_tablesได้รับในแต่ละฟิลด์ (จากรายละเอียด) และสร้าง * เลือกจากตารางที่สนามเท่ากับ 'Val'


5

ฉันแก้ไขสคริปต์ของ Flood ให้ดำเนินการครั้งเดียวสำหรับแต่ละตารางแทนที่จะเป็นทุกคอลัมน์ของแต่ละตารางเพื่อการดำเนินการที่เร็วขึ้น ต้องใช้ Oracle 11g หรือสูงกว่า

    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;
/

5

ฉันมีปัญหาต่อไปนี้สำหรับคำตอบของ @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

วิธีแก้ไขคือ:

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"
/ 

4

หากเราทราบชื่อตารางและคอลัมน์ แต่ต้องการทราบจำนวนครั้งที่สตริงปรากฏสำหรับแต่ละสคีมา:

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;

2

ขั้นตอนการค้นหาฐานข้อมูลทั้งหมด:

    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;    

ดำเนินการคำสั่ง

  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;

ตัวอย่างผลลัพธ์

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.

1

ฉันไม่มีวิธีง่ายๆใน SQL promprt Howeve มีเครื่องมือไม่กี่อย่างเช่นคางคกและ PL / SQL Developer ที่มี GUI ที่ผู้ใช้สามารถป้อนสตริงที่ต้องการค้นหาและจะส่งคืนตาราง / ขั้นตอน / วัตถุที่พบ


1

มีเครื่องมือฟรีบางอย่างที่ใช้ในการค้นหาประเภทนี้เช่นเครื่องมือนี้ใช้งานได้ดีและมีซอร์สโค้ด: https://sites.google.com/site/freejansoft/dbsearch

คุณจะต้องมีไดรเวอร์ Oracle ODBC และ DSN เพื่อใช้เครื่องมือนี้


1

การแก้ไขโค้ดเพื่อค้นหาแบบไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่โดยใช้แบบสอบถาม LIKE แทนการค้นหารายการที่ตรงกันทั้งหมด ...

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;

0

- รันเสร็จสมบูรณ์ - ไม่มีข้อผิดพลาด

    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

การยืมเพิ่มและลดความซับซ้อนเล็กน้อยจากบล็อกนี้โพสต์คำสั่ง SQL ง่ายๆต่อไปนี้ดูเหมือนจะทำงานได้ดี:

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";

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.