PL/SQL 存储过程填充事实表
Posted
技术标签:
【中文标题】PL/SQL 存储过程填充事实表【英文标题】:PL/SQL Stored Procedure to Populate Fact Table 【发布时间】:2018-02-21 17:31:45 【问题描述】:我需要使用 PL/SQL 存储过程填充这个事实表:
CREATE TABLE SALES_FACTS
(saleDay DATE,
vehicleCode INT,
planID INT,
dealerID INT,
vehiclesSold INT,
grossSalesAmt NUMBER(10),
CONSTRAINT SALE_DAY_FK FOREIGN KEY (saleDay) REFERENCES TIMES(saleDay) ON DELETE CASCADE,
CONSTRAINT VEHICLE_CODE_FK FOREIGN KEY (vehicleCode) REFERENCES VEHICLES(vehicleCode) ON DELETE CASCADE,
CONSTRAINT PLAN_ID_FK FOREIGN KEY (planID) REFERENCES FINANCING_PLANS(planID) ON DELETE CASCADE,
CONSTRAINT DEALER_FK FOREIGN KEY (dealerID) REFERENCES DEALERSHIPS(dealerID) ON DELETE CASCADE,
CONSTRAINT SALES_FACTS_PK PRIMARY KEY (saleDay, vehicleCode, planID, dealerID));
我被要求通过使用四个嵌套游标循环来获取维度表主键的每个可能组合,以及每个组合的总销量和总销售额。
此外,如果vehiclesSold
和grossSalesAmount
的值为零,则不应将行插入SALES_FACTS
表中。
只应插入销售了一些车辆的四个外键列组合的行。
我创建了以下代码,希望能实现这一点:
CURSOR factData IS
SELECT vehicleVin,saleDate,sf.planID,sp.dealerID
COUNT (*) AS vehiclesSold
SUM (s.grossSalePrice) AS grossSalesAmount
FROM SALES s, SALES_FINANCINGS sf, SALESPERSONS sp
WHERE s.saleID = sf.saleID
AND s.salespersonID = sp.salespersonID
GROUP BY vehicleVIN, saleDate, sf.planID, sp.dealerID
HAVING COUNT(*) > 0;
BEGIN
FOR record IN factData
LOOP
INSERT INTO SALES_FACTS (saleDay,vehicleCode,planID,dealerID,vehiclesSold, grossSalesAmount
VALUES (record.saleDate,record.vehicleVin,record.planID,record.dealerID,record.vehiclesSold,record.grossSalesAmount);
END LOOP;
END;
/
但是代码执行得很好,但是当我运行时我没有得到任何结果
SELECT COUNT(*) FROM SALES_FACTS;
我在这里创建了一个 SQL Fiddle 链接http://sqlfiddle.com/#!4/9708d6/1,因为表和表填充的代码太多,无法在这个问题上发布。请记住,我为每个表只INSERT
ed 大约 2-3 行数据以保持代码有点短,但是已插入的数据应该足以使其正常工作。
请告诉我哪里出了问题以及解决问题的最佳方法是什么!提前致谢!
【问题讨论】:
为什么需要循环?这可以通过插入 .. 选择来完成。 1) 修正游标中查询的语法(dealerID 和车辆Sold 后缺少逗号)。 2) 您可以删除COUNT(*) > 0
,因为该组必须至少有一行。 3) 用光标定义调整表结构,例如vehicleCode 是 INT,但光标返回 147258HHE91K3RT
。 4) 添加提交
@OldProgrammer 你是对的。我只是选择了循环方法。愿意进行 INSERT,但不清楚如何针对这种特殊情况组装它。
@MarmiteBomber 感谢您抓住这些。我已经为此进行了很多回合,以至于我忘记在需要的地方进行更改。进行了更改,但仍然无法正常工作。
@StevenC:我建议你使用 livesql(或者 sqlplus,如果你有的话 sql developer)来验证 PL/SQL 块。我不知道它在 sqlfiddle 中是否有效,但据我尝试,它永远不会按预期工作。但是,首先要修复所有语法错误。
【参考方案1】:
这最终成功了。感谢所有评论者的帮助。
DECLARE
CURSOR sales_data
IS
SELECT vehicleVIN, saleDate, SF.planID, SP.dealerID,
COUNT(*) AS vehiclesSold, SUM(S.grossSalePrice) AS grossSalesAmt
FROM SALES S, SALES_FINANCINGS SF, SALESPERSONS SP, VEHICLES V
WHERE S.saleID = SF.saleID AND S.vehicleVIN = V.vehicleCode AND S.salespersonID = SP.salespersonID
GROUP BY vehicleVIN, saleDate, SF.planID, SP.dealerID
HAVING COUNT(*) > 0;
BEGIN
FOR record IN sales_data
LOOP
INSERT INTO SALES_FACTS (saleDay,vehicleCode,planID,dealerID,vehiclesSold, grossSalesAmt)
VALUES (record.saleDate,record.vehicleVIN,record.planID,record.dealerID,record.vehiclesSold,record.grossSalesAmt);
END LOOP;
END;
/
【讨论】:
以上是关于PL/SQL 存储过程填充事实表的主要内容,如果未能解决你的问题,请参考以下文章
在存储过程中创建动态表而在 PL/SQL 块表中创建时权限不足[重复]