您可以使用复合触发器来整理所有插入和更新,然后发出一个 MERGE 语句(而不是为每个更改的行执行一个 MERGE)。
例如,如果您的表 Y 可以包含多个日期的数据:
CREATE TABLE y (
code INT,
col1 INT,
col2 INT,
dt DATE,
PRIMARY KEY ( code, dt )
);
还有应该包含最新日期数据的表X:
CREATE TABLE x (
code INT PRIMARY KEY,
col1 INT,
col2 INT,
dt DATE
);
并希望保持X 更新(但不想将其创建为VIEW 或MATERIALIZED VIEW 并且不会去UPDATE DT 表中的DT 列Y)然后你可以使用复合触发器:
CREATE TRIGGER log_y_changes_to_x
FOR INSERT OR UPDATE ON y
COMPOUND TRIGGER
y_data y_table := y_table();
AFTER EACH ROW
IS
BEGIN
y_data.EXTEND(1);
y_data(y_data.COUNT) := y_object( :NEW.code, :NEW.col1, :NEW.col2, :NEW.dt );
END AFTER EACH ROW;
AFTER STATEMENT
IS
BEGIN
MERGE INTO x
USING (
SELECT code,
col1,
col2,
dt
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY code ORDER BY dt DESC ) rn
FROM TABLE(y_data) t
)
WHERE rn = 1
) y
ON ( y.code = x.code )
WHEN MATCHED THEN
UPDATE
SET col1 = y.col1,
col2 = y.col2,
dt = y.dt
WHERE y.dt >= x.dt
WHEN NOT MATCHED THEN
INSERT ( code, col1, col2, dt )
VALUES ( y.code, y.col1, y.col2, y.dt );
END AFTER STATEMENT;
END;
/
并且有类型:
CREATE TYPE y_object IS OBJECT (
code INT,
col1 INT,
col2 INT,
dt DATE
);
CREATE TYPE y_table IS TABLE OF y_object;
然后你插入数据:
INSERT INTO y ( code, col1, col2, dt )
SELECT 1, 0, 2, DATE '2020-01-01' FROM DUAL UNION ALL
SELECT 2, 1, 0, DATE '2020-01-01' FROM DUAL UNION ALL
SELECT 2, 0, 3, DATE '2020-01-02' FROM DUAL UNION ALL
SELECT 3, 3, 3, DATE '2020-01-01' FROM DUAL;
那么表X包含:
代码 | COL1 | COL2 | DT
---: | ---: | ---: | :-----------------
2 | 0 | 3 | 2020-01-02 00:00:00
3 | 3 | 3 | 2020-01-01 00:00:00
1 | 0 | 2 | 2020-01-01 00:00:00
而且,如果您更新数据:
UPDATE y
SET col1 = col1 + 3
WHERE code <= 2
AND dt = DATE '2020-01-01';
然后表X 包含*(注意:代码2 行未更新,因为它不是最新的行):
代码 | COL1 | COL2 | DT
---: | ---: | ---: | :-----------------
2 | 0 | 3 | 2020-01-02 00:00:00
3 | 3 | 3 | 2020-01-01 00:00:00
1 | 3 | 2 | 2020-01-01 00:00:00
还有:
INSERT INTO y ( code, col1, col2, dt )
SELECT 3, 5, 5, DATE '2020-01-05' FROM DUAL;
然后X 包含
代码 | COL1 | COL2 | DT
---: | ---: | ---: | :-----------------
2 | 0 | 3 | 2020-01-02 00:00:00
3 | 5 | 5 | 2020-01-05 00:00:00
1 | 3 | 2 | 2020-01-01 00:00:00
还有:
INSERT INTO y ( code, col1, col2, dt )
SELECT 3, 4, 4, DATE '2020-01-04' FROM DUAL;
然后X 不变,因为该行比前一行旧。
db小提琴here