【问题标题】:Simple beginner Oracle PL/SQL help/fix needed for procedure creation创建过程所需的简单初学者 Oracle PL/SQL 帮助/修复
【发布时间】:2012-08-04 23:47:46
【问题描述】:

我是 PL/SQL 的新手,所以如果这看起来太像初学者的问题,请不要标记我。我已经花了几个小时来解决这个问题,现在正在寻求帮助。此外,请记住此代码不完整。我正在寻求帮助来完成它。所以我正在尝试为我的测试表创建一个名为 KEYBOARD_LEARNING 的简单过程。 我以前必须手动使用此代码:

INSERT INTO keyboard_learning (emplid, wpm, date_completed,exercise,attempt,score_lvl) 
VALUES ('000000000','37.66','04-JUL-2012','Keyhero.com','28','95.87% accuracy')

..每次我想在 KEYBOARD_LEARNING 中记录一个新分数。我想我可以创建一个程序来为我处理这个问题,但我需要它不是静态的,因为我在调用这个程序时输入的值总是在变化。关于如何使我拥有的代码具有这种最佳功能的任何想法?顺便说一句,下面的代码没有执行,我相信有经验的 Oracle 用户可以马上找出原因。

谢谢

CREATE OR REPLACE PROCEDURE INSERT_WPM_SCORE
(
          P_EMPLID VARCHAR2
         ,P_WPM NUMBER
         ,P_DATE_COMPLETED SYSDATE
         ,P_EXERCISE VARCHAR2
         ,P_ATTEMPT VARCHAR2
         ,P_SCORE_LVL VARCHAR2
) AS

          /*
          Original Author: 
          Created Date: 2-Aug-2012
          Purpose: For inputting latest WPM score from typing practice
          */

          /*variables*/

          L_EMPLID VARCHAR2(4000);
          L_WPM NUMBER;
          L_DATE_COMPLETED SYSDATE;
          L_EXERCISE VARCHAR2(4000);
          L_ATTEMPT VARCHAR2(4000);
          L_SCORE_LVL VARCHAR2(4000);
          L_PREVENT_NULL_INPUT EXCEPTION;
          PRAGMA EXCEPTION_INIT(L_PREVENT_NULL_INPUT, -44002); --GET CORRECT ERROR # BY TESTING WITHOUT EXCEPTION
          VALUES VARCHAR2(4000);  [b]<-- getting an error here[/b]

          /*Procedure 'W' is a wrapper for DBMS output*/
          PROCEDURE W(STR VARCHAR2) IS
                        L_STRING VARCHAR2(4000);
          BEGIN
                        /*Outputting string parameter passed into 'W' procedure*/
                        L_STRING := STR;
                        DBMS_OUTPUT.PUT_LINE(STR);
          END;

BEGIN

         VALUES := (L_EMPLID, L_WPM,  L_DATE_COMPLETED, L_EXERCISE,  L_ATTEMPT,L_SCORE_LVL);

          SELECT INTO (SELECT *
                       FROM KEYBOARD_LEARNING A
                       ORDER BY A.EXERCISE
                               ,TO_NUMBER(ATTEMPT))

                     -- DBMS_OUTPUT.PUT_LINE(RESULTS);

EXCEPTION
          /* */            
          WHEN L_PREVENT_NULL_INPUT THEN
                        NULL;

          /*this exception catches all other exceptions*/
          WHEN OTHERS THEN
                        W('ERROR: ' || SQLERRM);

END;

【问题讨论】:

  • 对于初学者来说,您的代码相当复杂。正如 Justin 下面提到的,您应该首先从绝对最简单的方法开始,然后根据需要添加更多方法。这通常是处理大多数问题的好方法。

标签: sql oracle plsql oracle11g plsqldeveloper


【解决方案1】:

首先,让我们实现最简单的可行方法

CREATE OR REPLACE PROCEDURE INSERT_WPM_SCORE
(
          P_EMPLID VARCHAR2
         ,P_WPM NUMBER
         ,P_DATE_COMPLETED DATE DEFAULT SYSDATE
         ,P_EXERCISE VARCHAR2
         ,P_ATTEMPT VARCHAR2
         ,P_SCORE_LVL VARCHAR2
) AS
BEGIN
  INSERT INTO keyboard_learning (emplid, wpm, date_completed,exercise,attempt,score_lvl) 
    VALUES( p_emplid, p_wpm, p_date_completed, p_exercise, p_attempt, p_score_lvl );
END;

假设这可行,那么您可以向该过程添加额外的功能。不幸的是,对我来说,您想要实现哪些附加功能并不明显。

  • 例如,您有一个异常,您似乎想要基于NULL 输入抛出和/或捕获,但我不确定它试图完成什么。您是否尝试验证程序的输入?您是否试图捕获在执行 INSERT 并违反 NOT NULL 约束时引发的异常?还有什么?
  • 我不确定您原始帖子中的SELECT 声明的目的是什么。也许您正试图覆盖传递给过程的p_attempt

此外,作为一般规则,捕获您无法处理的异常是一个错误,而WHEN OTHERS 后面没有RAISE 几乎总是一个错误。如果捕获异常并将SQLERRM 写入DBMS_OUTPUT,则会丢失异常提供的所有有用的堆栈跟踪信息,丢失生成错误的代码的行号,依赖客户端应用程序实际启用DBMS_OUTPUT 缓冲区并从中读取(大多数客户端应用程序不这样做),并且您正在阻止过程的调用者确定调用失败。完全消除异常处理程序会更好地为您服务。

【讨论】:

  • 很好的意见,谢谢贾斯汀。好吧,让我们看看......“例如,您有一个异常,您似乎想要基于 NULL 输入抛出和/或捕获,但我不确定它试图完成什么。”回答:是的,你是对的。如果在调用此过程时输入的数据为 0,我只想抛出某种异常。
  • “我不确定您原始帖子中的 SELECT 语句打算做什么。”回答:我仍然不确定必须如何创建此过程。我忘了把那段代码注释掉。基本上,SELECT 自己所做的就是检索我表中的 40 行并相应地对它们进行排序。它可能不需要在程序中。很抱歉离开了
  • @Shades - 如果您尝试调用过程而不为任何没有默认值的参数提供值,Oracle 将抛出一个错误,它无法确定您要调用的过程 (您可以有多个具有相同名称和不同参数列表的过程)。这将被抛出您的程序之外,因此您的程序无法捕获它。
  • 所以最好我在这个过程中没有例外,你觉得呢?还是我应该只实现 RAISE_APPLICATION_ERROR 类型的异常?
  • @Shades - 如果你可以对异常做一些有意义的事情,你应该只捕获一个异常。潜在地,捕获一个异常并引发另一个异常可能是有意义的——例如,您可能会捕获一个 dup_val_on_index 异常,检查它是否违反了主键约束,然后引发一个自定义异常对用户来说更有意义的错误消息(即“密钥”|| P_EMPLID || '已存在于表中。')。或者您可能会捕获异常,记录它,然后重新抛出它。但是,在 99% 的情况下,您应该让异常传播。
猜你喜欢
  • 1970-01-01
  • 2021-04-11
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多