【问题标题】:Merge into table with composite primary key使用复合主键合并到表中
【发布时间】:2018-12-07 10:58:59
【问题描述】:

我正在尝试将一些条目插入到我的表中,并且当条目已经存在时什么也不做。我的主键包含多个列(event_timestamp、device_id、path、message_id)。

当我在 JDBC 中尝试以下语句时:

MERGE INTO events dest
                    USING ( SELECT event_timestamp, device_id, path, message_id from events) src
                    ON (dest.event_timestamp = src.event_timestamp
                    and dest.device_id = src.device_id
                    and dest.path = src.path
                    and dest.message_id = src.message_id)
                    WHEN NOT MATCHED THEN
                    INSERT (event_timestamp, device_id, path, message_id, text, direction, speed, net, gross)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)

没有插入任何内容。

使用正常的语句,例如:

INSERT (event_timestamp, device_id, path, message_id, text, direction, speed, net, gross) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)

一切都插入没有问题。

我还尝试将 select 语句更改为从 DUAL 中选择,而不是像这样的事件:

MERGE INTO events dest
                    "USING ( SELECT event_timestamp, device_id, path, message_id from DUAL) src
                    ON (dest.event_timestamp = src.event_timestamp
                    and dest.device_id = src.device_id 
                    and dest.path = src.path
                    and dest.message_id = src.message_id)
                    WHEN NOT MATCHED THEN
                    INSERT (event_timestamp, device_id, path, message_id, text, direction, speed, net, gross)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)

但后来我得到了异常:ORA-00904: invalid identifier

我该怎么做才能让它发挥作用?

【问题讨论】:

  • WHEN MATCHED THEN 试试UPDATE,这将确保匹配的记录存在与否
  • event_timestamp 是日期还是时间戳列?如果是这样,请确保插入唯一的记录。
  • @Jåcob:感谢您的评论。当我尝试对任何引用的列 ORA-38104: Columns referenced in the ON Clause cannot be updated 进行更新时,出现以下异常。 event_timestamp 是一个时间戳列。我试图通过检查复合(event_timestamp、device_id、path、message_id)来确保插入唯一记录。
  • 如果您发布“普通”SQL而不是Java中的字符串连接,那么您的SQL会更容易理解

标签: oracle sql-merge


【解决方案1】:

您要传递的新值应该是SELECT FROM dual 子句中USING 的一部分

MERGE INTO events dest USING (
     SELECT ? as event_timestamp,
            ? as device_id,
            ? as path,
            ? as message_id
     FROM dual
)
src ON (
      dest.event_timestamp = src.event_timestamp 
      AND dest.device_id = src.device_id 
      AND dest.path = src.path 
      AND dest.message_id = src.message_id
)
WHEN NOT MATCHED THEN INSERT (
     event_timestamp,
     device_id,
     path,
     message_id,
     text,
     direction,
     speed,
     net,
     gross ) VALUES (?,?,?,?,?,?,?,?,?);

也可以使用这样的普通INSERT INTO .. SELECT

INSERT INTO events (
     event_timestamp,
     device_id,
     path,
     message_id,
     text,
     direction,
     speed,
     net,
     gross ) 
SELECT ?,?,?,?,?,?,?,?,? FROM DUAL
WHERE NOT EXISTS ( select 1 from events d WHERE  
          d.event_timestamp  = ? 
      AND d.device_id        = ?
      AND d.path             = ?
      AND d.message_id       = ?
      );

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2018-11-28
    • 2017-08-06
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    相关资源
    最近更新 更多