63

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

关于这是出于安全原因的争论听起来像是由 TSA 精心设计的。如果我是攻击者,我会知道我刚刚试图利用哪个表,并且能够轻松地解释这个无用的消息。如果我是一名通过多层应用程序代码处理复杂连接的开发人员,通常很难分辨。

我的猜测是,最初实现此错误时,有人忽略了添加对象名称,现在,人们担心它会破坏兼容性来修复它。(如果代码发生变化,解析错误消息之类的傻事会很混乱。)

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


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

4

8 回答 8

14

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

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

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

于 2008-09-05T17:51:57.167 回答
12

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

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 语句中,您可以看到星号突出显示未知表的名称:

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(不知何故)。

于 2008-09-09T15:11:58.407 回答
6

我不同意这种观点,即 SQL+ 让您了解哪个表名是不可接受的。诚然,它有助于直接 DML,尽管解析它非常困难。但是当谈到动态时,我们没有任何帮助:

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
于 2011-01-31T12:32:54.493 回答
5

如果您使用的是 TOAD 或 TORA 等 SQL 浏览工具,它将通过突出显示或将光标移动到您出错的位置来帮助您解决 ORA 错误。

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

于 2008-09-05T17:55:49.810 回答
3

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

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> 

这并不理想,但缺少检查跟踪文件,我不知道该怎么做。

于 2008-09-06T00:58:34.520 回答
3

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

$ 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 的所有错误消息(包括未来的错误)编写一个自定义解析器以突出显示有问题的位置。

有时包含表名会产生误导。仅仅知道哪里出了问题就会有很大的帮助:

SQL> select * from where dummy = 'X';
select * from where dummy = 'X'
              *
ERROR at line 1:
ORA-00903: invalid table name

至于甲骨文为什么选择这样做,我有一些猜测:

  1. IBM 将这种风格的错误消息用于 System R,Larry Ellison、Bob Miner 和 Ed Oates 将其复制以构建 Oracle V2。(向后兼容性。)

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

  3. 正如我上面所指出的,为了简化连接到 Oracle 的工具的创建。(互操作性。)

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

于 2009-04-21T00:03:19.810 回答
3

原因一:多语言界面

您的数据库实例有一个特定于语言的消息配置文件。消息从那里被拉出并从纯数字版本转换为数字+文本版本。

使用硬编码字符串可能被认为比在运行时冒着由于格式不正确的“%s”字符串而发生神秘故障的风险更好。

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

原因 2:安全性

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

如果默认打印更多详细信息,应用程序将更加暴露......例如,如果花旗银行打印了更多解释性消息。

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

于 2009-04-21T03:54:47.493 回答
1

@马修

您的查询是一个开始,但是当您有多个架构时它可能不起作用。例如,如果我以我自己的身份登录到我们的实例,我就拥有对我们所有表的读取权限。但是,如果我不使用架构限定表名,我将得到一个 ORA-00942 用于没有同义词的表:

SQL> 从工具中选择 *;
从工具中选择 *
              *
第 1 行的错误:
ORA-00942: 表或视图不存在

该表仍然显示在 all_tables 中:

SQL> select owner, table_name from all_tables where table_name = 'TOOLS';

所有者 TABLE_NAME
------------------------------ -------------------- ----------
应用工具

@erikson 抱歉,这并没有多大帮助。我和马克在一起——我用过 TOAD。

于 2008-09-07T13:07:45.710 回答