天天看點

ORACLE 檢索某列包含特定字元串的資料表工具存儲過程

使用示例:

1、初始化環境

delete APPS.FIND_RESULT;

set serveroutput on

2、執行查找特定檢索字元串

declare 

    v_ret varchar(200);

begin 

   apps.sp_findstring('IP2000', 1, v_ret);  --檢索數值則用如下 apps.sp_findstring('2000', 0, v_ret);

    DBMS_OUTPUT.PUT_LINE('OUT_RETURN = "' || v_ret || '"');

end;

3、查詢檢查結果

select * from apps.find_result order by TABLE_NAME, COLUMN_NAME; 

create table apps.find_result(table_name varchar2(255), column_name varchar2(255), data_value varchar2(255), rowversion date);
DELETE apps.find_result;
select * from apps.find_result order by table_name;

DECLARE
  IN_DATA VARCHAR2(200);
  IN_FLAG NUMBER;
  OUT_RETURN VARCHAR2(200);
BEGIN
  IN_DATA := 'ip2000';
  IN_FLAG := 0;

  SP_FINDSTRING(
    IN_DATA => IN_DATA,
    IN_FLAG => IN_FLAG,
    OUT_RETURN => OUT_RETURN
  );
  DBMS_OUTPUT.PUT_LINE('OUT_RETURN = ' || OUT_RETURN);
END;      

工具存儲過程:

create or replace PROCEDURE        APPS."SP_FINDSTRING" ( in_data IN VARCHAR2 --被檢索的字元串
  , in_flag IN  NUMBER DEFAULT 0 --0:數字;1:字元串
  , out_return OUT VARCHAR2 )
/**************************************************************
TEST SAMPLE:
======================================
delete APPS.FIND_RESULT;
set serveroutput on;
declare 
    v_ret varchar(200);
begin 
    apps.sp_findstring('第一階段', 1, v_ret);
    DBMS_OUTPUT.PUT_LINE('OUT_RETURN = "' || v_ret || '"');
end;
select * from apps.find_result;
**************************************************************/  
IS
  errorException exception; --聲明異常   
  errorCode number; --異常編碼   
  errorMsg varchar2(1000); --異常資訊   
  v_flag varchar2(10);

  v_owner_name varchar2(128);
  v_table_name varchar2(128);
  v_cloumn_name varchar2(128);
  v_count int;
  v_data VARCHAR2(500);
  v_sql varchar2(2000);
  v_data_type varchar2(100);
  v_rows_found int;
  --按照如下條件取出遊标,其中USERS是表空間,那個地方你可以改
  cur_data SYS_REFCURSOR;

begin--判斷是數字
  v_flag := 'true';
  v_rows_found := 0;

  if ( Lower(in_data) = Upper(in_data) AND in_flag = 0 ) then 
     v_sql :=' SELECT A.OWNER, A.TABLE_NAME, A.COLUMN_NAME, A.data_type from DBA_TAB_COLUMNS A, DBA_TABLES B WHERE A.TABLE_NAME = B.TABLE_NAME AND B.STATUS = ''VALID'''
       || ' AND A.OWNER = B.OWNER AND A.OWNER NOT IN (''SYS'', ''SYSTEM'', ''SYSMAN'', ''APPQOSSYS'', ''APEX_030200'', ''CTXSYS'', ''MDSYS'''
       || ' , ''OLAPSYS'', ''ORDSYS'', ''OWBSYS'', ''EXFSYS'', ''WMSYS'', ''DBSNMP'', ''OUTLN'', ''XDB'')'
       || ' AND A.data_type = ''NUMBER'' ORDER BY A.OWNER, A.TABLE_NAME, A.COLUMN_NAME';  
     open cur_data for v_sql;--打開遊标
     loop
        fetch cur_data into v_owner_name, v_table_name, v_cloumn_name, v_data_type;
        exit when cur_data%notfound;
        --取出遊标裡的各個變量,拼成動态sql語句
        if v_data_type = 'NUMBER' then
           v_sql := 'select count(*) from ' || v_owner_name || '.' || v_table_name || ' where ' || v_cloumn_name || ' = ' ||in_data;
        end if;
        execute immediate v_sql into v_count;
        --如果查詢出來的條數大于,則将查詢中的表名,字段名和輸入的内容插入到我建的那個表中
        if v_count > 0 then
           v_sql := 'insert into APPS.FIND_RESULT values (''' || v_owner_name || '.' || v_table_name ||
                       ''',''' || v_cloumn_name || ''',''' || in_data || ''',sysdate)';
           execute immediate v_sql;
           commit;
           v_rows_found := v_rows_found + 1;
        end if;
     end loop;
     close cur_data;
   else--不是數字
     v_data := Upper(in_data);
     v_sql :=' SELECT A.OWNER, A.TABLE_NAME, A.COLUMN_NAME, A.data_type from DBA_TAB_COLUMNS A, DBA_TABLES B WHERE A.TABLE_NAME = B.TABLE_NAME AND B.STATUS = ''VALID'''
       || ' AND A.OWNER = B.OWNER AND A.OWNER NOT IN (''SYS'', ''SYSTEM'', ''SYSMAN'', ''APPQOSSYS'', ''APEX_030200'', ''CTXSYS'', ''MDSYS'''
       || ' , ''OLAPSYS'', ''ORDSYS'', ''OWBSYS'', ''EXFSYS'', ''WMSYS'', ''DBSNMP'', ''OUTLN'', ''XDB'')'
       || ' AND (A.data_type = ''VARCHAR2'' OR A.data_type = ''NVARCHAR2'' OR A.data_type = ''NCLOB'') ORDER BY A.OWNER, A.TABLE_NAME, A.COLUMN_NAME';  
     --dbms_output.put_line(v_sql);
     open cur_data for v_sql;     
     loop
        fetch cur_data into v_owner_name, v_table_name, v_cloumn_name, v_data_type;
        exit when cur_data%notfound;
        --取出遊标裡的各個變量,拼成動态sql語句,
        v_sql := 'select count(*) from ' || v_owner_name || '."' || v_table_name || '" where Upper("' || v_cloumn_name || '") LIKE ''%' || v_data || '%''';
        --if v_table_name = 'MESSAGEMETADATA' and v_cloumn_name = 'DESCRIPTION' then 
        --   dbms_output.put_line(v_sql);
        --end if;
        execute immediate v_sql into v_count;
        --如果查詢出來的條數大于,則将查詢中的表名,字段名和輸入的内容插入到我建的那個表中
        if v_count > 0 then
           v_sql := 'insert into APPS.FIND_RESULT values (''' || v_owner_name || '.' || v_table_name || ''',''' || v_cloumn_name || ''',''' || in_data || ''',sysdate)';
           execute immediate v_sql;
           commit;
           dbms_output.put_line('found in: ' || v_owner_name || '."' || v_table_name || '"."' || v_cloumn_name || '"');
           v_rows_found := v_rows_found + 1;
        end if;
     end loop;
     close cur_data;
   end if;
   out_return := 'found ' || v_rows_found || ' (rows).' ;
   
   exception  --異常捕捉,不要把有需要的代碼放在異常捕捉後面,有異常才會執行異常代碼下所有代碼,沒有異常不會執行
     when errorException then
       errorCode := SQLCODE;
       errorMsg := SUBSTR(SQLERRM, 1, 200);
       v_flag := 'false';
       out_return := 'flag=' || v_flag || ', errorCode=' || errorCode || ', errorMsg=' || errorMsg;
     when others then
       errorCode := SQLCODE;
       errorMsg := SUBSTR(SQLERRM, 1, 200);
       v_flag := 'false';
       out_return := 'flag=' || v_flag || ', errorCode=' || errorCode || ', errorMsg=' || errorMsg;

   --dbms_output.put_line(out_return);
end sp_findstring;      

分割字元串函數(以管道形式輸出):

CREATE OR REPLACE TYPE SPLITSTRING_TYPE IS TABLE OF VARCHAR2 (4000);
/
CREATE OR REPLACE FUNCTION APPS.FN_SPLITSTRING(
-- 使用上面的函數前需要先建立一個類型
-- CREATE OR REPLACE TYPE SPLITSTRING_TYPE IS TABLE OF VARCHAR2 (4000);
-- Usage: SELECT * FROM TABLE(APPS.FN_SPLITSTRING('1,2,3,4,5'));
   p_value in varchar2, --待分割的字元串
   p_split varchar2 := ',' --分割标志
  )
  return SPLITSTRING_TYPE
  pipelined is
  v_idx       integer;
  v_str       varchar2(500);
  v_strs_last varchar2(4000) := p_value;

begin
  loop
    v_idx := instr(v_strs_last, p_split);
    exit when v_idx = 0;
    v_str := substr(v_strs_last, 1, v_idx - 1);
    v_strs_last := substr(v_strs_last, v_idx + 1);
    pipe row(v_str);
  end loop;
  pipe row(v_strs_last);
  return;
end FN_SPLITSTRING;