2017-08-15 32 views
0

我正在使用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数据定义功能。那么当我使用这两个函数时,有什么办法可以避免重复?

或者是否有任何方法分别为第二个函数CA_Parse_CorpActnOptnDtls_fn(ev.MessageID)为LSCI_DateOfRecord和RoundingDesc建立一个临时列表?然后我可以更新表格。

任何帮助,非常感谢。

+0

可以将它们插入到一个临时表,删除重复的,并插入到真正的表? – DVT

+0

有几种方法可以解决这个问题。但他们都取决于你的意思是重复的。它只是一个重复的键值或是整行被重复?也许一个简单的小组可以解决问题。也许别的东西。 –

+0

一些示例数据在这里将会走很长的路,就像您所拥有的那些2个UDF的定义一样。这将帮助我们理解您定义为重复的内容。请告诉我们你得到什么(作为选择声明)以及你期望看到什么 – Eli

回答

0

看看错误和你的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,杰森