Нарушение ограничения 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, Джейсон