2011-03-31 161 views
1

我需要您的帮助来处理我的包中的异常。我不知道在哪里写异常。我包括这个功能。问题是ACTY_COUNT是varchar类型的。所以如果用户在不知不觉中输入一些字母,整个程序包将无法工作,因为我们是该字段的总和。我需要为此写一个例外情况,以便如果为该字段输入了任何字母值,则可以处理该员工的错误,同时显示其他人的报告。在此先感谢PLSQL中的异常处理

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; 
+0

你真的不能让'ACTY_COUNT'一个'NUMBER'列?这将是如此容易,更好 – 2011-03-31 07:40:22

+0

不,我不能改变列的数据类型...我需要一个替代解决方案 – Remya 2011-03-31 09:24:37

回答

5

您可以创建自己的函数来解决此问题。例如: -

​​

现在更改查询:

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

但在这里,我使用游标从查询中获取值..如果我使用上面的函数,我只需要传递那个特定的值。它不会很复杂吗? Plz在这方面给我建议 – Remya 2011-03-31 09:28:54

+3

@Remya说:“它不会很复杂吗?”使用VARCHAR2列存储数值会产生任何复杂情况。糟糕的数据模型总是让我们的生活变得更加复杂。正如Jeffrey指出的那样,在这种情况下,有一个合理的地方可以解决问题 - 最深层的问题。事实上,每当你引用'NVL(MAIN_DATA.ACTY_COUNT,0)'时,你就可以去除所有其他'NVL()'函数,所以这个查询实际上是因为稍微复杂一点。 – APC 2011-03-31 17:40:10

+0

嗨Jeffrey和APC感谢您的宝贵意见。我可以实现该功能及其工作。非常感谢... – Remya 2011-04-05 07:35:03