我有一个存储过程,可以从表中读取行,对每行进行一些计算,然后将结果存储在同一行中。
当我需要处理一百万行时,所有UPDATES都在填充DBC数据库,因此我想在1000行计算之后执行COMMIT。
我需要使用交易还是需要使用COMMIT? 提交工作是做什么的?
我在TERA模式下执行所有操作,版本为15.00。
这是简化我的程序的示例:
-- Creates a sample table
--DROP TABLE DM_CALIDAD.RGR_TEST_PROCEDURE;
CREATE MULTISET TABLE DM_CALIDAD.RGR_TEST_PROCEDURE AS(
SELECT T.TABLENAME AS "TABLE_NAME", 0(INTEGER) AS IND_NAME FROM DBC.TABLESV T
)WITH DATA
;
--Creates the procedure
REPLACE PROCEDURE DM_CALIDAD.SP_TEST_NAME()
BEGIN
DECLARE V_TABLE_NAME VARCHAR(256) DEFAULT NULL;
DECLARE V_CALC INTEGER;
DECLARE SQL_CURSOR1, SQL_UPDATE VARCHAR(10000) DEFAULT NULL;
DECLARE CONT INTEGER DEFAULT NULL;
DECLARE CUR_CURSOR1 CURSOR FOR PREP_CURSOR1;
SET SQL_CURSOR1 = 'SELECT TABLE_NAME FROM DM_CALIDAD.RGR_TEST_PROCEDURE';
SET CONT = 1;
PREPARE PREP_CURSOR1 FROM SQL_CURSOR1;
OPEN CUR_CURSOR1;
BEGIN TRANSACTION;
l_loop:
LOOP
FETCH CUR_CURSOR1 INTO V_TABLE_NAME;
IF (SQLCODE <> 0) THEN
LEAVE l_loop;
END IF;
SET SQL_UPDATE = 'UPDATE DM_CALIDAD.RGR_TEST_PROCEDURE SET IND_NAME = IND_NAME+1 WHERE TABLE_NAME = ''' ||V_TABLE_NAME || '''';
EXECUTE IMMEDIATE SQL_UPDATE;
-- Ends the transacion each 1000 updates
SET CONT = CONT + 1;
IF (CONT MOD 1000 = 0) THEN
END TRANSACTION;
--COMMIT WORK;
BEGIN TRANSACTION;
END IF;
END LOOP l_loop;
END TRANSACTION;
CLOSE CUR_CURSOR1;
END;
-- Calls procedure
CALL DM_CALIDAD.SP_TEST_NAME();
谢谢。
Edit1,更多详细信息。
我真正要计算的是考虑到每个城市的银行假期(或节日)和周末,两个日期之间有多少个工作日。
例如,我正在将某物从A发送到B,并且我有一个跟踪事件说它在2月1日(星期五)在A,在2月6日(下一个星期三)在B,因此对于BI,需要查询这些日期之间的所有日子都在寻找节日。
对于这个提议,我有一张桌子,桌子上有2列,分别是城市和节日。
CITY | FESTIVE
B 2019-02-02 -- For being Saturday
B 2019-02-03 -- For being Sunday
B 2019-02-04 -- For being festive at B
因此,对于每一行,我读取列 first_event 和列 last_event 并进行差值(6-1 = 5days),然后计算出B的休息日
(SELECT COUNT(*) FROM FESTIVES_TABLE WHERE CITY='B' AND FESTIVE BETWEEN DATE '2019-02-01' AND DATE '2019-02-06')
,它返回3天,然后我将它们减去5天(06天-01天= 5天,5天-3节日= 2天)。
所以劳动天数是2,然后用计算出的值更新行。
我已经检查了DBC数据库的烫发空间,它具有1962GB。
再次感谢:)
答案 0 :(得分:1)
有一种非常简单的方法来计算工作日(或假日)的天数,而无需循环/计数/等,它是基于日历表中计算出的business_day数列。在您的情况下,它稍微复杂一点,因为您需要多个日历,每个城市一个。
因此,让我们在视图中进行计算(或使用通用表表达式WITH my_cal AS SELECT ...
):
REPLACE VIEW my_cal AS
SELECT c.*,
-- running business day number
-- increases only for each business day
Sum(CASE WHEN f.festive IS NULL THEN 1 ELSE 0 end)
Over (PARTITION BY c.city
ORDER BY c.caldt
ROWS Unbounded Preceding) AS business_day_num
FROM
( -- this simply create all dates for each city
SELECT *
FROM
( -- all cities
SELECT DISTINCT city
FROM festivetable
) AS f
CROSS JOIN
( -- all dates
SELECT calendar_date AS caldt
FROM sys_calendar.CALENDAR AS c -- you should use your company's calendar instead
WHERE caldt BETWEEN DATE '2018-10-01' AND DATE '2019-02-28'
) AS c
) AS c
LEFT JOIN festivetable AS f
ON c.city = f.city
AND c.caldt = f.festive;
现在,在start_date / end_date只需两个联接并计算差异。
SELECT ...
end_cal.business_day_num - start_cal.business_day_num AS duration_in_business_days
FROM mytable
JOIN my_cal AS start_cal
ON mytable.city = start_cal.city
AND mytyble.first_event = start_cal.caldt
JOIN my_cal AS end_cal
ON mytable.city = end_cal.city
AND mytyble.first_event = end_cal.caldt
关于DBC,当您说所有UPDATES都在填充DBC数据库时,您是指《瞬态日志》吗?好吧,这可能比dbc大得多(如果系统上有可用空间)。
但是dbc的2TB彼尔姆空间非常低(除非您的系统非常小),目标表有多大,并且要更新的行百分比是什么?