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

发布于 2024-07-04 10:19:17 字数 452 浏览 5 评论 0原文

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

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

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

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


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

If you've used Oracle, you've probably gotten the helpful message "ORA-00942: Table or view does not exist". 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. 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?


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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

早茶月光 2024-07-11 10:19:17

@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
抱歉,这没有多大帮助。 我和马克在一起——我用过蟾蜍。

@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:

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:

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

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

@erikson
Sorry that doesn't help much. I'm with Mark - I used TOAD.

硬不硬你别怂 2024-07-11 10:19:17

我在解释 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

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

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

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

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

无论如何,我认为您不需要成为 DBA 才能找出哪个表不存在。 您只需要使用正确的工具即可。 (我想,并调整你的期望。)

I've never had a problem with interpreting Oracle error messages. 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. That includes SQL*Plus, as others have noted, and the Perl DBI module:

$ 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. 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. As far as I can tell, none of the the error messages in Oracle support variable text. Instead, Oracle returns two bits of information: an error number and a location where the error occurs. 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. Imagine having to write a custom parser for all of Oracle's error messages (including future errors) to highlight the offending location.

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:

  1. IBM used this style of error message for System R, which Larry Ellison, Bob Miner and Ed Oates copied to build 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. (Interoperability.)

In any case, I don't think you need to be a DBA to figure out which table doesn't exist. You just need to use the proper tools. (And adjust your expectations, I suppose.)

你与清晨阳光 2024-07-11 10:19:17

原因 1:多语言界面

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

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

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

原因 2:安全性

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

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

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

Reason 1: Multi-lingual interface

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.

(Not that I particularly agree with this POV, btw.)

Reason 2: Security

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.

Applications would be a bit more exposed if more detail were printed by default... For example, if citibank printed a more explanatory message.

(see disclaimer above, I would be happy to get more information in the error as well.)

流绪微梦 2024-07-11 10:19:17

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

EVENT="942 跟踪名称 errorstack level 12"

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

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.

EVENT="942 trace name errorstack level 12"

If you are using a plain text file you need to keep all your EVENT settings on consecutive lines. Not sure how that applied to spfile.

等风来 2024-07-11 10:19:17

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

SQL*Plus does tell you the table that doesn't exist. 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.

Similarly, in a one-line SQL statement you can see the asterisk highlighting the name of the unknown table:

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).

沉鱼一梦 2024-07-11 10:19:17

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

I would disagree with the opinion, that SQL+ lets you understand which table name is unacceptable. True, it helps in direct DML, although parsing it is very hard. 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
寻找一个思念的角度 2024-07-11 10:19:17

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

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

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.

Copy and paste your SQL in to one of these tools to help. You may also find the analyse info available useful too.

勿忘心安 2024-07-11 10:19:17

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

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> 

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文