Oracle Merge忽略重复项

时间:2015-05-06 19:59:52

标签: oracle merge

我有一个可以通过oracle数据库链接访问的表,我试图将其拉入本地数据库表,原因很简单。

MERGE INTO MEMBERSHIPS LOCAL
USING (
  SELECT DISTINCT
    REMOTE.GROUP_NAME        "GROUP_NAME",
    REMOTE.USER_ACCOUNT      "USERNAME",
    REMOTE.SOME_OTHER_COLUMN "COL3"
  FROM MEMBERSHIPS@link REMOTE
) REMOTE
ON (
  REMOTE.GROUP_NAME = LOCAL.GROUP_NAME AND
  REMOTE.USERNAME   = LOCAL.USERNAME
)
WHEN MATCHED THEN
  UPDATE SET
    LOCAL.COL3       = REMOTE.COL3
    LOCAL.UPDATED_AT = sysdate
WHEN NOT MATCHED THEN
  INSERT (ID, GROUP_NAME, USERNAME, COl3, CREATED_AT, UPDATED_AT)
  VALUES (MEMBERSHIPS_SEQ.NEXTVAL, REMOTE.GROUP_NAME, REMOTE.USERNAME, REMOTE.COl3, sysdate, sysdate)

最不幸的是,原始数据库的所有者并没有因担心数据完整性而失去多少睡眠,所以在300万行中,有71个重复,这会炸毁我的组名,用户名上的唯一索引。如果我删除唯一性约束,合并将处理,但是这些行将随后在ORA-30926: unable to get a stable set of rows in the source tables的查询执行中爆炸。

这是每天都会运行的东西,所以我需要找到一种方法来忽略重复

编辑:

我原以为不同的人会为我解决这个问题,但事实并非如此。我仍然得到重复:

SELECT DISTINCT
REMOTE.GROUP_NAME,
REMOTE.USER_ACCOUNT
COUNT(*)
FROM MEMBERSHIPS@link REMOTE
GROUP BY
REMOTE.GROUP_NAME,
REMOTE.USER_ACCOUNT
HAVING COUNT(*) > 1;

显示仍有重复的71个GROUP_NAME / USER_ACCOUNT个组合

2 个答案:

答案 0 :(得分:2)

在类似情况下,您始终可以尝试对行进行排名以避免重复,而不是DISTINCT。 在这种情况下,它会是这样的:

MERGE INTO MEMBERSHIPS LOCAL
USING (
  SELECT rank() over(partition by REMOTE.GROUP_NAME
        ,REMOTE.USER_ACCOUNT
        order by NVL(REMOTE.UPDATED_AT,REMOTE.CREATED_AT) DESC NULLS LAST) r,
    REMOTE.GROUP_NAME        "GROUP_NAME",
    REMOTE.USER_ACCOUNT      "USERNAME",
    REMOTE.SOME_OTHER_COLUMN "COL3"`
  FROM MEMBERSHIPS@link REMOTE ) REMOTE
ON (
  REMOTE.GROUP_NAME = LOCAL.GROUP_NAME 
  AND REMOTE.USERNAME   = LOCAL.USERNAME
  AND REMOTE.r = 1
)
WHEN MATCHED THEN
  UPDATE SET
    LOCAL.COL3       = REMOTE.COL3
    LOCAL.UPDATED_AT = sysdate
WHEN NOT MATCHED THEN
  INSERT (ID, GROUP_NAME, USERNAME, COl3, CREATED_AT, UPDATED_AT)
  VALUES (MEMBERSHIPS_SEQ.NEXTVAL, REMOTE.GROUP_NAME, REMOTE.USERNAME, REMOTE.COl3, sysdate, sysdate);

答案 1 :(得分:1)

我尝试使用两个本地表重现您描述的问题。通过您提供的合并,我没有源表中的重复项引起的问题(在Oracle 11.2.0.4中)。如果我从DISTINCT子句中的子查询中删除USING关键字,那么我会得到您所描述的问题 - 第一次尝试时出现约束违规,或者如果我删除则会出现第二次尝试中的ORA-30926独特的约束。

我能想到的两个解释是:(a)您在Oracle中遇到了一些错误,可能涉及远程子查询中的DISTINCT,或者(b)您实际运行的合并语句不包括{ {1}}。 (我还考虑过NULL值可能导致DISTINCT操作出现意外结果的可能性,但我无法想出会发生的方法。)

编辑: 另一个经过深思熟虑的解释 - 如果两个数据库使用不同的字符集,我想知道原始表中不同的值是否可能在传输中转换为相同的值?