在整个数据库中搜索串联的字符串

时间:2019-02-16 00:29:04

标签: sql oracle

我正在尝试使用下面的脚本在整个Oracle数据库中找到一个串联的字符串

DECLARE
  match_count INTEGER;
-- Type the owner of the tables you are looking at
--  v_owner VARCHAR2(255) :='APEX_030200';

-- 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) :='48-S-9-00028';

  v_sql varchar2(1000);
BEGIN
  FOR t IN (
    SELECT table_name, column_name,owner 
    FROM sys.all_tab_cols 
    WHERE 
      data_type LIKE '%CHAR%' 
      AND owner NOT IN ('XDB','SYS','SYSMAN') 
      AND table_name <> 'Folder36_TAB'
  ) LOOP

    --v_sql := 'SELECT COUNT(*) FROM '|| t.owner || '.'||t.table_name||' WHERE '||t.column_name || ' like ''%'' || :1 || ''%''';
    v_sql := 'SELECT COUNT(*) FROM '|| t.owner || '.'||t.table_name||' WHERE '||t.column_name || ' =  :1 ';

    EXECUTE IMMEDIATE 
    v_sql
    INTO match_count
    USING v_search_string;

    IF match_count > 0 THEN
       dbms_output.put_line(v_sql);
      dbms_output.put_line(t.owner||'.'|| t.table_name ||' '||t.column_name||' '||match_count );
    END IF;

  END LOOP;

  EXCEPTION WHEN OTHERS THEN
   dbms_output.put_line(v_sql);
END;
/

字符串48-S-9-00028由4列组成 像48S900028 = 48-S-9-00028

我想在整个数据库中找到由4列组成该字符串的连接字符串,我从下面的脚本中进行了尝试,但它仅给出单个值的输出。

2 个答案:

答案 0 :(得分:0)

  

“客户端刚刚向我显示了我们没有源代码的报告,因此完全不知道要连接的4列”

首先,客户必须对该报告提供的数据有所了解。这可以为您提供一些线索,让您了解需要查看哪种表。

第二,如果它是一个业务键-如果不是,那么为什么要查找它-那么也许为这些列定义了一个主键或唯一键。因此,此查询可能会产生一些候选:

 select c.constraint_name, c.constraint_type 
 from user_cons_columns cc
      join user_constraints c
           on c.constraint_name = cc.constraint_name
 group by c.constraint_name, c.constraint_type having count(cc.column_name) = 4;

这两个建议都假定了合理的命名约定和对关系完整性的适当实施。在这种情况下,您可能没有那么幸运。

在这种情况下,启用SQL跟踪,运行报告,然后细读跟踪文件以查看提供数据的所有查询。您的桌子就是其中之一。 Find out more.

答案 1 :(得分:0)

如果要搜索的值来自4个串联的列,那么最好进行拖网搜索是搜索每个组件值,因为值'48-S-9-00028'实际上并不存在。

如果这些值是从具有派生值的视图中获取的,那么您将很不走运。但是,一切都不会丢失,请参阅我有关使用AWR或跟踪来查找正在运行的查询的评论。

因此,搜索此内容时,我会将拖网更改为以下内容(注意,这仅是功能性的,可能不会很快):

DECLARE
  match_count INTEGER;
  match_value VARCHAR2(20);
  v_data_type VARCHAR2(255) :='VARCHAR2';
  v_sql varchar2(1000);
BEGIN
  FOR t IN (
    SELECT table_name, column_name,owner 
    FROM sys.all_tab_cols 
    WHERE 
      data_type LIKE '%CHAR%' 
      AND owner NOT IN ('XDB','SYS','SYSMAN') 
      AND table_name <> 'Folder36_TAB'
  ) LOOP

      v_sql := 'SELECT ''' || t.column_name || ''' cn '
                 'FROM '|| t.owner || '.'||t.table_name||
                 ' WHERE '||t.column_name || ' IN ( ''48'', ''S'', ''9'', ''00028'' ) ' ||
                 ' AND rownum < 2';

      EXECUTE IMMEDIATE v_sql INTO match_value;

      dbms_output.put_line(v_sql);
      dbms_output.put_line(t.owner||'.'|| t.table_name ||' '||t.column_name||' '||match_value );
   END IF;
END;

也就是说,搜索存在4个组件值中的任何一个的任何表,仅返回匹配的值和找到的第一行,以帮助您缩小搜索范围。