PLSQL中的异常处理

PLSQL中的异常处理,plsql,Plsql,我需要你的帮助来处理我包中的异常。我不知道在哪里写异常。我包括函数。问题是ACTY_COUNT是varchar类型。因此,如果用户在不知不觉中输入了一些字母,则整个程序包将无法工作,因为我们是该字段的总和。我需要为此编写一个例外,这样,如果该字段输入了任何字母值,它应该为该员工处理错误,同时显示其他员工的报告。提前谢谢 FUNCTION ACTY_Ld_DAT(V_STARTDATE IN DATE,V_ENDDATE IN DATE) RETURN SYS_REFCURSOR IS ACT

我需要你的帮助来处理我包中的异常。我不知道在哪里写异常。我包括函数。问题是ACTY_COUNT是varchar类型。因此,如果用户在不知不觉中输入了一些字母,则整个程序包将无法工作,因为我们是该字段的总和。我需要为此编写一个例外,这样,如果该字段输入了任何字母值,它应该为该员工处理错误,同时显示其他员工的报告。提前谢谢

FUNCTION ACTY_Ld_DAT(V_STARTDATE IN DATE,V_ENDDATE IN DATE) RETURN SYS_REFCURSOR IS
  ACTY_DATA SYS_REFCURSOR;

  BEGIN
      OPEN ACTY_DATA FOR
  /*Query to fetch the report field into ref cursor*/
      SELECT
     MAIN_DATA.EMPID AS "EMP_ID",
     MAIN_DATA.FIRST_NAME AS "FIRST_NAME",
     MAIN_DATA.LAST_NAME AS "LAST_NAME",
     MAIN_DATA.LOCATION AS "LOCATION",
     MAIN_DATA.ACTY_NAME AS "ACTY_NAME",
     SUM(NVL(MAIN_DATA.ACTY_COUNT,0)) AS "ACTY_COUNT",
     SUM(MAIN_DATA.REGULAR_HRS) AS "REG_HRS",
     SUM(MAIN_DATA.OVERTIME_HRS) AS "OT_HRS",
     SUM(MAIN_DATA.TOTAL_HRS) AS "TOTAL_HRS",
     (
        CASE
           WHEN MAIN_DATA.ACTY_NAME = 'X' AND SUM(ACTY_COUNT) != 0  THEN
              (100/SUM(MAIN_DATA.TOTAL_HRS)) * ROUND((1.33 * SUM(ACTY_COUNT)),1)
           WHEN (MAIN_DATA.ACTY_NAME = 'Y' OR MAIN_DATA.ACTY_NAME = 'Z' OR MAIN_DATA.ACTY_NAME = 'U') AND SUM(ACTY_COUNT) != 0 THEN
              (100/SUM(MAIN_DATA.TOTAL_HRS)) * ROUND((5 * SUM(ACTY_COUNT)),1)
           WHEN MAIN_DATA.ACTY_NAME = 'V' AND SUM(ACTY_COUNT) != 0 THEN
              (100/SUM(MAIN_DATA.TOTAL_HRS)) * ROUND((8 * SUM(ACTY_COUNT)),1)
           ELSE
              0
        END
     ) "PROD_PERCENTAGE"
  FROM
     (
  SELECT
           DATA.EMPID,
           DATA.FIRST_NAME,
           DATA.LAST_NAME,
           DATA.LOCATION,
           DATA.ACTY_NAME,
           SUM(NVL(DATA.ACTY_COUNT,0)) AS "ACTY_COUNT",
           MIN("Regular_Hrs") AS "REGULAR_HRS",
           MIN("Overtime_Hrs") AS "OVERTIME_HRS",
           MIN("Regular_Hrs") + MIN("Overtime_Hrs") AS "TOTAL_HRS"
        FROM
        (
           SELECT
              P.PERSONID "EMPID",
              P.FIRSTNM "FIRST_NAME",
              P.LASTNM "LAST_NAME",
              LABACCT.LABORLEV1NM "LOCATION",
              ACT.ACTIVITYNM "ACTY_NAME",
              SUM(NVL(RES.REPTXT,0)) AS "ACTY_COUNT",
              MIN(SPAN.EVENTDTM) "EVENTDT",
              (
                 SELECT
                    SUM(DURATIONSECSQTY/3600)
                 FROM
                    WFCTOTAL TOT,
                    PAYCODE PCD
                 WHERE
                    P.PERSONID = TOT.EMPLOYEEID AND
                    TOT.PAYCODEID = PCD.PAYCODEID AND
                    PCD.NAME IN ('Regular 1','Regular 2','Regular 3') and
                    TOT.APPLYDTM BETWEEN TRIM(V_STARTDATE) AND TRIM(V_ENDDATE)
              ) AS "Regular_Hrs",
              (
                 SELECT
                    NVL(SUM(DURATIONSECSQTY/3600),0)
                 FROM
                    WFCTOTAL TOT,
                    PAYCODE PCD
                 WHERE
                    P.PERSONID = TOT.EMPLOYEEID AND
                    TOT.PAYCODEID = PCD.PAYCODEID AND
                    PCD.NAME IN ('Overtime 1','Overtime 2','Overtime 3') and
                    TOT.APPLYDTM BETWEEN TRIM(V_STARTDATE) AND TRIM(V_ENDDATE)
              ) AS "Overtime_Hrs"
           FROM
              PERSON P,
              WFAREPACTYSPAN SPAN,
              WFAREPLABACCT WFALABACCT,
              LABORACCT LABACCT,
              WFAREPACTYRES RES,
              WFAACTIVITY ACT
           WHERE
              P.PERSONID = SPAN.EMPLOYEEID AND
              WFALABACCT.WFAREPACTYSPANID = SPAN.WFAREPACTYSPANID AND
              LABACCT.LABORACCTID = WFALABACCT.LABORACCTID AND
              RES.WFAREPACTYSPANID(+) = SPAN.WFAREPACTYSPANID AND
              ACT.WFAACTIVITYID = SPAN.WFAACTIVITYID AND
              ACT.WFAACTIVITYID NOT IN (-1) AND
              SPAN.DELETEDSW = 0 AND
              SPAN.APPROVEDSW = 1 AND
              SPAN.EVENTDTM BETWEEN TRIM(V_STARTDATE) AND TRIM(V_ENDDATE) AND
              P.PERSONID IN  (
                                 SELECT
                                    EMPLOYEEID
                                 FROM
                                    WTKEMPLOYEE
                                 WHERE
                                    PAYRULEID IN (
                                                    SELECT
                                                       PAYRULEID
                                                    FROM
                                                       PAYRULEIDS
                                                    WHERE
                                                       NAME = 'XXXX'OR
                                                       NAME = 'YYYY'
                                                 )
                              )
           GROUP BY
              P.PERSONID,
              P.FIRSTNM,
              P.LASTNM,
              LABACCT.LABORLEV1NM,
              ACT.ACTIVITYNM,
              SPAN.EVENTDTM
        ) DATA
        GROUP BY
           DATA.EMPID,
           DATA.FIRST_NAME,
           DATA.LAST_NAME,
           DATA.LOCATION,
           DATA.ACTY_NAME
       )MAIN_DATA
     GROUP BY
        MAIN_DATA.EMPID,
        MAIN_DATA.FIRST_NAME,
        MAIN_DATA.LAST_NAME,
        MAIN_DATA.LOCATION,
        MAIN_DATA.ACTY_NAME;




     RETURN ACTY_DATA;
  END ACTY_LOAD_DATA;

您可以创建自己的函数来解决此问题。e、 g:

CREATE FUNCTION to_number_or_null (text IN VARCHAR2) RETURN NUMBER IS
BEGIN
  RETURN TO_NUMBER(text);
EXCEPTION
  WHEN VALUE_ERROR THEN
    RETURN NULL;
END to_number_or_null;
现在,更改您的查询:

SUM(NVL(to_number_or_null(RES.REPTXT),0)) AS "ACTY_COUNT",

您可以创建自己的函数来解决此问题。e、 g:

CREATE FUNCTION to_number_or_null (text IN VARCHAR2) RETURN NUMBER IS
BEGIN
  RETURN TO_NUMBER(text);
EXCEPTION
  WHEN VALUE_ERROR THEN
    RETURN NULL;
END to_number_or_null;
现在,更改您的查询:

SUM(NVL(to_number_or_null(RES.REPTXT),0)) AS "ACTY_COUNT",

你真的不能把
ACTY\u COUNT
a
NUMBER
列?这样做会容易得多,而且更好我不能更改列的数据类型。。。我需要另一个解决方案你真的不能把
活动计数
a
NUMBER
列?这样做会容易得多,而且更好我不能更改列的数据类型。。。我需要一个替代的解决方案,但是这里我使用一个游标从查询中获取值。如果我使用上面的函数,我只需要传递那个特定的值,我猜。这不是很复杂吗?请给我一些建议this@Remya表示“这不是很复杂吗?”使用VARCHAR2列存储数值会导致任何复杂情况。糟糕的数据模型总是让我们的生活更加复杂。在这种情况下,只有一个合乎逻辑的地方可以解决问题——正如杰弗里指出的,最内在的问题。事实上,只要引用
NVL(MAIN\u DATA.ACTY\u COUNT,0)
,您就可以去掉所有其他
NVL()
函数,因此查询实际上稍微不那么复杂。嗨,Jeffrey和APC感谢您的宝贵建议。我可以实现该功能及其工作。非常感谢…但我在这里使用游标从查询中获取值..如果我使用上述函数,我只需要传递特定的值,我猜。这不是很复杂吗?请给我一些建议this@Remya表示“这不是很复杂吗?”使用VARCHAR2列存储数值会导致任何复杂情况。糟糕的数据模型总是让我们的生活更加复杂。在这种情况下,只有一个合乎逻辑的地方可以解决问题——正如杰弗里指出的,最内在的问题。事实上,只要引用
NVL(MAIN\u DATA.ACTY\u COUNT,0)
,您就可以去掉所有其他
NVL()
函数,因此查询实际上稍微不那么复杂。嗨,Jeffrey和APC感谢您的宝贵建议。我可以实现该功能及其工作。非常感谢你。。。