简体   繁体   English

Oracle MERGE:仅触发NOT MATCHED

[英]Oracle MERGE: only NOT MATCHED is triggered

Database: Oracle 数据库: Oracle

Table: 表:

CREATE TABLE TABLE_FOR_TESTS (
    d DATE,
    t NUMBER(8)
)

MERGE: 合并:

MERGE INTO TABLE_FOR_TESTS
    USING DUAL
    ON ((SELECT COUNT(*) FROM TABLE_FOR_TESTS) = 1)
    WHEN MATCHED THEN
        UPDATE SET T = T+1
    WHEN NOT MATCHED THEN         
        INSERT (D, T) VALUES (sysdate, 1)

or 要么

    ...
    ON ((SELECT T FROM TABLE_FOR_TESTS) is not null)
    ...

I will refer to the first version of MERGE, but the second one has the same effect. 我将参考MERGE的第一个版本,但是第二个版本具有相同的效果。

1) I run that MERGE for the first time 1)我第一次运行MERGE

  • result: expected (because there is no element, the ON condition is false => INSERT ) 结果: 预期的 (因为没有元素,所以ON条件为false => INSERT

2) Here I run: 2)我在这里运行:

SELECT COUNT(*) FROM TABLE_FOR_TESTS

and it's output is "1". 它的输出为“ 1”。

3) I run that MERGE for the second time 3)我第二次运行该合并

  • result: unexpected ( INSERT ), expected: UPDATE (it works only on sqlfiddle) 结果: 意外INSERT ),预期:UPDATE(仅在sqlfiddle上有效)

Why is ON condition false at the N-th run (N>1) ? 为什么在第N次运行(N> 1)时ON条件为假? ( if it was "1" as output at 2) ) (如果在输出2时为“ 1”)

(just to test: if I change the condition to be ON (1=1) before the second run, it works well: UPDATE is done) (只是测试:如果我在第二次运行之前将条件更改为ON (1=1) ,则效果很好:UPDATE已完成)

I think you have misunderstood what merge is for. 我认为您误解了合并的目的。

I would expect your table to be something like: 我希望您的桌子像这样:

CREATE TABLE TABLE_FOR_TESTS (
    d DATE,
    t NUMBER(8),
    CONSTRAINT TABLE_FOR_TESTS_PK PRIMARY KEY (d)
)

and then the merge statement could be: 然后合并语句可能是:

MERGE INTO TABLE_FOR_TESTS t
  USING (SELECT trunc(sysdate) d FROM DUAL) s
    ON (s.d = t.d)
  WHEN MATCHED THEN
    UPDATE SET t = t+1
  WHEN NOT MATCHED THEN         
    INSERT (d, t) VALUES (trunc(sysdate), 1)

where the join is on the primary key of the table and either update or insert depending on whether the record for that PK value exists. 连接在表的主键上的位置,并根据该PK值的记录是否存在而更新或插入。

This would have a maximum of one record per day and t would hold the number of executions of this statement per day (assuming no other DML on TABLE_FOR_TESTS). 每天最多有一个记录,并且t将保存每天该语句的执行次数(假设TABLE_FOR_TESTS上没有其他DML)。

Note: sysdate by itself includes a time component. 注意:sysdate本身包含一个时间组件。 trunc(sysdate) removes it and sets the time to 00:00:00. trunc(sysdate)会将其删除并将时间设置为00:00:00。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM