这是我调用 sqlplus 的 shell 脚本:
#!/usr/bin/ksh
sqlplus $USER/$PASSWD@$DB<<!!>./logFile.log
SELECT 'IN sqlplus' FROM dual;
DECLARE tbl_xst integer;
SELECT COUNT(*) INTO tbl_xst FROM SYS.ALL_TABLES
WHERE table_name = 'SOME_TABLE'
AND OWNER = 'SOME_OWNER';
IF tbl_xst = 1 THEN
BEGIN
DROP TABLE SOME_OWNER.SOME_TABLE;
END
END IF
SELECT 'The end' FROM dual;
!!
当我运行 shell 脚本并查看日志文件 logFile.log 时,会出现以下内容:
SQL*Plus: Release 10.2.0.3.0 - Production on Mon Oct 22 12:33:05 2012
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options
SQL> SQL>
'INSQLPLUS
----------
IN sqlplus
SQL> SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Disconnected from Oracle Database 11g Enterprise Edition Releas
e 11.2.0.2.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options
如您所见,第一个记录 SELECT 语句 ('IN sqlplus') 使其进入,而底部的第二个 on 则没有,即执行没有到达它,因为两者之间存在错误。为什么 sqlplus 不在日志文件中写入此错误消息?
一些评论后编辑: 我们已经确定它很可能是由于 sqlplus 没有将 STDERR 转储到指定的日志文件中,其中只有 STDOUT 。如何格式化 sqlplus 命令以将两个流(STDOUT 和 ERR)组合到指定的日志文件中?我怀疑<<!!>
这里很关键。
更多实验后编辑: 奇怪的是,一些错误消息被转储到 STDOUT 中,我猜想那些试图引用坏 DB 对象的语法正确。如果有一个 SQL 编译错误,它显然是在 STDERR 中。我所做的是在上面的第一个 SELECT 和 DECLARE 之后插入以下行:
DROP TABLE FAKE_NONEXISTING;
该语句是合法的并且可以编译,但 FAKE_NONEXISTING 不存在,我在日志文件中得到以下内容:
SQL> SQL> DROP TABLE FAKE_NONEXISTING
*
ERROR at line 1:
ORA-00942: table or view does not exist
但是,我在日志文件中没有得到任何似乎是 SQL 编译错误的信息