繁体   English   中英

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

[英]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跟踪名称errorstack level 12”

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

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

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

将SQL复制并粘贴到其中一个工具中以提供帮助。 您也可以找到可用的分析信息。

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

我从未遇到过解释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

至于Oracle选择以这种方式做事的原因,我有一些猜测:

  1. IBM在System R中使用了这种错误消息,Larry Ellison,Bob Miner和Ed Oates复制了这些消息来构建Oracle V2。 (向后兼容性。)

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

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

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

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

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:多语言界面

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

拥有硬编码字符串可能被认为比在运行时因为格式不正确的“%s”字符串而导致出现神秘故障的风险更大。

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

原因2:安全

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

如果默认打印更多细节,应用程序将更加暴露...例如,如果citibank打印了更多解释性消息。

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

@马修

您的查询是一个开始,但是当您有多个模式时它可能不起作用。 例如,如果我以自己的身份登录我们的实例,我可以读取所有表的访问权限。 但是,如果我没有使用模式限定表名,我将为没有同义词的表获得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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM