2016-04-21 79 views
2

這是XML我:T-SQL MERGE語句更新時,條件匹配的新插入的記錄

<?xml version="1.0" encoding="UTF-8"?> 
<Data> 
    <Record> 
     <ServerId>1</ServerId> 
     <CompanyId>1</CompanyId> 
     <InstanceId>2</InstanceId> 
     <TemplateId>23</TemplateId> 
     <ContactId>11052</ContactId> 
     <RecordId>11462</RecordId> 
     <TaskId>677</TaskId> 
     <EntryDate>2016-04-21 14:17:02:813</EntryDate> 
     <EntryKey>key_test_1</EntryKey> 
     <EntryValue>value_test_1</EntryValue> 
    </Record> 
    <Record> 
     <ServerId>1</ServerId> 
     <CompanyId>1</CompanyId> 
     <InstanceId>2</InstanceId> 
     <TemplateId>23</TemplateId> 
     <ContactId>11052</ContactId> 
     <RecordId>11462</RecordId> 
     <TaskId>677</TaskId> 
     <EntryDate>2016-04-21 14:17:02:873</EntryDate> 
     <EntryKey>key_test_2</EntryKey> 
     <EntryValue>value_test_2</EntryValue> 
    </Record> 
    <Record> 
     <ServerId>1</ServerId> 
     <CompanyId>1</CompanyId> 
     <InstanceId>2</InstanceId> 
     <TemplateId>23</TemplateId> 
     <ContactId>11052</ContactId> 
     <RecordId>11462</RecordId> 
     <TaskId>677</TaskId> 
     <EntryDate>2016-04-21 14:17:02:935</EntryDate> 
     <EntryKey>key_test_1</EntryKey> 
     <EntryValue>value_test_3</EntryValue> 
    </Record> 
</Data> 

,這是插入或MERGE語句更新此數據爲單個表:

merge WRF_REPOSITORY_CUSTOM_DATA rep 
using (select 
     entity.value('ServerId[1]', 'int') as ServerId, 
     entity.value('CompanyId[1]', 'int') as CompanyId, 
     entity.value('InstanceId[1]', 'int') as InstanceId, 
     entity.value('TemplateId[1]', 'int') as TemplateId, 
     entity.value('ContactId[1]', 'bigint') as ContactId, 
     entity.value('RecordId[1]', 'bigint') as RecordId, 
     entity.value('TaskId[1]', 'bigint') as TaskId, 
     entity.value('EntryDate[1]', 'datetime') as EntryDate, 
     entity.value('EntryKey[1]', 'varchar(max)') as EntryKey, 
     entity.value('EntryValue[1]', 'varchar(max)') as EntryValue 
     from @xmlInsertOrReplace.nodes('/Data/Record') as T(entity)) as dat 
on 
    rep.ServerId = dat.ServerId and 
    rep.CompanyId = dat.CompanyId and 
    rep.InstanceId = dat.InstanceId and 
    rep.TemplateId = dat.TemplateId and 
    rep.ContactId = dat.ContactId and 
    rep.RecordId = dat.RecordId and 
    rep.EntryKey = dat.EntryKey 
when MATCHED then update set 
    rep.TaskId = dat.TaskId, 
    rep.EntryDate = dat.EntryDate, 
    rep.EntryValue = dat.EntryValue 
when NOT MATCHED then 
    insert (ServerId, CompanyId, InstanceId, TemplateId, ContactId, RecordId, TaskId, EntryDate, EntryKey, EntryValue) 
    values (dat.ServerId, dat.CompanyId, dat.InstanceId, dat.TemplateId, dat.ContactId, dat.RecordId, dat.TaskId, dat.EntryDate, dat.EntryKey, dat.EntryValue); 

當表中沒有記錄時,我期望的是第一個xml記錄將被插入,第二個xml記錄將被插入,第三個xml記錄將更新第一個表記錄,因爲它與條件匹配。實際發生的是我得到3插入,而不是2插入和1更新。

結果截圖:enter image description here

有沒有辦法迫使MERGE語句做COMMIT或東西每次插入或更新後?我不想將xml記錄分組或選擇最大/最後一個。

UPDATE:

我用類似於第一個多一個合併的行動。唯一的區別是這個連接值。

when MATCHED then update set 
    rep.TaskId = dat.TaskId, 
    rep.EntryDate = dat.EntryDate, 
    rep.EntryValue = case len(isnull(rep.EntryValue, '')) when 0 then dat.EntryValue else rep.EntryValue + ';' + dat.EntryValue end 

和預期的結果應該是:

key_test_1 | value_test_1;value_test_3 
key_test_2 | value_test_2 
+4

號MERGE是一個單一的陳述。如果你想先插入然後更新,你需要使用兩個單獨的語句。 –

+0

@肖恩蘭格是正確的。 MERGE語句將現有表中的數據與解析的XML數據中的數據進行比較。 – Steven

+3

*「我不想分組xml記錄或選擇最大/最後一個。」* - 爲什麼不?這似乎是解決方案,爲什麼要插入第一個記錄,如果所有的字段都會被寫入第三條記錄,那麼爲什麼呢? – GarethD

回答

2

你可以試試這個:

使用ROW_NUMBER找到最當前記錄在您的XML和忽略前輩之一,這將無論如何都會被覆蓋...

WITH shreddedXML AS 
(
    select 
     entity.value('ServerId[1]', 'int') as ServerId, 
     entity.value('CompanyId[1]', 'int') as CompanyId, 
     entity.value('InstanceId[1]', 'int') as InstanceId, 
     entity.value('TemplateId[1]', 'int') as TemplateId, 
     entity.value('ContactId[1]', 'bigint') as ContactId, 
     entity.value('RecordId[1]', 'bigint') as RecordId, 
     entity.value('TaskId[1]', 'bigint') as TaskId, 
     entity.value('EntryDate[1]', 'datetime') as EntryDate, 
     entity.value('EntryKey[1]', 'varchar(max)') as EntryKey, 
     entity.value('EntryValue[1]', 'varchar(max)') as EntryValue 
    from @xmlInsertOrReplace.nodes('/Data/Record') as T(entity) 
) 
,SearchForMostActualRows AS 
(
    SELECT ROW_NUMBER() OVER(PARTITION BY ServerId,CompanyId,InstanceId,TemplateId,ContactId,RecordId,EntryKey ORDER BY EntryDate DESC) AS Nr 
      ,* 
    FROM shreddedXML 
) 
SELECT * 
FROM SearchForMostActualRows 
WHERE Nr=1 

現在請做您的MERGE與此...

+0

問題是我不能忽視任何記錄。我會用原因更新我的問題。 – HABJAN

+0

@HABJAN我剛剛讀了原因。只需將我的查詢更改爲'SELECT * INTO#tempTable'。在接下來的步驟中,您使用'SELECT * FROM #tempTable WHERE Nr = 1'來執行'MERGE',然後在'SELECT * FROM #tempTable WHERE Nr> 1'處做任何事情' – Shnugo

+0

即使這樣也解決不了我問題,它指出我正確的方向。謝謝。 – HABJAN