代码之家  ›  专栏  ›  技术社区  ›  StevenC

填充维度表时PL/SQL FOR循环错误

  •  0
  • StevenC  · 技术社区  · 7 年前

    我正在填充一个名为 TIMES 使用来自名为 SALES 使用以下代码:

    CREATE TABLE TIMES
    (saleDay        DATE        PRIMARY KEY,
    dayType         VARCHAR(50) NOT NULL);
    
    
    BEGIN
        FOR rec IN 
            (SELECT saleDate, CASE WHEN h.hd IS NOT NULL THEN 'Holiday'
                    WHEN to_char(saleDate, 'd') IN (1,7) THEN 'Weekend'
                    ELSE 'Weekday' END dayType
            FROM SALES s LEFT JOIN 
                (SELECT '01.01' hd FROM DUAL UNION ALL
                SELECT '15.01' FROM DUAL UNION ALL
                SELECT '19.01' FROM DUAL UNION ALL
                SELECT '28.05' FROM DUAL UNION ALL
                SELECT '04.07' FROM DUAL UNION ALL
                SELECT '08.10' FROM DUAL UNION ALL
                SELECT '11.11' FROM DUAL UNION ALL
                SELECT '22.11' FROM DUAL UNION ALL
                SELECT '25.12' FROM DUAL) h
            ON h.hd = TO_CHAR(s.saleDate, 'dd.mm'))    
            LOOP
                INSERT INTO TIMES VALUES rec;
            END LOOP;
    END;
    /
    

    当我运行这个程序时,我得到了错误ORA-00001(唯一约束冲突)和ORA-06512。我相信这是因为代码试图为我的 时代 维度表( saleDay ). 如何在这个循环中实现一个子句,使其只填充每个循环的一个实例 saleDate 进入 saleDay销售日 PK所以没有违规?

    例如,如果 出售 表,其中 销售日期 是2015-10-10,则代码应仅将2015-10-10的一个实例填充到 saleDay销售日 主键。我想我应该走的方向是实施 WHILE 子句,但我不能百分之百确定这将如何工作,因为此代码也使用 CASE 确定 saleDay销售日 是假日、工作日或周末,并将结果填充到 dayType

    2 回复  |  直到 7 年前
        1
  •  1
  •   mathguy    7 年前

    正在添加 DISTINCT 正如下面的评论所建议的,你的问题是解决问题的一种方法。

    以下方法可能更有效:

    for rec in (select distinct saledate from sales)
    loop
        insert into times (saleday, daytype) values
            (rec.saledate,   CASE .......);
    end loop;
    

    即:将大小写表达式放在INSERT语句中,而不是放在(隐式)游标的定义中。没有理由为同一日期多次计算CASE表达式,因为它可能多次出现在SALES表中。CASE表达式也没有理由成为游标的一部分。CASE表达式可以使用IN条件( case when to_char(rec.saledate, 'dd.mm') in ('01.01', '15.01', ....) then 'Holiday' when ....... )

    当然,除非作业问题明确指示您使用左外连接……:-(

        2
  •  0
  •   StevenC    7 年前

    正在添加 DISTINCT 已解决此问题。最初的想法 独特的 会对 CASE 但事实并非如此。感谢I3rutt指出这一点。

    BEGIN
        FOR rec IN 
            (SELECT DISTINCT saleDate, CASE WHEN h.hd IS NOT NULL THEN 'Holiday'
                    WHEN to_char(saleDate, 'd') IN (1,7) THEN 'Weekend'
                    ELSE 'Weekday' END dayType
            FROM SALES s LEFT JOIN 
                (SELECT '01.01' hd FROM DUAL UNION ALL
                SELECT '15.01' FROM DUAL UNION ALL
                SELECT '19.01' FROM DUAL UNION ALL
                SELECT '28.05' FROM DUAL UNION ALL
                SELECT '04.07' FROM DUAL UNION ALL
                SELECT '08.10' FROM DUAL UNION ALL
                SELECT '11.11' FROM DUAL UNION ALL
                SELECT '22.11' FROM DUAL UNION ALL
                SELECT '25.12' FROM DUAL) h
            ON h.hd = TO_CHAR(s.saleDate, 'dd.mm'))    
            LOOP
                INSERT INTO TIMES VALUES rec;
            END LOOP;
    END;
    /