【问题标题】:Error ORA-06502: PL/SQL: numeric or value error: character to number conversion error ORA-06512: at line 22错误 ORA-06502:PL/SQL:数字或值错误:字符到数字的转换错误 ORA-06512:在第 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 表之间进行连接吗?

标签: oracle plsql


【解决方案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,如果它解决了您的问题,您能否将答案标记为正确,因为它有助于反馈等。很高兴我能提供帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多