Нарушение ограничения PRIMARY KEY при использовании перекрестного и внешнего применения вместе

Я использовал Microsoft SQL Server. Я хочу использовать обе функции для анализа данных, поступающих в мою таблицу. Поэтому я использую поперечное и внешнее применение вместе.

CROSS APPLY CA_Parse_CorpActnDtls_fn(MessageID) ent
outer apply CA_Parse_CorpActnOptnDtls_fn(ev.MessageID) cod

Но когда я сделал это, он пожаловался на следующую ошибку:

Нарушение ограничения PRIMARY KEY 'PK_AfterParse_CA_Events'. Невозможно вставить дубликат ключа в объект 'dbo.AfterParse_CA_Events'. Дубликат значения ключа (105818432, 37819929). Заявление было прекращено.

Весь код T-sql выглядит так:

insert into AfterParse_CA_Events (
           EventID
           ,MessageID
          ,cdtprFunction
          ,CreationDate
          ,MsgDefIdr
          ,EventType
          ,CFI
          ,EventProcessingType
          ,MndtryVlntryEvtTp
          ,RecordDate
          ,EffectiveDate
          ,DueBillRdmDate
          ,CUSIP
          ,LSCI_DateOfRecord
          ,RoundingDesc

        )

    SELECT  ent.EventID
            ,ent.MessageID
            ,ent.cdtprFunction
            ,ent.CreationDate
            ,ent.MsgDefIdr
            ,ent.EventType
            ,ent.CFI
            ,ent.EventProcessingType
            ,ent.MndtryVlntryEvtTp
            ,ent.RecordDate
            ,ent.EffectiveDate_Cmpny
            ,ent.DueBillRdmDate
            ,ent.CUSIP
            ,ROXSQL.dbo.GetNthTradeDay_fn(
            case when ent.EventProcessingType = 'DISN'
                then COALESCE (ent.ExDividendDate, ent.RecordDate)
                ELSE COALESCE(ent.EffectiveDate_Xchg, ent.EffectiveDate_Cmpny,cod.EarliestPaymentDate_Secu,cod.PaymentDate_Secu ,cod.PaymentDate_Cash)
            END,-1) AS LSCI_DateOfRecord
            ,cod.RoundingDesc


    FROM #EventsToDo ev 
    CROSS APPLY CA_Parse_CorpActnDtls_fn(MessageID) ent
    outer apply CA_Parse_CorpActnOptnDtls_fn(ev.MessageID) cod

Вы можете видеть, что мне нужна вторая функция CA_Parse_CorpActnOptnDtls_fn(ev.MessageID), потому что я хочу составить данные LSCI_DateOfRecord, используя мою пользовательскую функцию. так есть ли способ избежать дубликата, когда я использую две функции вместе?

или есть какие-либо способы построить временный список для LSCI_DateOfRecord и RoundingDesc из второй функции CA_Parse_CorpActnOptnDtls_fn(ev.MessageID) отдельно? И тогда я могу обновить таблицу.

Любая помощь с благодарностью.

1 ответ

Глядя на ошибку и ваш код SQL, это не операторы APPLY, вызывающие проблему как таковую. Дело в том, что одна или обе функции возвращают более одной строки для набора EvenID и MessageID, и именно это и является причиной нарушения PK.

Ниже приведена упрощенная демонстрация с использованием функции разделения строк ( DelimitedSplit8K)

IF OBJECT_ID('tempdb..#EventsToDo ', 'U') IS NOT NULL 
DROP TABLE #EventsToDo ;
GO

CREATE TABLE #EventsToDo (
    EventID BIGINT NOT NULL,
    MessageID BIGINT NOT NULL,
    MessageText VARCHAR(1000) NOT NULL 
    );
GO

INSERT #EventsToDo (EventID, MessageID, MessageText) VALUES
    (105818432, 37819929, 'Part 1,Part 2,Part 3,Part 4,Part 5');
GO

-----------------------------------------------------------------

-- create the AfterParse_CA_Events table with PRIMARY KEY (EvenID, MessageID)...
IF OBJECT_ID('tempdb..#AfterParse_CA_Events', 'U') IS NOT NULL 
DROP TABLE #AfterParse_CA_Events;
GO

CREATE TABLE #AfterParse_CA_Events (
    EvenID BIGINT NOT NULL,
    MessageID BIGINT NOT NULL,
    MessagePart VARCHAR(1000) NULL 
    PRIMARY KEY (EvenID, MessageID)
    );
GO

--===============================================================

-- see what happens when we try to insert the parsed message values
-- into AfterParse_CA_Events while it has a PK of (EvenID, MessageID)...
INSERT #AfterParse_CA_Events (EvenID, MessageID, MessagePart)
SELECT 
    etd.EventID, 
    etd.MessageID, 
    dsk.Item
FROM
    #EventsToDo etd
    CROSS APPLY dbo.DelimitedSplit8K(etd.MessageText, ',') dsk;
GO

--===============================================================
-- execute the code below in a separate execution
--===============================================================

-- now, let's modify the  AfterParse_CA_Events table so that we have "MessagePartID" 
-- and make that part of the PK
IF OBJECT_ID('tempdb..#AfterParse_CA_Events', 'U') IS NOT NULL 
DROP TABLE #AfterParse_CA_Events;
GO 

CREATE TABLE #AfterParse_CA_Events (
    EvenID BIGINT NOT NULL,
    MessageID BIGINT NOT NULL,
    MessagePartID INT NOT NULL,
    MessagePart VARCHAR(1000) NOT NULL 
    PRIMARY KEY (EvenID, MessageID, MessagePartID)
    );
GO

--===============================================================

-- Now let's try the insertion again...
INSERT #AfterParse_CA_Events (EvenID, MessageID, MessagePartID, MessagePart)
SELECT 
    etd.EventID, 
    etd.MessageID, 
    dsk.ItemNumber,
    dsk.Item
FROM
    #EventsToDo etd
    CROSS APPLY dbo.DelimitedSplit8K(etd.MessageText, ',') dsk;
GO

--===============================================================

-- check the inserted values...
SELECT 
    *
FROM
    #AfterParse_CA_Events apce;

HTH, Джейсон

Другие вопросы по тегам