我使用以下代码填充名为TIMES
的维度表,其中包含来自名为SALES
的OLTP表中的数据:
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。我相信这种情况正在发生,因为代码试图在我的TIMES
维度表(saleDay
)的PK中输入多个日期(其中一些是相同的)。我如何在这个循环中实现一个子句,这样它只会将每个saleDate
的一个实例填充到saleDay
PK中,这样就没有违规?
例如,如果SALES
表中有三行saleDate
是2015-10-10,则代码应仅填充2015-10-10的一个实例到{{ 1}} PK。我正在考虑我应该采用的方向是实现一个saleDay
子句,但是我不能100%确定它是如何工作的,因为这段代码也使用WHILE
来确定是否CASE
1}}是假日,工作日或周末,并将结果填入saleDay
列。
答案 0 :(得分:1)
根据问题下方的评论中的建议添加DISTINCT
是解决问题的一种方法。
以下方法可能更有效:
for rec in (select distinct saledate from sales)
loop
insert into times (saleday, daytype) values
(rec.saledate, CASE .......);
end loop;
即:将CASE表达式放在INSERT语句中,而不是放在(隐式)游标的定义中。没有理由在同一日期多次计算CASE表达式,这可能在SALES表中多次出现。 CASE表达式也没有理由成为游标的一部分。 CASE表达式可以使用IN条件(case when to_char(rec.saledate, 'dd.mm') in ('01.01', '15.01', ....) then 'Holiday' when .......
)
当然,除非作业问题明确指示你使用左外连接.......: - (
答案 1 :(得分:0)
添加DISTINCT
已解决此问题。最初认为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;
/