PL / SQL:遇到符号“END”

时间:2012-11-03 12:27:07

标签: sql oracle stored-procedures plsql sqlplus

我收到以下错误,即使我仔细检查了代码。我不知道我错过了什么。

LINE / COL ERROR


31/1 PLS-00103:当期待其中一个时遇到符号“END”          以下内容:

CODE:

CREATE OR REPLACE PROCEDURE sp_ssjm_newworkorder
(   workorderno IN NUMBER,
company     IN CHAR,
attention   IN CHAR,
datedue     IN DATE,
loggedby    IN CHAR
)

AS  id     NUMBER;
today         DATE:=SYSDATE;
BEGIN
SELECT  client_id   --grab client_id
INTO id 
FROM    ssjm_client
WHERE ssjm_client.name=company;

IF id IS NULL THEN  --check if client exists by checking if client_id is there
    dbms_output.put_line('Please create client first');
    GOTO the_end;
ELSE
    INSERT INTO ssjm_workorder      VALUES(workorderno,workorderno,company,loggedby,attention,'Received',today,datedue,id);
END IF;

EXCEPTION
    WHEN OTHERS THEN
    raise_application_error(-20999,'An error occured in' ||
        SQLCODE || '-ERROR-' || SQLERRM);

<<the_end>>

END sp_ssjm_newworkorder;

1 个答案:

答案 0 :(得分:4)

您的代码中有几个需要注意的地方:

  1. 您遇到此错误的原因是因为标签<<the_end>>应放在EXCEPTION部分之前。
  2. 标签后需要操作员。因此,如果要跳转到存储过程的末尾,则不应使用其他操作NULL运算符。
  3. 为此,您的代码应如下所示:

    IF id IS NULL THEN  --check if client exists by checking if client_id is there
        dbms_output.put_line('Please create client first');
        GOTO the_end;
    ELSE
        INSERT INTO ssjm_workorder
     VALUES(workorderno,workorderno,company,loggedby
           ,attention,'Received',today,datedue,id);
    END IF;
    
    <<the_end>>
    NULL;
    
    EXCEPTION
        WHEN OTHERS THEN
        raise_application_error(-20999,'An error occured in' ||
            SQLCODE || '-ERROR-' || SQLERRM);
    END sp_ssjm_newworkorder;
    

    一定要尽量避免无条件分支。使用GOTO运算符是非常非常好的做法。它会杀死可读性,代码很难调试。它将导致你和所有在你头疼之后会查看该代码的人。而且如果查询

    SELECT  client_id   --grab client_id
    INTO id 
    FROM    ssjm_client
    WHERE ssjm_client.name=company;
    

    不返回任何行,将立即引发异常NO_DATA_FOUND并停止执行代码。因此永远不会评估IF id IS NULL THEN条件。您可以通过删除该条件并在代码的NO_DATA_FOUND部分中添加EXCEPTION异常处理程序来重写代码。当然正如@Rob van Wijk在评论中正确指出的那样

      

    但可以进一步清理代码。今天变量可以删除和   什么时候应该删除其他人。就像现在一样,它只是   将错误转换为更长的错误消息,而无需更多详细信息   最重要的是:它伪装了真实错误所在的行号   发生了。

    不需要today变量,SYSDATE可以直接在values语句的insert子句中使用,WHEN OTHERS可以删除同样。

    CREATE OR REPLACE PROCEDURE sp_ssjm_newworkorder
    (
    workorderno IN NUMBER,
    company     IN CHAR,
    attention   IN CHAR,
    datedue     IN DATE,
    loggedby    IN CHAR
    )
    AS  
      id     NUMBER;
    BEGIN
      SELECT client_id   --grab client_id
        INTO id
        FROM ssjm_client
       WHERE ssjm_client.name=company;
    
        INSERT INTO ssjm_workorder      
          VALUES(workorderno,workorderno,company,loggedby
                ,attention,'Received',SYSDATE,datedue,id);
    
    EXCEPTION
        when NO_DATA_FOUND
        then dbms_output.put_line('Please create client first');
    END sp_ssjm_newworkorder;