【问题标题】:PLS-00103 error for procedurePLS-00103 程序错误
【发布时间】:2011-08-06 22:35:48
【问题描述】:

我有 2 台服务器(一台用于测试,一台用于生产),都有以下 Oracle 包(SELECT * FROM V$VERSION; 的输出相同:

Oracle9i 企业版 9.2.0.3.0 版 - 生产
PL/SQL 版本 9.2.0.3.0 - 生产
核心 9.2.0.3.0 生产
适用于 Linux 的 TNS:版本 9.2.0.3.0 - 生产
NLSRTL 版本 9.2.0.3.0 - 生产

奇怪的是,它在一台服务器上工作得很好,而在另一台服务器上却出现了这些错误……我应该去哪里看?看来是服务器配置问题。

我正在尝试编译这个程序:

CREATE OR REPLACE PROCEDURE P_A1 AS  
  NUMAR INTEGER := 0;  
  CURSOR A1_C3 IS  
    SELECT   
(SELECT SUM(D1.A_PAY) FROM A1_A D1 WHERE D1.YR_R = D.YR_R AND D1.MON_R = D.MON_R) x_A  
      FROM APP_COMPANY_ALL CO, A1_A D  
     WHERE D.YR_R = y.APPL_admin.F$APPL_YEAR  
       AND D.MON_R = y.APPL_admin.F$APPL_MONTH  
       AND d.cif=SUBSTR(RTRIM(CO.c_fisc),3);  
  V_A1 A1_C3%ROWTYPE;  

 BEGIN  
  NULL;  
END;  

我在其中一台服务器上收到以下错误:
PROCEDURE P_A1 的编译错误

Error: PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:

          ( - + case mod new not null others <an identifier>
          <a double-quoted delimited-identifier> <a bind variable> avg
          count current exists max min prior sql stddev sum variance
          execute forall merge time timestamp interval date
          <a string literal with character set specification>
          <a number> <a single-quoted SQL string> pipe
Text: (SELECT SUM(D1.A_PAY) FROM A1_A D1 WHERE D1.YR_R = D.YR_R AND D1.MON_R = D.MON_R) x_A

Error: PLS-00103: Encountered the symbol ")" when expecting one of the following:

          . ( * @ % & - + ; / at for mod rem <an exponent (**)> and or
          group having intersect minus order start union where connect
          ||
Text: (SELECT SUM(D1.A_PAY) FROM A1_A D1 WHERE D1.YR_R = D.YR_R AND D1.MON_R = D.MON_R) x_A

问题是,正如我所说,它可以在测试服务器上运行,但不能在生产服务器上运行。 Oracle 版本是相同的。我很确定这是导致此问题的配置选项。但我不知道在哪里寻找解决方案。

如果“Select ( Select ...”不是标量子查询,它就可以正常工作。当它在游标内时会失败。为什么它不能在生产服务器上工作?

【问题讨论】:

  • 附带说明,您知道您正在运行的版本不再受支持.....
  • 尝试将整个查询从游标粘贴到存储过程之外,看看它是否有效。疯狂的猜测 - 生产中的权限问题,例如缺少表上的授权?
  • 要检查是否是配置问题,请尝试在两个数据库上运行 select * from v$parameter 并比较两个查询的输出。
  • 我怀疑您的测试环境已升级到不同版本的 Oracle。

标签: oracle plsql pls-00103


【解决方案1】:

在比较两个服务器方面可能值得检查几个初始化参数:

plsql_optimize_level 兼容

这些差异可能会在服务器之间产生不同的行为。您可以通过将其更改为动态 SQL 来验证它可能是解析器问题的建议:

open my_cursor for 
     'SELECT   
           (SELECT SUM(D1.A_PAY) FROM A1_A D1 WHERE D1.YR_R = D.YR_R AND D1.MON_R = D.MON_R) x_A  
      FROM APP_COMPANY_ALL CO, A1_A D  
     WHERE D.YR_R = :1 
       AND D.MON_R = :2
       AND d.cif=SUBSTR(RTRIM(CO.c_fisc),3)'  using y.APPL_admin.F$APPL_YEAR , y.APPL_admin.F$APPL_MONTH  

【讨论】:

    【解决方案2】:

    这可能只是一个剪切粘贴问题,但在原始帖子中,光标以

    开头
    SELECT (SELECT...
    

    我认为这行不通。我建议您尝试以下方法:

    CREATE OR REPLACE PROCEDURE P_A1 AS
      NUMAR INTEGER := 0;
      CURSOR A1_C3 IS
        SELECT x_A.PAY_SUM
          FROM (SELECT SUM(D1.A_PAY) AS PAY_SUM
                  FROM A1_A D1
                  WHERE D1.YR_R = D.YR_R AND
                        D1.MON_R = D.MON_R) x_A
          INNER JOIN A1_A A D
            ON (D.YR_R = y.APPL_admin.F$APPL_YEAR AND
                D.MON_R = y.APPL_admin.F$APPL_MONTH)
          INNER JOIN APP_COMPANY_ALL CO
            ON (SUBSTR(RTRIM(CO.c_fisc),3) = D.CIF);
      V_A1 A1_C3%ROWTYPE;
    BEGIN
      NULL;
    END P_A1; 
    

    分享和享受。

    【讨论】:

    • 在 Oracle SQL 中,以“SELECT (SELECT...”开头的查询是可以的。但是在 Oracle 9 中,SQL 和 PL/SQL 在 DML 语句的实现之间存在严重差异。这是唯一的原因我可以看到为什么“SELECT (SELECT...”应该可以工作。从 Oracle 10 开始,在 SQL 和 PL/SQL 中都应该没问题。
    • @Codo:我的立场是正确的。我仍然很想知道上面响应中的查询版本是否更正了问题。
    • 在 Oracle 10、Oracle 11、PL/SQL 和 SQL 中都试过了,使用“SELECT (SELECT...”构造时总是出错。没有文档证明 Oracle 可以处理这个问题。可能是真的,您的测试服务器以某种方式未修补以允许这项工作?顺便说一句,为什么您需要这种奇怪的“选择(选择..”构造?
    • 这只是作为 select 子句的一部分的子查询,没什么异常。 stackoverflow.com/questions/20557899/…
    • docs.oracle.com/cd/E11882_01/server.112/e41084/… 声明“您可以在大多数需要表达式 (expr) 的语法中使用标量子查询表达式。”其中包括 select 语句的 select_list。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多