如何使用过程

时间:2019-01-15 07:06:13

标签: oracle oracle-apex

我尝试使用过程将数据从其他维表插入事实表,但无法执行。有时它会显示缺少的表达式,有时会忽略错误语句。

我通过编写此查询进行了尝试,但没有成功。

CREATE OR REPLACE PROCEDURE final_upload_fact AS
  CURSOR finally IS
    SELECT p.clean_project_key,
         u.cconsultant_key,
         c.stage_company_key,
         t.time_key
    FROM   clean_project p
    INNER  JOIN clean_consultant u
    ON     p.clean_consultant_id = u.cldmch_id
    INNER  JOIN clean_company c
    ON     p.clean_company_id = c.stage_ldmch_id
    INNER  JOIN dim_time t
    ON     t.year = to_char(p.clean_estimated_end_date, 'yyyy')
    OR     t.year = to_char(p.clean_actual_end_date, 'yyyy');
BEGIN
  FOR k IN finally
  LOOP
    INSERT INTO fact
    (prjfinished_estimatedate,
     hig_qual_consultant,
     nooffeedbackless3,
     noprjoverrunmnth,
     fk1_dim_consultant_key,
     fk2_time_key,
     fk3_dim_project_key,
     fk4_dim_company_key)
    VALUES
    (SELECT COUNT(dim_project_key)
     FROM   dim_project
     WHERE  dim_project_estimated_end_date <= dim_actual_end_date, 
       SELECT MAX(dim_highest_quality)
     FROM   dim_consultant,
       SELECT COUNT(dim_feedbackvalue)
       FROM   dim_project
       WHERE  dim_feedbackvalue != 'N/A'
       AND    dim_feedbackvalue <= 3,  SELECT COUNT(dim_project_key)
               FROM   dim_project,
       k.cconsultant_key,
       k.time_key,
       k.clean_project_key,
       k.stage_company_key);
  END LOOP;
END;
/

1 个答案:

答案 0 :(得分:2)

问题是您的子查询在VALUES子句中没有括号。

在引用子查询时,需要将其括在方括号中,这将使您的代码看起来像这样:

CREATE OR REPLACE PROCEDURE final_upload_fact AS
  CURSOR finally IS
    SELECT p.clean_project_key,
           u.cconsultant_key,
           c.stage_company_key,
           t.time_key
    FROM   clean_project p
    INNER  JOIN clean_consultant u
    ON     p.clean_consultant_id = u.cldmch_id
    INNER  JOIN clean_company c
    ON     p.clean_company_id = c.stage_ldmch_id
    INNER  JOIN dim_time t
    ON     t.year = to_char(p.clean_estimated_end_date, 'yyyy')
    OR     t.year = to_char(p.clean_actual_end_date, 'yyyy');
BEGIN
  FOR k IN finally
  LOOP
    INSERT INTO fact
      (prjfinished_estimatedate,
       hig_qual_consultant,
       nooffeedbackless3,
       noprjoverrunmnth,
       fk1_dim_consultant_key,
       fk2_time_key,
       fk3_dim_project_key,
       fk4_dim_company_key)
    VALUES
      ((SELECT COUNT(dim_project_key)
        FROM   dim_project
        WHERE  dim_project_estimated_end_date <= dim_actual_end_date), 
       (SELECT MAX(dim_highest_quality)
        FROM   dim_consultant),
       (SELECT COUNT(dim_feedbackvalue)
        FROM   dim_project
        WHERE  dim_feedbackvalue != 'N/A'
        AND    dim_feedbackvalue <= 3),
       (SELECT COUNT(dim_project_key)
        FROM   dim_project),
       k.cconsultant_key,
       k.time_key,
       k.clean_project_key,
       k.stage_company_key);
  END LOOP;
END;
/

但是,可以通过将子查询移到游标中来极大地简化代码,这将消除遍历游标的需要,因为您可以执行insert-as-select。

假设子查询与定义的游标确实没有任何关联,则可以像这样重写整个内容:

CREATE OR REPLACE PROCEDURE final_upload_fact AS
    INSERT INTO fact
          (prjfinished_estimatedate,
           hig_qual_consultant,
           nooffeedbackless3,
           noprjoverrunmnth,
           fk1_dim_consultant_key,
           fk2_time_key,
           fk3_dim_project_key,
           fk4_dim_company_key)
    SELECT (SELECT COUNT(dim_project_key)
            FROM   dim_project
            WHERE  dim_project_estimated_end_date <= dim_actual_end_date) cnt_est_less_act_end_dt, 
           (SELECT MAX(dim_highest_quality)
            FROM   dim_consultant) max_highest_quality_consultant,
           (SELECT COUNT(dim_feedbackvalue)
            FROM   dim_project
            WHERE  dim_feedbackvalue != 'N/A'
            AND    dim_feedbackvalue <= 3) feedback_cnt,
           (SELECT COUNT(dim_project_key)
            FROM   dim_project) project_cnt,
           p.clean_project_key,
           u.cconsultant_key,
           c.stage_company_key,
           t.time_key
    FROM   clean_project p
    INNER  JOIN clean_consultant u
    ON     p.clean_consultant_id = u.cldmch_id
    INNER  JOIN clean_company c
    ON     p.clean_company_id = c.stage_ldmch_id
    INNER  JOIN dim_time t
    ON     t.year = to_char(p.clean_estimated_end_date, 'yyyy')
    OR     t.year = to_char(p.clean_actual_end_date, 'yyyy');
END final_upload_fact;
/

这样,您将删除原始过程在PL / SQL和SQL之间进行的所有上下文切换(即,在PL / SQL中打开游标,切换到SQL以生成执行计划,再回到PL / SQL以请求执行下一行,返回SQL获取下一行,返回PL / SQL将行存储在记录中,返回SQL以插入相关数据,返回PL / SQL以确定循环的结束因此要求下一行,等等,等等。