MERGE UPSERT在不匹配时不起作用

时间:2018-01-15 17:33:35

标签: sql oracle csv

ABC_TABLE根据UPDATED_TS列保存历史数据。 要求是从CSV文件加载数据,条件如下:

  1. 根据UPDATED_TS获取最新的EMPLOYEE_NAME(在USING条件中查询)
  2. 在ON状态检查中,如果CSV文件中的EMPLOYEE_NAME与USING查询中提取的EMPLOYEE_NAME不匹配,则应插入新行
  3. 如果CSV文件中存在新的TABLE_ID且ABC_TABLE中不存在TABLE_ID,则应插入新记录
  4. 执行以下查询时,不会为新的TABLE_ID插入行

      MERGE INTO ABC_TABLE T
      USING (SELECT EMPLOYEE_NAME
               FROM ABC_TABLE
              WHERE TABLE_ID = ?
                AND UPDATED_TS =
                    (SELECT MAX(UPDATED_TS) FROM ABC_TABLE WHERE TABLE_ID = ?)) S
      ON ((S.EMPLOYEE_NAME IS NULL AND ? IS NULL) OR ? = S.EMPLOYEE_NAME )
      WHEN NOT MATCHED THEN
        INSERT
    

    / * 在这里插入声明 * /

    非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

The merge documentation说:

  

使用ON子句指定MERGE操作更新或插入的条件。对于搜索条件为true的目标表中的每一行,Oracle数据库使用源表中的相应数据更新该行。如果任何行的条件不为真,则数据库将根据相应的源表行插入目标表。

对于匹配和不匹配,在源表(本例中为S子查询)中必须有一行才能发生任何事情。如果传入的值不存在,则子查询不会找到任何行,因此源表为空,因此没有任何反应。

您可以在子查询中添加聚合函数调用,以便它始终找到某些内容,并使用它(例如,找到的记录的数量)来确定它是否匹配;类似的东西:

  MERGE INTO ABC_TABLE T
  USING (SELECT :table_id AS TABLE_ID, :employee_name AS EMPLOYEE_NAME, count(*) AS FOUND
           FROM ABC_TABLE
          WHERE TABLE_ID = :table_id
            AND ((EMPLOYEE_NAME IS NULL AND :employee_name IS NULL)
                    OR EMPLOYEE_NAME = :employee_name)
            AND UPDATED_TS =
                (SELECT MAX(UPDATED_TS) FROM ABC_TABLE WHERE TABLE_ID = :table_id)) S
  ON (S.FOUND > 0)
  WHEN NOT MATCHED THEN
    INSERT (table_id, updated_ts, employee_name)
    VALUES (S.TABLE_ID, systimestamp, S.EMPLOYEE_NAME)

但是,由于您只是插入而且从不更新,为什么不只使用insert

 INSERT INTO ABC_TABLE T (table_id, updated_ts, employee_name)
 SELECT :table_id, systimestamp, :employee_name
   FROM DUAL
  WHERE NOT EXISTS (
         SELECT null
           FROM ABC_TABLE T2
          WHERE T2.TABLE_ID = :table_id
            AND ((T2.EMPLOYEE_NAME IS NULL AND :employee_name IS NULL)
                    OR T2.EMPLOYEE_NAME = :employee_name)
            AND UPDATED_TS =
                (SELECT MAX(UPDATED_TS) FROM ABC_TABLE WHERE TABLE_ID = :table_id)
        )

我不确定你是否真的希望UPDATED_TS检查这两种情况。