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

Posted

技术标签:

【中文标题】错误 ORA-06502:PL/SQL:数字或值错误:字符到数字的转换错误 ORA-06512:在第 22 行【英文标题】:Error ORA-06502: PL/SQL: numeric or value error: character to number conversion error ORA-06512: at line 22 【发布时间】:2015-12-18 03:07:41 【问题描述】:

我尝试了两天解决这个问题,但我无法解决。 我知道代码为什么会发生,但我不确定在哪里。 或者为什么会这样……

这必须在 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

【问题讨论】:

你要写的是存储过程吗? 我们不能简单地在 PAYDATA1 和 PAYTRAN1 表之间进行连接吗? 【参考方案1】:

问题是您的列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

【讨论】:

【参考方案2】:

在第 13 行,当您将光标 paydata_cursor 定义为类似列时

从 PAYDATA1 中选择 IDNO、姓名、工作代码、工资、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 因为salary 必须是数字并且v_check 必须是varchar

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

谢谢 席德

【讨论】:

【参考方案3】:

我可以看到您的代码存在一些问题,但在不了解更多信息的情况下很难诊断...但我会尝试:

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

您还没有在任何地方打开您的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 上,因此对任何语法错误表示歉意。

【讨论】:

谢谢你们,你们太棒了,这解决了我的问题。 @FagnerSchundtCaetano,如果它解决了您的问题,您能否将答案标记为正确,因为它有助于反馈等。很高兴我能提供帮助。

以上是关于错误 ORA-06502:PL/SQL:数字或值错误:字符到数字的转换错误 ORA-06512:在第 22 行的主要内容,如果未能解决你的问题,请参考以下文章

ORA-06502 PL/SQL:数字或值错误:字符到数字的转换错误;

ORA-06502: PL/SQL: 数字或值错误: 字符到数字的转换错误

ORA-06502: PL/SQL: 数字或值错误: NULL 索引表键值

ORA-06502: PL/SQL: 数字或值错误: 数字精度太大

获取 ORA-06502:PL/SQL:数字或值错误:SQL 触发器中的字符到数字转换错误

oracle ORA-06502:PL/SQL:数字或值错误:批量绑定:截断绑定