3

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

LINE/COL 错误


31/1 PLS-00103:在预期以下情况之一时遇到符号“END”:

代码:

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;
4

1 回答 1

4

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

  1. 您出现该错误的原因是标签 <<the_end>>应该放在该EXCEPTION部分之前。
  2. 标签后需要操作符。因此,如果您想跳转到存储过程的末尾并且不需要其他操作,NULL则应使用运算符。

为此,您的代码应如下所示:

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 变量可以被删除,而 WHEN OTHERS 绝对应该被删除。就像现在一样,它只是将错误转换为更长的错误消息,没有更多细节,最重要的是:它掩盖了发生真正错误的行号。

不需要today变量,SYSDATE可以直接在语句的values子句中使用insertWHEN 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;
于 2012-11-03T12:40:56.677 回答