簡體   English   中英

ORACLE 12c唯一約束在MERGE命令中失敗,該命令與索引中的所有列匹配

[英]ORACLE 12c Unique constraint failing in MERGE command which is matching all columns from the index

我有一個匯總數據表,這些表收集不正確,並且我試圖將select的結果合並到其中,但遇到約束違規並且可能缺少明顯的東西。 表很簡單:

 CREATE TABLE "DVRA_STATS_AGG_HOURLY" 
       (    "ID" NUMBER(*,0), 
        "SHIPMENTS" NUMBER, 
        "EVENT_DATETIME" DATE, 
        "COUNTRY" VARCHAR2(2 CHAR), 
        "DATA_TYPE" VARCHAR2(3 CHAR), 
        "EVENT_TYPE" CHAR(15)
       )
    CREATE UNIQUE INDEX "DVRA_STATS_AGG_HOURLY_PK" ON "DVRA_STATS_AGG_HOURLY" ("ID")
    CREATE UNIQUE INDEX "DVRA_STATS_AGG_HOURLY_UK1" ON "DVRA_STATS_AGG_HOURLY" ("EVENT_DATETIME", "COUNTRY", "DATA_TYPE", "EVENT_TYPE")
 CREATE INDEX "DVRA_STATS_AGG_HOURLY_INDEX1" ON "DVRA_STATS_AGG_HOURLY" ("EVENT_DATETIME" DESC)

帶觸發順序和觸發

CREATE OR REPLACE EDITIONABLE TRIGGER "DVRA_STATS_AGG_HOURLY_AINC" 
BEFORE INSERT ON dvra_stats_agg_hourly 
FOR EACH ROW

BEGIN
  SELECT stats_seq.NEXTVAL
  INTO   :new.id
  FROM   dual;
END;

合並也不復雜:

MERGE INTO dvra_stats_agg_hourly stats
USING(
    SELECT COUNT(*) as SHIPMENTS, TRUNC(event_datetime,'HH24') as event_datetime,COUNTRY,data_type,event_type
FROM AUDIT 
WHERE   event_type in (<List of events>)
    and TRUNC(event_datetime,'HH24') < trunc(sysdate,'HH24')
    and audittable.event_datetime is not null
    and audittable.COUNTRY is not null
    and audittable.data_type is not null
    and audittable.event_type is not null
GROUP BY TRUNC(event_datetime,'HH24'),COUNTRY,data_type,event_type
    ) audittable 
    ON (
            audittable.event_datetime = stats.event_datetime 
        and audittable.COUNTRY = stats.COUNTRY
        and audittable.data_type = stats.data_type 
        and audittable.event_type = stats.event_type
        )
WHEN MATCHED THEN 
    UPDATE SET stats.SHIPMENTS = audittable.SHIPMENTS WHERE stats.SHIPMENTS <> audittable.SHIPMENTS
WHEN NOT MATCHED THEN 
    INSERT (SHIPMENTS,event_datetime,STATS.COUNTRY,data_type,event_type)
    VALUES (audittable.SHIPMENTS,audittable.event_datetime,audittable.COUNTRY ,audittable.data_type ,audittable.event_type)
;

我收到錯誤消息:ORA-00001:唯一約束(DVRA_MONITORING.DVRA_STATS_AGG_HOURLY_UK1)被違反

我正在與在唯一約束中使用的相同列進行匹配。 我只插入不匹配的行,並且按相同的列分組,因此這些列的唯一組合應該只有一行。

執行此操作時,我只是一個更新表,因此在運行查詢期間沒有其他會話在處理數據。

我在這里想念什么?

編輯:將DVRA_STATS_AGG_HOURLY中的數據與insert插入select中。 與此合並中使用的選擇相同。 只是一些數據尚未正確加載,因此我正在更正。

Edit2:添加的不為null

Edit3:與Alex討論后合並查詢中的更改

MERGE INTO dvra_stats_agg_hourly stats
USING(
    SELECT COUNT(*) as SHIPMENTS, TRUNC(event_datetime,'HH24') as event_datetime,COUNTRY,data_type,event_type
    FROM BCTCUSTOM.V_DVRA_AUDIT 
    WHERE   event_type in (<List of types>)
        and TRUNC(event_datetime,'HH24') < trunc(sysdate,'HH24')
        and TRUNC(event_datetime,'HH24') is not null
        and event_datetime is not null
        and COUNTRY is not null
        and data_type is not null
        and event_type is not null
    GROUP BY TRUNC(event_datetime,'HH24'),COUNTRY,data_type,event_type
    ) audittable 
    ON (
            audittable.event_datetime = stats.event_datetime 
        and ((audittable.COUNTRY is null and stats.COUNTRY is null) or audittable.COUNTRY = stats.COUNTRY)
        and ((audittable.data_type is null and stats.data_type is null) or audittable.data_type = stats.data_type)
        and ((audittable.event_type is null and stats.event_type is null) or audittable.event_type = stats.event_type)
        )
WHEN MATCHED THEN 
    UPDATE SET stats.SHIPMENTS = audittable.SHIPMENTS WHERE stats.SHIPMENTS <> audittable.SHIPMENTS
WHEN NOT MATCHED THEN 
    INSERT (SHIPMENTS,event_datetime,STATS.COUNTRY,data_type,event_type)
    VALUES (audittable.SHIPMENTS,audittable.event_datetime,audittable.COUNTRY ,audittable.data_type ,audittable.event_type)
;

如果您要在ON子句中比較的四列中的任何一列為null,則它們將與當前條件不匹配,因為null = null是未知的。

您可以添加顯式null檢查; 代替:

ON (
        audittable.event_datetime = stats.event_datetime 
    and audittable.COUNTRY = stats.COUNTRY
    and audittable.data_type = stats.data_type 
    and audittable.event_type = stats.event_type
    )

做類似的事情:

ON (
        audittable.event_datetime = stats.event_datetime 
    and ((audittable.COUNTRY is null and stats.COUNTRY is null)
       or audittable.COUNTRY = stats.COUNTRY)
    and ((audittable.data_type is null and stats.data_type is null)
       or audittable.data_type = stats.data_type)
    and ((audittable.event_type is null and stats.event_type is null)
       or audittable.event_type = stats.event_type)
    )

db <> fiddle不包含null-工作正常。

db <>帶有null的小提琴 -最初會失敗,但可以使用添加的顯式null檢查。


另一種可能是數據類型不匹配,因為您在顯示的表中使用的是CHAR(15) 如果審核表將該列定義為VARCHAR2(15)則比較也會失敗(因為“只要比較中的一個或兩個值的數據類型為VARCHAR2或NVARCHAR2Oracle就會使用未填充的比較語義” )和隱式轉換在插入期間將導致約束沖突。 在這種情況下,您可以調整CHAR值:

ON (
        audittable.event_datetime = stats.event_datetime 
    and audittable.COUNTRY = stats.COUNTRY
    and audittable.data_type = stats.data_type 
    and audittable.event_type = trim(stats.event_type)
    )

分貝<>小提琴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM