提问人:erickson 提问时间:9/6/2008 最后编辑:Lalit Kumar Berickson 更新时间:12/18/2015 访问量:23952
为什么 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 跟踪名称错误堆栈级别 12”
如果您使用的是纯文本文件,则需要将所有 EVENT 设置保留在连续的行上。不确定这如何应用于 spfile。
评论
如果您使用的是 TOAD 或 TORA 等 SQL 浏览工具,它将通过突出显示或指向将光标移动到您出错的位置来帮助您解决 ORA 错误。
将 SQL 复制并粘贴到这些工具之一中,以提供帮助。您可能还会发现可用的分析信息也很有用。
评论
如果它不是一个巨大的语句,那么最简单的方法就是检查数据字典,
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>
这并不理想,但除了检查跟踪文件之外,我不确定还能如何做到这一点。
@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。
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(以某种方式)。
评论
我在解释 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
至于为什么甲骨文选择这样做事,我有一些猜测:
IBM 将这种样式的错误消息用于 System R,Larry Ellison、Bob Miner 和 Ed Oates 复制了该消息来构建 Oracle V2。(向后兼容性。
错误号和位置是诊断信息的最小可能表示形式。(吝啬。
正如我上面所指出的,为了简化连接到 Oracle 的工具的创建。(互操作性。
无论如何,我认为你不需要成为DBA就能弄清楚哪个表不存在。您只需要使用适当的工具。(我想,调整你的期望。
评论
ORA-00904 string: invalid identifier
原因1:多语言界面
数据库实例有一个特定于语言的消息配置文件。消息从那里拉出,从纯数字版本转换为数字+文本版本。
人们可能认为使用硬编码的字符串比在运行时冒着由于格式不正确的“%s”字符串而发生神秘故障的风险要好。
(顺便说一句,并不是说我特别同意这个 POV。
原因 2:安全性
现在,如果您打印 PHP 等,将 Oracle 错误消息转储到浏览器,则不会特别暴露应用程序的内部工作。
如果默认情况下打印更多细节,应用程序会更加暴露......例如,如果花旗银行打印了更具解释性的消息。
(请参阅上面的免责声明,我也很乐意在错误中获得更多信息。
评论
ORA-00932 inconsistent datatypes: expected %s got %s
我不同意这样一种观点,即 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
评论