简体   繁体   English

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

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

If you've used Oracle, you've probably gotten the helpful message "ORA-00942: Table or view does not exist". 如果你使用过Oracle,你可能会收到有用的消息“ORA-00942:表或视图不存在”。 Is there a legitimate technical reason the message doesn't include the name of the missing object? 是否有合法的技术原因消息不包含丢失对象的名称?

Arguments about this being due to security sound like they were crafted by the TSA. 关于这一点的争论是由于安全听起来像是由TSA制作的。 If I'm an attacker, I'd know what table I just attempted to exploit, and be able to interpret this unhelpful message easily. 如果我是攻击者,我会知道我刚试图利用哪个表,并且能够轻松地解释这个无用的消息。 If I'm a developer working with a complex join through several layers of application code, it's often very difficult to tell. 如果我是通过多层应用程序代码处理复杂连接的开发人员,那么通常很难说。

My guess is that when this error was originally implemented, someone neglected to add the object name, and now, people are afraid it will break compatibility to fix it. 我的猜测是,当最初实现此错误时,有人忽略了添加对象名称,现在,人们担心它会破坏兼容性来修复它。 (Code doing silly things like parsing the error message will be confused if it changes.) (代码执行愚蠢的事情,如解析错误消息,如果它发生变化将会混淆。)

Is there a developer-friendly (as opposed to recruiting your DBA) way to determine the name of the missing table? 是否有开发人员友好(而不是招募您的DBA)方式来确定缺失表的名称?


Although I've accepted an answer which is relevant to the topic, it doesn't really answer my question: Why isn't the name part of the error message? 虽然我已经接受了与该主题相关的答案,但它并没有真正回答我的问题: 为什么这个名称不是错误信息的一部分? If anyone can come up with the real answer, I'll be happy to change my vote. 如果有人能提出真正的答案,我会很乐意改变我的投票。

You can set an EVENT in your parameter file (plain text or spfile) to force Oracle to dump a detailed trace file in the user_dump_dest, the object name might be in there, if not the SQL should be. 您可以在参数文件(纯文本或spfile)中设置EVENT以强制Oracle在user_dump_dest中转储详细的跟踪文件,对象名称可能在那里,如果不是SQL应该在那里。

EVENT="942 trace name errorstack level 12" EVENT =“942跟踪名称errorstack level 12”

If you are using a plain text file you need to keep all your EVENT settings on consecutive lines. 如果您使用的是纯文本文件,则需要将所有EVENT设置保留在连续的行中。 Not sure how that applied to spfile. 不确定如何应用于spfile。

SQL*Plus does tell you the table that doesn't exist. SQL * Plus会告诉您不存在的表。 For example: 例如:

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

Here it shows that the name of the missing table and the line number in the SQL statement where the error occurs. 这里显示了缺失表的名称以及发生错误的SQL语句中的行号。

Similarly, in a one-line SQL statement you can see the asterisk highlighting the name of the unknown table: 同样,在单行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

In terms of your question, I guess the reason the error message doesn't include the name of the table is that the error message itself needs to be static text. 就你的问题而言,我猜错误消息不包括表名的原因是错误消息本身需要是静态文本。 The line number and location in the line of the error is clearly passed back to SQL*Plus (somehow). 错误行中的行号和位置显然会传回SQL * Plus(不知何故)。

If you are using a SQL browsing tool like TOAD or TORA it will help you with ORA errors by highlightling or pointing moving the cursor to where you made your error. 如果您使用的是TOAD或TORA等SQL浏览工具,它会通过突出显示或指向将光标移动到您出错的位置来帮助您解决ORA错误。

Copy and paste your SQL in to one of these tools to help. 将SQL复制并粘贴到其中一个工具中以提供帮助。 You may also find the analyse info available useful too. 您也可以找到可用的分析信息。

I would disagree with the opinion, that SQL+ lets you understand which table name is unacceptable. 我不同意这个观点,即SQL +可以让你了解哪个表名是不可接受的。 True, it helps in direct DML, although parsing it is very hard. 没错,它有助于直接DML,虽然解析它非常困难。 But when it comes to dynamic, we get no help: 但是当谈到动态时,我们没有得到任何帮助:

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

I've never had a problem with interpreting Oracle error messages. 我从未遇到过解释Oracle错误消息的问题。 Part of the reason is that every interactive tool I've seen for developing SQL for Oracle helpfully points to the location the query went wrong. 部分原因是我见过的用于开发SQL for Oracle的每个交互式工具都有助于指出查询出错的位置。 That includes SQL*Plus, as others have noted, and the Perl DBI module: 这包括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.

Well, that is a bit hard to read since it's all squished on one line. 嗯,这一个有点难以阅读,因为这一切都压扁在一行。 But a GUI tool would be able to point to the token where Oracle started having problems with the query. 但是GUI工具可以指向Oracle开始遇到查询问题的令牌。 And given a bit of work on a parser, you could write a tool to pick out the offending table. 并且在解析器上做了一些工作,你可以编写一个工具来挑选出有问题的表。

To answer the underlying question, Oracle errors don't seem to be designed to work the way you expect. 为了回答基本问题,Oracle错误似乎并不像您期望的那样工作。 As far as I can tell, none of the the error messages in Oracle support variable text. 据我所知,Oracle中的错误消息都不支持变量文本。 Instead, Oracle returns two bits of information: an error number and a location where the error occurs. 相反,Oracle返回两位信息:错误号和发生错误的位置。 If you have proper tools, it's pretty easy to diagnose an error with those pieces of data. 如果您有合适的工具,那么使用这些数据来诊断错误非常容易。 It can be argued that Oracle's system is nicer to tool creators than one which provides variable amounts of diagnostic data depending on the error. 可以说Oracle的系统比工具创建者更好,而不是根据错误提供可变数量的诊断数据。 Imagine having to write a custom parser for all of Oracle's error messages (including future errors) to highlight the offending location. 想象一下,必须为所有Oracle的错误消息(包括将来的错误)编写自定义解析器,以突出显示有问题的位置。

Sometimes including the table name would be misleading. 有时包括表名会有误导性。 Just knowing where things went wrong can be a huge help: 只知道出了什么问题可能是一个巨大的帮助:

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

As for why Oracle chose to do thing this way, I have some speculations: 至于Oracle选择以这种方式做事的原因,我有一些猜测:

  1. IBM used this style of error message for System R, which Larry Ellison, Bob Miner and Ed Oates copied to build Oracle V2. IBM在System R中使用了这种错误消息,Larry Ellison,Bob Miner和Ed Oates复制了这些消息来构建Oracle V2。 (Backward compatibility.) (向后兼容性。)

  2. Error number and location are the smallest possible representation of diagnostic information. 错误编号和位置是诊断信息的最小可能表示。 (Parsimony.) (简约)。

  3. As I indicated above, to simplify the creation of tools that connect to Oracle. 如上所述,为了简化连接到Oracle的工具的创建。 (Interoperability.) (互操作性)。

In any case, I don't think you need to be a DBA to figure out which table doesn't exist. 无论如何,我认为您不需要成为DBA来确定哪个表不存在。 You just need to use the proper tools. 你只需要使用适当的工具。 (And adjust your expectations, I suppose.) (并且我想,调整你的期望。)

If its not a huge statement, then the easiest way is just to check the data dictionary, 如果它不是一个巨大的声明,那么最简单的方法就是检查数据字典,

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> 

This isn't ideal, but short of going and examining trace files, I'm not sure how else to do it. 这不是理想的,但缺少去检查跟踪文件,我不知道怎么做。

Reason 1: Multi-lingual interface 原因1:多语言界面

There is a language-specific message configuration file for your database instance. 您的数据库实例有一个特定于语言的消息配置文件。 Messages are pulled out of there and translated from the pure numeric version to the numeric+text version. 消息被拉出并从纯数字版本转换为数字+文本版本。

It was probably considered better to have the hardcoded strings, than to run the risk at runtime of having a mysterious failure due to an improperly formatted "%s" string. 拥有硬编码字符串可能被认为比在运行时因为格式不正确的“%s”字符串而导致出现神秘故障的风险更大。

(Not that I particularly agree with this POV, btw.) (不是说我特别同意这个POV,顺便说一下。)

Reason 2: Security 原因2:安全

Right now you don't particularly expose the internal workings of your application if you print a PHP, etc, dump of an Oracle error message to the browser. 现在,如果您打印PHP等,将Oracle错误消息转储到浏览器,则不会特别公开应用程序的内部工作方式。

Applications would be a bit more exposed if more detail were printed by default... For example, if citibank printed a more explanatory message. 如果默认打印更多细节,应用程序将更加暴露...例如,如果citibank打印了更多解释性消息。

(see disclaimer above, I would be happy to get more information in the error as well.) (请参阅上面的免责声明,我也很乐意在错误中获得更多信息。)

@Matthew @马修

Your query's a start, but it might not work when you have multiple schemas. 您的查询是一个开始,但是当您有多个模式时它可能不起作用。 For example, if I log into our instance as myself, I have read access to all our tables. 例如,如果我以自己的身份登录我们的实例,我可以读取所有表的访问权限。 But if I don't qualify the table name with the schema I'll get an ORA-00942 for tables without synonyms: 但是,如果我没有使用模式限定表名,我将为没有同义词的表获得ORA-00942:

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

The table still shows up in all_tables though: 该表仍显示在all_tables中:

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

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

@erikson Sorry that doesn't help much. @erikson对不起,这没什么用。 I'm with Mark - I used TOAD. 我和马克一起 - 我用过TOAD。

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

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