为什么 Oracle 不告诉您哪个表或视图不存在?

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

提问人:erickson 提问时间:9/6/2008 最后编辑:Lalit Kumar Berickson 更新时间:12/18/2015 访问量:23952

问:

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

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

我的猜测是,当这个错误最初实现时,有人忽略了添加对象名称,现在,人们担心它会破坏兼容性来修复它。(如果代码发生更改,执行诸如解析错误消息之类的愚蠢操作的代码会感到困惑。

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


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

SQL 数据库 Oracle ORA-00942

评论

3赞 Graeme Perrow 4/7/2009
我想你必须问一个真正的Oracle工程师才能得到真正的答案。顺便说一句,我在 Sybase 工作,我们的服务器 (SQL Anywhere) 为您提供 “Table 'blah' not found”。
3赞 James P. 9/11/2011
这可能是由于保密反射;):链接
8赞 Lawrence 3/10/2014
好吧,我完全同意海报。我花了几个小时的时间试图找到开发问题,因为预言机忽略了说什么表不存在!安全性呢?您仍然可以选择不将详细的错误消息传递给客户端,而您通常永远不会这样做!我通常发现 Oracle 软件真的很糟糕,当涉及到比显而易见的更进一步思考时......

答:

14赞 Ethan Post 9/6/2008 #1

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

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

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

评论

0赞 10/6/2015
我尝试将此行添加到“init.ora”文件中,然后重新启动我的 dbms,但 user_dump_dest 文件夹中没有任何可用内容。有什么提示吗?
5赞 Mark Nold 9/6/2008 #2

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

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

评论

0赞 adolf garlic 7/22/2013
好吧,对我来说,它突出显示了我定义的常量,例如“:myvar”,所以根本没有帮助
3赞 Matthew Watson 9/6/2008 #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> 

这并不理想,但除了检查跟踪文件之外,我不确定还能如何做到这一点。

1赞 Hobo 9/7/2008 #4

@Matthew

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

SQL> select * from tools; 
select * from tools 
              * 
ERROR at line 1: 
ORA-00942: table or view does not exist 

不过,该表仍显示在all_tables中:

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

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

@erikson 对不起,这没有多大帮助。我和马克在一起 - 我用过TOAD。

12赞 Nick Pierpoint 9/9/2008 #5

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(以某种方式)。

评论

7赞 erickson 4/28/2011
当您可以交互式地使用 SQL*Plus 来测试查询时,这很好。然而,一个常见的情况是,当你只有来自使用持久层(如 Hibernate)的应用程序的日志时,很难准确关联可能执行的查询。
2赞 Jeffrey Kemp 3/21/2012
@erickson:这更像是 Hibernate ;) 的问题(开个玩笑)
2赞 ibre5041 3/4/2013
@erickson:恐怕是瘦JDBC驱动的限制。OCI 调用 OCIErrorGet 可以返回多个错误字符串。第一个是主要的,其他的都是细节(如堆栈跟踪)。您还可以询问“错误句柄”以获取OCI_ATTR_PARSE_ERROR_OFFSET等详细信息。我在JDBC驱动程序API中找不到任何相应的调用。无论如何,Oracle JDBC 驱动程序抛出纯通用 JDBC SqlExption - 没有特定于 Oracle 的内容。
1赞 Amit Naidu 4/2/2016
ORA-00959 表空间“string”不存在
3赞 Jon 'links in bio' Ericson 4/21/2009 #6

我在解释 Oracle 错误消息时从未遇到过问题。部分原因是,我所看到的用于开发 SQL for Oracle 的每个交互式工具都有助于指出查询出错的位置。正如其他人所指出的,这包括 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就能弄清楚哪个表不存在。您只需要使用适当的工具。(我想,调整你的期望。

评论

1赞 erickson 4/21/2009
感谢您的输入,乔恩。我没有说清楚,但就我而言,这些通常是在 Java 应用程序中通过几个不同的代码层遇到的......一个 Web 框架、一个持久性库、Java 数据库驱动程序。因此,有时甚至很难确定正在执行哪个查询,尤其是当您与另一个组合作以获取第三个组在测试期间创建的日志时!是的,这是一桶真正的猴子。
0赞 Jon 'links in bio' Ericson 4/21/2009
我想说,这更像是对Java的控诉,而不是对Oracle的控诉。;-)
1赞 erickson 4/21/2009
非常正确。但后来我再也没有试图起诉甲骨文......除非你把 JAVA 算作 ORCL。尽管有一些怪癖,但甲骨文在绝对意义上是伟大的,而且在“竞争对手”旁边看起来更好。
1赞 nsandersen 2/1/2016
你不需要成为DBA来弄清楚哪个表,不,但你确实需要花时间,似乎没有充分的理由。
1赞 Amit Naidu 4/2/2016
ORA-00904 string: invalid identifier
3赞 Mark Harrison 4/21/2009 #7

原因1:多语言界面

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

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

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

原因 2:安全性

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

如果默认情况下打印更多细节,应用程序会更加暴露......例如,如果花旗银行打印了更具解释性的消息。

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

6赞 user332325 1/31/2011 #8

我不同意这样一种观点,即 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