我有以下任务:
任务描述
有一些客户使用某些服务的事实表:
USAGES表存储在模式USAGE_MGMT中。每月由外部应用程序填充一次。 有必要通过读取USAGES表并在BILL_CALC模式中填写以下表来实施帐单计算解决方案以为客户准备帐单,以在三个级别的层次结构中详细列出计算结果:
解决方案应在DB存储包中实施。它应允许针对单个或所有客户的特定月份和年份启动帐单计算流程。 假定USAGES表可以包含数十亿条不同客户和使用日期的记录,则该解决方案应适用于大量计算过程。如果某些使用记录的PRICE列为空,则过程不会停止,但应记录错误,并为下一个客户端继续计算过程。 假设USAGE_MGMT和BILL_CALC模式在不同的Oracle数据库实例中,并且两者都授予了sys管理员权限,请提供DDL脚本来创建必要的数据库实体,包括(但不限于)数据库链接,授权,程序包规范和主体,表索引等。
我的问题是如何将数据从USAGES表发送到其他三个表?另外,为什么需要包装?我们需要三个将成为游标的SELECT语句和一个过程。我说的对吗?
编辑:
CREATE OR REPLACE PROCEDURE proc_test (p_year IN VARCHAR2,
p_month IN VARCHAR2,
p_client_id IN NUMBER)
IS
num_of_clients NUMBER;
t_client_id NUMBER;
CURSOR cur_clients
IS
SELECT DISTINCT CLIENT_ID
FROM USAGE_MGMT.USAGES;
CURSOR cur_bill_total
IS
SELECT u.CLIENT_ID
FROM USAGE_MGMT.USAGES u;
BEGIN
DBMS_OUTPUT.PUT_LINE ('number of clients' || num_of_clients);
OPEN cur_clients
LOOP
FETCH cur_clients INTO t_client_id;
EXIT WHEN cur_clients%NOTFOUND;
--INSERT INTO
DBMS_OUTPUT.put_line ('Client:' || t_client_id);
END LOOP;
COMMIT;
END;
我对如何插入INTO感兴趣?
编辑:
有人可以检查以下步骤吗?它给我一个错误:Error(44,13): PL/SQL: ORA-00933: SQL command not properly ended
CREATE OR REPLACE PROCEDURE proc_test (p_year IN VARCHAR2,
p_month IN VARCHAR2,
p_client_id IN NUMBER)
IS
vIDArray DBMS_SQL.NUMBER_TABLE;
vIDClientArray DBMS_SQL.NUMBER_TABLE;
BEGIN
INSERT INTO bill_total (id,
client_id,
month,
year,
first_usage_date,
last_usage_date,
cost)
SELECT *
FROM (WITH Myfilter
AS (SELECT p_client_id pClientID,
TO_NUMBER (p_month) pMonth,
TO_NUMBER (p_year) pYear,
TO_DATE (
LPAD (p_month, 2, '0')
|| LPAD (p_year, 4, '0'),
'MMYYYY')
FirstOfMonth
FROM DUAL)
SELECT usage_mgmt.seq_usages.NEXTVAL,
u.client_ID,
f.pMonth,
f.pYear,
MIN (u.DTE),
MAX (u.DTE),
SUM (u.Price) -- or SUM(u.Quantity * u.Price)
FROM Myfilter f
JOIN usage_mgmt.usages u
ON (NVL (f.pClientID, u.client_ID) = u.client_ID
AND u.DTE >= f.FirstOfMonth
AND u.DTE < ADD_MONTHS (f.FirstOfMonth, 1))
GROUP BY u.client_ID, f.pMonth, f.pYear
HAVING SUM (CASE WHEN u.Price IS NULL THEN 1 ELSE 0 END) =
0)
RETURNING id, client_id
BULK COLLECT INTO vIDArray, vIDClientArray;
END;
编辑:
这有什么问题?问题出在SUBTOTAL内部循环中。它不会打印所有必要的行。
create or replace PROCEDURE proc_test2
(p_year IN VARCHAR2, p_month IN VARCHAR2, p_client_id IN NUMBER)
IS
--num_of_clients NUMBER;
--t_client_id NUMBER;
f_client_id NUMBER;
f_month VARCHAR2(100);
f_year VARCHAR2(100);
f_cost NUMBER;
f_min_date DATE;
f_max_date DATE;
f2_client_id NUMBER;
f2_unit_of_measure NUMBER;
f2_quantity NUMBER;
f2_cost NUMBER;
/*cursor cur_clients is
select distinct CLIENT_ID
from USAGE_MGMT.USAGES;
cursor cur_bill_total is
select u.CLIENT_ID
from USAGE_MGMT.USAGES u;*/
cursor cur_table1 is
select u.CLIENT_ID,to_char(sysdate, 'MM'), to_char(sysdate, 'YY') , SUM(u.QUANTITY*u.PRICE) AS COST, MIN(u.DTE), MAX(u.DTE)
from USAGES u
where u.CLIENT_ID=p_client_id
and to_char(u.DTE, 'MM')=p_month
and to_char(u.DTE, 'YY')=p_year
GROUP BY CLIENT_ID,to_char(sysdate, 'MM'), to_char(sysdate, 'YY')
;
cursor cur_table1_all is
select CLIENT_ID,to_char(sysdate, 'MM'), to_char(sysdate, 'YY') , SUM(u.QUANTITY*u.PRICE) AS COST, MIN(u.DTE), MAX(u.DTE)
from USAGES u
where
to_char(u.DTE, 'MM')=p_month
and to_char(u.DTE, 'YY')=p_year
GROUP BY CLIENT_ID, to_char(sysdate, 'MM'), to_char(sysdate, 'YY')
;
cursor cur_table2 is
select
u.UNIT_OF_MEASURE, SUM(u.QUANTITY),SUM(u.QUANTITY*u.PRICE) AS COST
from USAGES u
where u.CLIENT_ID=p_client_id
and to_char(u.DTE, 'MM')=p_month
and to_char(u.DTE, 'YY')=p_year
GROUP BY UNIT_OF_MEASURE
;
cursor cur_table2_all is
select
u.CLIENT_ID,u.UNIT_OF_MEASURE, SUM(u.QUANTITY),SUM(u.QUANTITY*u.PRICE) AS COST
from USAGES u
--where u.CLIENT_ID=p_client_id
where to_char(u.DTE, 'MM')=p_month
and to_char(u.DTE, 'YY')=p_year
GROUP BY CLIENT_ID,UNIT_OF_MEASURE
;
cursor cur_table3 is
select
u.TYPE_ID,MIN(u.DTE),MAX(u.DTE),SUM(u.QUANTITY),u.UNIT_OF_MEASURE,u.PRICE,SUM(u.QUANTITY*u.PRICE) AS COST
from USAGES u
where u.TYPE_ID=p_client_id
and to_char(u.DTE, 'MM')=p_month
and to_char(u.DTE, 'YY')=p_year
GROUP BY UNIT_OF_MEASURE,TYPE_ID,PRICE
;
seq_id NUMBER;
seq_id_2 NUMBER;
begin
--DBMS_OUTPUT.PUT_LINE('number of clients'||num_of_clients);
/*open cur_clients;
loop
fetch cur_clients
into t_client_id;
exit when cur_clients%notfound;*/
--INSERT INTO
if(p_client_id=0) then
open cur_table1_all;
else open cur_table1;
end if;
/*if(p_client_id=0) then
open cur_table2_all;
else open cur_table2;
end if;*/
open cur_table2;
loop
if(p_client_id=0) then
fetch cur_table1_all into f_client_id, f_month, f_year, f_cost, f_min_date, f_max_date;
exit when cur_table1_all%notfound;
else
fetch cur_table1 into f_client_id, f_month, f_year, f_cost, f_min_date, f_max_date;
exit when cur_table1%notfound;
end if;
SELECT BILL_CALC.SEQ_BILL_TOTAL.NEXTVAL into seq_id from dual;
INSERT INTO BILL_CALC.BILL_TOTAL (ID, CLIENT_ID, MONTH, YEAR, FIRST_USAGE_DATE, LAST_USAGE_DATE, COST)
VALUES(seq_id, f_client_id, f_month, f_year , f_min_date, f_max_date, f_cost );
loop
/*if(p_client_id=0) then
fetch cur_table2_all into f2_client_id,f2_unit_of_measure,f2_quantity,f2_cost;
exit when cur_table2_all%notfound;*/
--else
fetch cur_table2 into f2_unit_of_measure,f2_quantity,f2_cost;
exit when cur_table2%notfound;
--end if;
if(f2_client_id=f_client_id) then
SELECT BILL_CALC.SEQ_BILL_SUBTOTAL.NEXTVAL into seq_id_2 from dual;
INSERT INTO BILL_CALC.BILL_SUBTOTAL (ID, BILL_TOTAL_ID, UNIT_OF_MEASURE, QUANTITY,COST)
VALUES(seq_id_2, seq_id, f2_unit_of_measure, f2_quantity, f2_cost);
end if;
end loop;
--dbms_output.put_line ('Client:'||t_client_id);
end loop;
if (p_client_id=0) then
close cur_table1_all;
else
close cur_table1;
end if;
/*if (p_client_id=0) then
close cur_table2_all;
else
close cur_table2;
end if;*/
close cur_table2;
commit;
END;