关于sql:Oracle为什么不告诉您WHICH表或视图不存在?

关于sql:Oracle为什么不告诉您WHICH表或视图不存在?

Why doesn't Oracle tell you WHICH table or view does not exist?

如果您使用过Oracle,则可能会收到有用的消息" ORA-00942:表或视图不存在"。消息中不包含丢失对象的名称是有正当的技术原因吗?

关于此事的争论归因于安全性,就像它们是由TSA精心制作的。如果我是攻击者,我会知道我刚刚尝试利用哪个表,并且能够轻松地解释此无用的消息。如果我是一名开发人员,需要通过几层应用程序代码进行复杂的联接,那么通常很难说出来。

我的猜测是,当最初实现此错误时,有人忽略了添加对象名称,而现在,人们担心它会破坏兼容性来修复它。 (如果代码发生变化,则执行诸如解析错误消息之类的愚蠢行为的代码将被混淆。)

有没有一种开发人员友好的方法(而不是招募DBA)来确定丢失表的名称?

尽管我已经接受了与该主题相关的答案,但它并没有真正回答我的问题:为什么错误消息中的名称不是一部分?如果有人能提出真正的答案,我将很乐意更改我的投票。


您可以在参数文件(纯文本或spfile)中设置EVENT,以强制Oracle将详细的跟踪文件转储到user_dump_dest中,如果不是SQL,则对象名称可能在其中。

EVENT =" 942跟踪名称错误堆栈级别12"

如果您使用的是纯文本文件,则需要将所有EVENT设置保持在连续的行上。不确定如何将其应用于spfile。


SQL * Plus会告诉您该表不存在。例如:

1
2
3
4
5
6
7
8
9
10
11
SQL> SELECT
  2     *
  3  FROM
  4     user_tables a,
  5     non_existent_table b
  6  WHERE
  7     a.table_name = b.table_name;
   non_existent_table b
   *
ERROR at line 5:
ORA-00942: TABLE OR VIEW does NOT exist

此处显示丢失表的名称和SQL语句中发生错误的行号。

同样,在单行SQL语句中,您可以看到星号突出显示未知表的名称:

1
2
3
4
5
SQL> SELECT * FROM user_tables a, non_existent_table b WHERE a.table_name = b.table_name;
SELECT * FROM user_tables a, non_existent_table b WHERE a.table_name = b.table_name
                             *
ERROR at line 1:
ORA-00942: TABLE OR VIEW does NOT exist

就您的问题而言,我想错误消息不包含表名的原因是错误消息本身需要为静态文本。错误行的行号和位置清楚地传递回SQL * Plus(以某种方式)。


我不同意SQL +可以让您了解哪个表名是不可接受的观点。的确,尽管很难解析,但它有助于直接DML。但是在动态方面,我们没有任何帮助:

1
2
3
4
5
6
7
8
9
SQL> BEGIN
  2  EXECUTE immediate 'insert into blabla values(1)';
  3  END;
  4  /
BEGIN
*
ERROR at line 1:
ORA-00942: TABLE OR VIEW does NOT exist
ORA-06512: at line 2

如果您使用的是TOAD或TORA之类的SQL浏览工具,它将通过突出显示或指向将光标移至发生错误的位置来帮助您解决ORA错误。

将您的SQL复制并粘贴到以下工具之一中以提供帮助。您可能还会发现可用的分析信息也很有用。


原因1:多语言界面

数据库实例有一个特定于语言的消息配置文件。邮件从此处拉出,然后从纯数字版本转换为数字+文本版本。

可能认为使用硬编码的字符串比在运行时冒由于格式错误的"%s"字符串而导致神秘失败的风险更好。

(顺便说一句,并不是我特别同意这个观点。)

原因2:安全性

现在,如果您打印PHP等,将Oracle错误消息转储到浏览器,则您不会特别暴露应用程序的内部工作原理。

如果默认情况下打印更多详细信息,则应用程序的公开程度将有所提高。例如,如果citibank打印了更多说明性消息。

(请参见上面的免责声明,我也很乐意在错误中获取更多信息。)


我从来没有解释Oracle错误消息的问题。部分原因是我见过的用于为Oracle开发SQL的每个交互式工具都有助于指出查询出错的位置。如其他人所述,其中包括SQL * Plus和Perl DBI模块:

1
2
$ exec_sql.pl 'select * from daul'
DBD::Oracle::db PREPARE failed: ORA-00942: TABLE OR VIEW does NOT exist (DBD ERROR: error possibly near <*> indicator at CHAR 14 IN 'select * from <*>daul') [FOR Statement"select * from daul"] at exec_sql.pl line 68.

好吧,这很难读,因为它们全部都压在一行上了。但是,GUI工具将能够指向令牌,在该令牌处Oracle开始出现查询问题。在解析器上进行了一些工作之后,您可以编写一个工具来挑选有问题的表。

为了回答基本问题,Oracle错误似乎并非旨在按照您期望的方式工作。据我所知,Oracle中的所有错误消息都不支持变量文本。而是,Oracle返回两位信息:错误号和错误发生的位置。如果您拥有合适的工具,则很容易使用这些数据来诊断错误。可以说,Oracle的系统对工具创建者而言要比根据错误提供可变数量的诊断数据的系统更好。想象一下,必须为所有Oracle错误消息(包括将来的错误)编写一个自定义解析器,以突出显示有问题的位置。

有时包括表名可能会引起误解。知道哪里出了问题可以提供巨大的帮助:

1
2
3
4
5
SQL> SELECT * FROM WHERE dummy = 'X';
SELECT * FROM WHERE dummy = 'X'
              *
ERROR at line 1:
ORA-00903: invalid TABLE name

至于为什么Oracle选择这种方式,我有一些猜测:

  • IBM将这种错误消息用于System R,Larry Ellison,Bob Miner和Ed Oates复制了这些错误消息以构建Oracle V2。 (向后兼容。)

  • 错误号和位置是诊断信息的最小可能表示。 (简约)

  • 如上文所述,为简化连接到Oracle的工具的创建。 (互操作性。)

  • 无论如何,我认为您无需成为DBA即可确定哪个表不存在。您只需要使用适当的工具即可。 (我想调整您的期望。)


    如果不是很大的声明,那么最简单的方法就是检查数据字典,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SQL> SELECT * FROM xx,abc;
    SELECT * FROM xx,abc
                     *
    ERROR at line 1:
    ORA-00942: TABLE OR VIEW does NOT exist


    SQL> SELECT owner,TABLE_NAME FROM all_tables WHERE TABLE_NAME IN ('XX','ABC');

    OWNER                          TABLE_NAME
    ------------------------------ ------------------------------
    MWATSON                        XX

    SQL>

    这不是理想的方法,但是由于缺少检查跟踪文件的方法,因此我不确定该如何做。


    @马修

    您的查询只是一个开始,但是当您有多个架构时,它可能无法正常工作。例如,如果我以自己的身份登录到我们的实例,则对所有表都具有读取权限。但是,如果我不使用模式限定表名,那么对于没有同义词的表,我将得到ORA-00942:

    1
    2
    3
    4
    5
    SQL> SELECT * FROM tools;
    SELECT * FROM tools
                  *
    ERROR at line 1:
    ORA-00942: TABLE OR VIEW does NOT exist

    该表仍然显示在all_tables中:

    1
    2
    3
    4
    5
    SQL> SELECT owner, TABLE_NAME FROM all_tables WHERE TABLE_NAME = 'TOOLS';

    OWNER                          TABLE_NAME
    ------------------------------ ------------------------------
    APPLICATION                    TOOLS

    @erikson
    抱歉,没有太大帮助。我和Mark在一起-我曾经用过TOAD。


    推荐阅读