【问题标题】:how to fetch email address from oracle database如何从oracle数据库中获取电子邮件地址
【发布时间】:2021-02-14 01:56:24
【问题描述】:

大家好,我正在尝试从 oracle db 11g 获取某些电子邮件模式,我使用了以下查询

不幸的是,我必须扫描完整的模式才能获取值 (@pqr.de),它存在于它所在的列和表中,理想情况下,此活动是列出非活动电子邮件地址(非活动eamil地址我需要在其他系统中单独检查而不是通过查询)

查询

--desc dba_tab_cols
SET SERVEROUTPUT ON 100000
DECLARE 
    l_sql    CLOB; 
    l_where  CLOB; 
    l_result INT; 
BEGIN 
    FOR i IN (SELECT table_name, 
                     column_name, 
                     Row_number() 
                       over ( 
                         PARTITION BY table_name 
                         ORDER BY column_name )    AS seq, 
                     Count(*) 
                       over ( 
                         PARTITION BY table_name ) AS cnt 
              FROM   dba_tab_columns 
              WHERE  data_type IN ( 'CHAR', 'CLOB', 'NCHAR', 'NVARCHAR2', 
                                    'VARCHAR2' 
                                  )) LOOP 
        IF i.seq = 1 THEN 
          l_sql := 'select ' 
                   ||Chr(10); 

          l_where := 'where ' 
                     ||Chr(10); 
        END IF; 

        l_sql := l_sql 
                 || '  max(case when ' 
                 ||i.column_name 
                 ||' like ''%@pqr.de%'' then ' 
                 ||Power(2, i.seq - 1) 
                 ||' else 0 end)+' 
                 ||Chr(10); 

        l_where := l_where 
                   || '  ' 
                   ||i.column_name 
                   ||' is not null or' 
                   ||Chr(10); 

        IF i.seq = i.cnt THEN 
          l_sql := Rtrim(l_sql, '+' 
                                ||Chr(10)) 
                   ||Chr(10) 
                   ||'from ' 
                   ||i.table_name 
                   ||Chr(10) 
                   ||Substr(l_where, 1, Length(l_where) - 4); 

          dbms_output.Put_line('---------------------------------------'); 

          dbms_output.Put_line(l_sql); 

          EXECUTE IMMEDIATE l_sql INTO l_result; 

          IF l_result > 0 THEN 
            dbms_output.Put_line('Found!!! l_result=' 
                                 ||l_result); 
          END IF; 
        END IF; 
    END LOOP; 
END; 

/ 

我遇到了错误

错误报告 -

ORA-00936: missing expression
ORA-06512: at line 54
00936. 00000 -  "missing expression"
*Cause:    
*Action:

如何解决错误,因为我正在尝试从上述查询中检索表列表

测试查询 - 在第 60 行失败

SET SERVEROUTPUT ON 100000
DECLARE 
    l_sql    CLOB; 
    l_where  CLOB; 
    l_result INT; 
BEGIN 
    FOR i IN (SELECT owner,
                     table_name, 
                     column_name, 
                     Row_number() 
                       over ( 
                         PARTITION BY table_name 
                         ORDER BY column_name )    AS seq, 
                     Count(*) 
                       over ( 
                         PARTITION BY table_name ) AS cnt 
              FROM   all_tab_columns 
              --WHERE  owner not in ('LIST_OF_SCHEMAS') -- list relevant schemas
              AND    data_type IN ( 'CHAR', 'CLOB', 'NCHAR', 'NVARCHAR2', 
                                    'VARCHAR2' 
                                  )) LOOP 
        IF i.seq = 1 THEN 
          l_sql := 'select ' 
                   ||Chr(10); 

          l_where := 'where ' 
                     ||Chr(10); 
        END IF; 

        l_sql := l_sql 
                 || '  max(case when "' 
                 ||i.column_name 
                 ||'" like ''%@pqr.de%'' then ' 
                 ||Power(2, i.seq - 1) 
                 ||' else 0 end)+' 
                 ||Chr(10); 

        l_where := l_where 
                   || ' "' 
                   ||i.column_name 
                   ||'" is not null or' 
                   ||Chr(10); 

        IF i.seq = i.cnt THEN 
          l_sql := Rtrim(l_sql, '+' 
                                ||Chr(10)) 
                   ||Chr(10) 
                   ||'from "'
                   ||i.owner
                   ||'"."'
                   ||i.table_name
                   ||'"'
                   ||Chr(10) 
                   ||Substr(l_where, 1, Length(l_where) - 4); 

          dbms_output.Put_line('---------------------------------------'); 

          ---dbms_output.Put_line(l_sql); 
          dbms_output.Put_line(dbms_lob.substr(l_sql, 4000, 1)); 

          EXECUTE IMMEDIATE l_sql INTO l_result; 

          IF l_result > 0 THEN 
            dbms_output.Put_line('Found!!! l_result=' 
                                 ||l_result); 
          END IF; 
        END IF; 
    END LOOP; 
END; 

错误报告 -

Error report -
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 61
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    
*Action:

【问题讨论】:

  • 据我计算,根据您问题中的代码,第 54 行是:EXECUTE IMMEDIATE l_sql INTO l_result; 这意味着l_sql 包含无效的 SQL。在该行之前,您在该行中打印l_sql 的值:dbms_output.Put_line(l_sql);。请edit您的问题并发布l_sql的值,其中包含导致错误ORA-00936的SQL。
  • 您有带引号标识符的表吗?我怀疑其中一个构造查询看到了它不喜欢的列名。最后打印的l_sql 应该告诉你哪个?顺便说一句,您正在查看整个数据库,而不是特定的模式;您可能想在光标上添加一个owner 过滤器,并可能查看all_ 而不是dba_ 视图。
  • @AlexPoole 基本上我正在尝试扫描整个 dwh 以识别电子邮件行存在的表、列 (@pqr.de),您能否在查询中编辑它必须更正的地方?
  • 我明白了,但是您正在查看内部表(例如 SYS 和 SYSTEM 模式)以及您感兴趣的那些,以及视图和表;通过查询dba_ 视图,您可能会选择您无权查询的表。您可以通过修改游标查询来更有选择性。您得到的错误是另一回事;就像我说的,可能是一个带引号的标识符,来自使用保留字的表或列名。请编辑您的问题以包含它打印的最后一个 l_sql 值。
  • 我不明白这整件事的前提。 (直言不讳:它暗示要么试图做错事,要么严重无能,或者试图隐藏自己的错误,等等。)你为什么要在“驾驶执照号码”之类的列中搜索电子邮件地址?在所有表中的所有(字符串)列中搜索 whatever 绝不是合理的做法(除非您正在寻找病毒签名等)。

标签: sql oracle plsql


【解决方案1】:

您的方法基本上是可行的(尽管有更简单的方法,如果您真的必须这样做;例如,有一些替代方法 here),因此您从执行特定的 l_sql 值中得到的错误表明该特定结构存在问题。可能的罪魁祸首是作为保留字的表或列名,这会使解析器感到困惑。您可能还会遇到带引号的标识符的问题,并且您正在寻找跨所有模式(包括 SYS 等内部模式)的表,但没有指定每个表的所有者。

可以通过在光标和构造语句中添加双引号和所有者来避免这些问题:

...
-- add owner to cursor
    FOR i IN (SELECT owner,
                     table_name, 
                     column_name, 
                     Row_number() 
                       over ( 
                         PARTITION BY table_name 
                         ORDER BY column_name )    AS seq, 
                     Count(*) 
                       over ( 
                         PARTITION BY table_name ) AS cnt 
-- possibly query all_ instead of dba_
              FROM   all_tab_columns 
-- limit to schema you're interested in
              WHERE  owner in (USER) -- list relevant schemas
              AND    data_type IN ( 'CHAR', 'CLOB', 'NCHAR', 'NVARCHAR2', 
                                    'VARCHAR2' 
                                  )) LOOP 
...
        l_sql := l_sql 
-- add double-quotes around column name
                 || '  max(case when "' 
                 ||i.column_name 
                 ||'" like ''%@pqr.de%'' then ' 
                 ||Power(2, i.seq - 1) 
                 ||' else 0 end)+' 
                 ||Chr(10); 

        l_where := l_where 
-- add double-quotes around column name
                   || ' "' 
                   ||i.column_name 
                   ||'" is not null or' 
                   ||Chr(10); 

        IF i.seq = i.cnt THEN 
          l_sql := Rtrim(l_sql, '+' 
                                ||Chr(10)) 
                   ||Chr(10) 
-- add double-quotes around table name, and prefix with owner, also quoted (just in case!)
                   ||'from "'
                   ||i.owner
                   ||'"."'
                   ||i.table_name
                   ||'"'
                   ||Chr(10) 
                   ||Substr(l_where, 1, Length(l_where) - 4); 
...

db<>fiddle

我已经测试了以下错误

错误报告 -

ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 19270, maximum: 4000)
ORA-06512: at line 60

查询应该可以使用 CLOB 值,所以我怀疑第 60 行现在是输出行,而 l_sql 本身太大了;在这种情况下,您可以将其更改为:

          dbms_output.Put_line(dbms_lob.substr(l_sql, 4000, 1)); 

错误报告 -

ORA-06502:PL/SQL:数字或值错误:数字精度太大 ORA-06512:在第 61 行

这大概是i.seq达到128的时候; power(2, 127) 对于您的 int 结果变量来说太大了。如果我没看错,这意味着您有一个包含 128 个文本列的表格?不知道那是什么意思。

【讨论】:

  • 谢谢,我将测试查询,但问题很少 1) 使用 dba_tab_cols 与 all_tab_columns 有什么区别 2) -- 在列名周围添加双引号我有兴趣搜索值 @ pqr.de 所以该列可以是任何东西,可能是我误解了 3)我想我也可以排除一些像 SYS 这样的模式
  • @rakesh - 1) dba_ 视图显示整个数据库的值,包括您可能无法访问的内容`all_ 视图排除了您无法访问的内容。 2) 添加双引号不会影响您搜索的 which 表和列,它只会停止使用带引号的标识符(例如混合大小写或保留字)创建的任何导致问题的内容。通常他们得到相同的结果,例如select * from dualselect * from "DUAL"Read more.
  • 非常感谢您的解释,让我尝试只用几个模式进行测试
  • @rakesh - 最好将错误消息(没有原因/操作部分)放在评论中。但不确定您为什么会看到它; it's OK with CLOBs。您的代码中的第 60 行是什么?哦……是put_line吗?
  • 请停止编辑您的问题。你原来的问题已经解决了,对吧?我已经用可能是最新错误的原因更新了答案。如果您还有其他问题,请提出新问题。
猜你喜欢
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
相关资源
最近更新 更多