oracle 获取ORA-01744:尝试编译此存储进程时INTO不正确

ngynwnxp  于 2023-04-05  发布在  Oracle
关注(0)|答案(2)|浏览(168)

我写这个存储过程来更新一行时,从多个表检索日期.运行每个查询在自己的作品,但当编译我得到一个不合适的进入,我不明白为什么选择进入是在查询的最外层.我相信它的东西很简单,我错过了,但会欣赏它的手.
所有的查询工作在自己的,但只是有一个问题,与第四次选择到,我想也许我不能选择到,而使用串联或可能与数据库链接?不确定任何一种方式。

/* Formatted on 4/1/2023 7:00:25 PM (QP5 v5.360) */
CREATE PROCEDURE UPDATE_CLAIM (V_CLAIM_ID IN PTSADMIN.CLAIM.CLAIMID%TYPE)
IS
    V_CREW_ID      NUMBER;
    V_PERSONID     NUMBER;
    V_LIRRNUM      VARCHAR2 (10);
    V_CNAME        VARCHAR2 (10);
    V_START_DATE   DATE;
    V_NEXT_DAY     DATE;
    V_JOBNAME      VARCHAR2 (20);
    V_JOBGRADEID   NUMBER;
BEGIN
    BEGIN
        SELECT CREWID,
               PERSONID,
               CLAIMDTM,
               CLAIMDTM + 1
          INTO V_CREW_ID,
               V_PERSONID,
               V_START_DATE,
               V_NEXT_DAY
          FROM PTSADMIN.CLAIM CM
         WHERE CM.CLAIMID = V_CLAIM_ID;
    END;

    BEGIN
        SELECT NAME
          INTO V_CNAME
          FROM PTSADMIN.CREW CW
         WHERE CW.CREWID = V_CREW_ID;
    END;

    BEGIN
        SELECT LIRRNUM
          INTO V_LIRRNUM
          FROM PTSADMIN.PERSON PR
         WHERE PR.PERSONID = PERSONID;
    END;

    BEGIN
        SELECT tm.OCCUP_CODE || td.RATE_CODE
          INTO V_JOBNAME
          FROM ewm.TIMESLIP_MSTR@TEAMS_DBLINK    tm,
               ewm.TIMESLIP_DETAIL@TEAMS_DBLINK  td,
               ewm.EMP_MSTR@TEAMS_DBLINK         em
         WHERE     tm.TIMESLIP_MSTR_SID = td.TIMESLIP_MSTR_SID(+)
               AND tm.EMP_MSTR_SID = em.EMP_MSTR_SID
               AND em.EMP_NBR = V_LIRRNUM
               AND tm.EFF_DATE_TIME BETWEEN TO_DATE (V_START_DATE,
                                                     'MM/DD/YYYY')
                                        AND TO_DATE (V_NEXT_DAY,
                                                     'MM/DD/YYYY')
               AND td.VERSION = 1
              AND ROWNUM <= 1;
    END;

    BEGIN
        SELECT JOBGRADEID
          INTO V_JOBGRADEID
          FROM PTSADMIN.JOBGRADE JB
         WHERE JB.NAME = V_JOBNAME;
    END;

    UPDATE PTSADMIN.CLAIM CL
       SET CL.JOBGRADEID = V_JOBGRADEID
     WHERE CL.CLAIMID = V_CLAIM_ID;
END UPDATE_CLAIM;
ie3xauqp

ie3xauqp1#

我注意到两个明显的错误:

  • 在一个查询中使用了personid而不是v_personid
  • 已经是DATE s的变量不应该是TO_DATE d。看起来你实际上想TRUNC它们。

另外(虽然这并没有错),将每个select封装到它自己的begin-end块中是没有用的。如果你想用这种方式处理异常,这是有意义的,但是-你没有。
修复后(无法编译,因为我没有你的表,你没有提供测试用例,我不想自己创建那么多):

CREATE PROCEDURE update_claim (
    v_claim_id IN ptsadmin.claim.claimid%TYPE
) IS

    v_crew_id    NUMBER;
    v_personid   NUMBER;
    v_lirrnum    VARCHAR2(10);
    v_cname      VARCHAR2(10);
    v_start_date DATE;
    v_next_day   DATE;
    v_jobname    VARCHAR2(20);
    v_jobgradeid NUMBER;
BEGIN
    SELECT
        crewid,
        personid,
        claimdtm,
        claimdtm + 1
    INTO
        v_crew_id,
        v_personid,
        v_start_date,
        v_next_day
    FROM
        ptsadmin.claim cm
    WHERE
        cm.claimid = v_claim_id;

    SELECT
        name
    INTO v_cname
    FROM
        ptsadmin.crew cw
    WHERE
        cw.crewid = v_crew_id;

    SELECT
        lirrnum
    INTO v_lirrnum
    FROM
        ptsadmin.person pr
    WHERE
        pr.personid = v_personid;    -- personid;      

    SELECT
        tm.occup_code || td.rate_code
    INTO v_jobname
    FROM
        ewm.timeslip_mstr@teams_dblink   tm,
        ewm.timeslip_detail@teams_dblink td,
        ewm.emp_mstr@teams_dblink        em
    WHERE
            tm.timeslip_mstr_sid = td.timeslip_mstr_sid (+)
        AND tm.emp_mstr_sid = em.emp_mstr_sid
        AND em.emp_nbr = v_lirrnum
        --AND tm.eff_date_time BETWEEN to_date(v_start_date, 'MM/DD/YYYY') AND to_date(v_next_day, 'MM/DD/YYYY')
        AND tm.eff_date_time BETWEEN trunc(v_start_date) AND trunc(v_next_day)
        AND td.version = 1
        AND ROWNUM <= 1;

    SELECT
        jobgradeid
    INTO v_jobgradeid
    FROM
        ptsadmin.jobgrade jb
    WHERE
        jb.name = v_jobname;

    UPDATE ptsadmin.claim cl
    SET
        cl.jobgradeid = v_jobgradeid
    WHERE
        cl.claimid = v_claim_id;

END update_claim;
ac1kyiln

ac1kyiln2#

您似乎可以将其全部重写为单个查询:

CREATE PROCEDURE UPDATE_CLAIM (
  V_CLAIM_ID IN PTSADMIN.CLAIM.CLAIMID%TYPE
)
IS
BEGIN
  UPDATE PTSADMIN.CLAIM CL
  SET CL.JOBGRADEID = (
        SELECT jb.JOBGRADEID
        FROM   PTSADMIN.JOBGRADE JB
        WHERE  JB.NAME = (
                 SELECT tm.OCCUP_CODE || td.RATE_CODE
                 FROM   PTSADMIN.CLAIM CM
                        INNER JOIN PTSADMIN.PERSON PR
                        ON PR.PERSONID = CM.PERSONID
                        INNER JOIN (
                          ewm.TIMESLIP_MSTR@TEAMS_DBLINK tm
                          INNER JOIN ewm.EMP_MSTR@TEAMS_DBLINK em
                          ON tm.EMP_MSTR_SID = em.EMP_MSTR_SID
                          LEFT OUTER JOIN ewm.TIMESLIP_DETAIL@TEAMS_DBLINK  td
                          ON tm.TIMESLIP_MSTR_SID = td.TIMESLIP_MSTR_SID
                        )
                        ON     em.EMP_NBR = pr.LIRRNUM
                           AND tm.EFF_DATE_TIME >= TRUNC(CLAIMDTM)
                           AND tm.EFF_DATE_TIME <  TRUNC(CLAIMDTM) + 1
                 WHERE  td.VERSION = 1
                 AND    ROWNUM <= 1
                 AND    CM.CLAIMID = V_CLAIM_ID
          )
        )
  WHERE CL.CLAIMID = V_CLAIM_ID;
END UPDATE_CLAIM;

这是未经测试的,因为我没有你的表。
注意事项:

  • 你从来没有使用过V_CNAME,所以获取它的值是没有意义的。一旦它没有被使用,那么V_CREW_ID就永远不会被使用。
  • 在对td别名表的查询中有一个LEFT OUTER JOIN,但也过滤了td.VERSION = 1,这要求td行存在,并将有效地将OUTER JOIN转换为INNER JOIN
  • 您在ROWNUM = 1上进行筛选。虽然这将返回单行,但查询的顺序不一定,因此您实际上是随机返回任何一行。如果您想要基于排序的特定行,请使用ORDER BY something FETCH FIRST ROW ONLY(可从Oracle 12获得)。

相关问题