错误ORA-06502:PL / SQL:数字或值错误:字符到数字转换错误ORA-06512:在第22行

时间:2015-12-18 03:07:42

标签: oracle plsql

我试着解决这个问题两天而且我无法解决 我知道为什么代码会发生但我不知道在哪里。
或者为什么会发生......

这必须在PLSQL中完成 这是一项家庭作业。

SET SERVEROUTPUT ON
DECLARE

  V_IDNO      PAYDATA1.IDNO%TYPE;
  V_NAME      PAYDATA1.NAME%TYPE;
  V_SAL       PAYDATA1.SALARY%TYPE;
  V_JOB       PAYDATA1.JOBCODE%TYPE;
  V_PAY       PAYDATA1.PAYHR%TYPE;
  V_IDNO1     PAYTRAN1.IDNO%TYPE;
  V_HOURSWK   PAYTRAN1.HOURSWK%TYPE; 
  V_HOURS     HOURSWKD.HOURSWK%TYPE; 

  V_CHECK    NUMBER(10);
CURSOR paydata_cursor IS
     SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR FROM PAYDATA1
     ORDER BY IDNO;
CURSOR paytran_cursor IS
     SELECT IDNO, HOURSWK FROM PAYTRAN1
     WHERE V_IDNO = IDNO
     order by IDNO;
BEGIN
OPEN paydata_cursor;
LOOP
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;
EXIT WHEN paydata_cursor%NOTFOUND;

IF V_SAL > 0 THEN
V_CHECK := V_SAL / 52;

DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);

END IF;

IF V_SAL = 0 AND V_HOURSWK < 41 THEN
V_CHECK := V_PAY * V_HOURS;

DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);

ELSIF V_SAL = 0 AND V_HOURSWK > 40 THEN
V_CHECK := V_PAY * V_HOURS;
V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));

DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);

END IF;

END LOOP;
CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF

我得到这个错误,试图把它固定一整天,但不能。有什么建议吗?

SQL> @ CURSOR5
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 22

3 个答案:

答案 0 :(得分:0)

问题是您的专栏paydata1.JOBCODE不是数字 在此代码FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;中,您将其分配给V_CHECK,即数字

更改这样的订单:FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_CHECK, V_PAY;它应该有效但请确保paydata1.salary是一个数字

此外,我不确定您何时声明V_SAL,然后为什么在此光标提取中使用V_CHECK

答案 1 :(得分:0)

我可以看到您的代码存在一些问题但却不知道更多信息很难诊断......但我会尝试:

打开光标时,您似乎正在选择错误的变量。

您还无法在任何地方打开paytran_cursor。您可以自己添加该代码,但在此之前,您对V_HOURSWK的检查不会非常有用等。

请改为尝试:

SET SERVEROUTPUT ON
DECLARE

  V_IDNO      PAYDATA1.IDNO%TYPE;
  V_NAME      PAYDATA1.NAME%TYPE;
  V_SAL       PAYDATA1.SALARY%TYPE;
  V_JOB       PAYDATA1.JOBCODE%TYPE;
  V_PAY       PAYDATA1.PAYHR%TYPE;
  V_IDNO1     PAYTRAN1.IDNO%TYPE;
  V_HOURSWK   PAYTRAN1.HOURSWK%TYPE; 
  V_HOURS     HOURSWKD.HOURSWK%TYPE; 

  V_CHECK    NUMBER(10);
CURSOR paydata_cursor IS
     SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR 
       FROM PAYDATA1
      ORDER BY IDNO;
CURSOR paytran_cursor IS
     SELECT IDNO, HOURSWK 
       FROM PAYTRAN1
      WHERE V_IDNO = IDNO
      order by IDNO;
BEGIN
  OPEN paydata_cursor;
  LOOP
    -- Changed the variables you were selecting into
    FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_SAL, V_PAY;
    EXIT WHEN paydata_cursor%NOTFOUND;

    IF V_SAL > 0 
    THEN
      V_CHECK := V_SAL / 52;

      DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
    END IF;

    IF V_SAL = 0 AND V_HOURSWK < 41 
    THEN
      V_CHECK := V_PAY * V_HOURS;

      DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
    ELSIF V_SAL = 0 AND V_HOURSWK > 40 
    THEN
      V_CHECK := V_PAY * V_HOURS;
      V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));

      DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
    END IF;

  END LOOP;
  CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF

希望它有所帮助。

修改

我试图猜测您要对代码执行的操作,并认为下面的内容可能会以某种方式更有效地解决您的问题:

SET SERVEROUTPUT ON
DECLARE
  --
  c_max_hours CONSTANT NUMBER := 40;
  --
  -- N.B.: I have assumed that there may be more than one entry per IDNO for 
  -- hours worked, if this is not the case then you can remove the SUM() and 
  -- the GROUP BY clause
  --
  CURSOR pay_cursor
  IS
    SELECT IDNO, 
           NAME, 
           JOBCODE, 
           SALARY, 
           PAYHR,
           SUM(HOURSWK) AS HOURS_WORKED
      FROM PAYDATA1
      JOIN PAYTRAN1 USING (IDNO)
     GROUP BY IDNO, 
              NAME, 
              JOBCODE, 
              SALARY, 
              PAYHR;
  --
  V_CHECK     NUMBER;
  pay_record  pay_cursor%ROWTYPE;
  --
BEGIN
  -- Depending on the rows in your cursor you might want to increase the output buffer for DBMS_OUTPUT
  DBMS_OUTPUT.ENABLE(1000000);
  --
  OPEN pay_cursor;
  LOOP
    -- Fetch the data into your cursor rowtype variable
    FETCH paydata_cursor INTO pay_record;
    EXIT WHEN pay_cursor%NOTFOUND;

    --
    -- ASSUMPTION: salary is not NULL (i.e. 0 or more).
    --
    IF pay_record.salary > 0 
    THEN
      V_CHECK := pay_record.salary / 52;
    ELSE
      --
      -- Salary must be zero
      --
      IF pay_record.hours_worked <= c_max_hours 
      THEN
        V_CHECK := pay_record.payhr * pay_record.hours_worked;
      ELSE
        -- Must be > c_max_hours 
        V_CHECK := pay_record.payhr * pay_record.hours_worked;
        V_CHECK := pay_record.salary + ((pay_record.hours_worked * 1.5) * (pay_record.hours_worked - 40));
      END IF;
    END IF;

    --
    -- Output your result
    --
    DBMS_OUTPUT.PUT_LINE(pay_record.idno|| ' HAS A CHECK FOR: '||V_CHECK);

  END LOOP;
  CLOSE paydata_cursor;
EXCEPTION
  WHEN others
  THEN
    -- Close the cursor if it is still open
    IF pay_cursor%ISOPEN
    THEN 
      CLOSE pay_cursor;
    END IF;
    -- Re-raise the error
    RAISE;
END;
/
SET SERVEROUTPUT OFF

我希望它有用。 附:我无法在真实的环境中检查这一点,因为我不在我平常的PC上,因此对任何语法错误表示道歉。

答案 2 :(得分:0)

当你将光标paydata_cursor定义为像

这样的列时,在第13行

从PAYDATA1中选择IDNO,NAME,JOBCODE,SALARY,PAYHR      由IDNO订购; 列序列IDNO,NAME,JOBCODE,SALARY,PAYHR

但在第23行,即

FETCH paydata_cursor INTO V_IDNO,V_NAME,V_CHECK,V_JOB,V_PAY; 你实际上正在提取像这样的列

IDNO,NAME,JOBCODE,SALARY,PAYHR进入 V_IDNO,V_NAME,V_CHECK,V_JOB,V_PAY

这意味着JOBCODE将进入V_CHECK 和SALARY进入V_JOB
因为薪水必须是数字,而v_check必须是varchar

我认为这就是你收到此错误的原因

由于 SID