2017-04-17 145 views
0

我有一个表如下:违反PRIMARY KEY约束,无法插入重复键(MS SQL Server)的

|Bookname|BDate|Description 

和BOOKNAME是我的主键 我需要经常读取一个文件来更新我的表。我已经writen存储过程来更新如下文件:

Create PROCEDURE [dbo].[UpdateMyTable] 
    -- Add the parameters for the stored procedure here 
    @SourceTable AS DVTable READONLY 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 
    MERGE dbo.MyTarget AS T 
    USING @SourceTable AS S ON (T.BookName=S.BookName) 
    WHEN NOT MATCHED BY Target 
    THEN INSERT(BookName,BDate,Description) 
    VALUES(S.BookName,S.BDate,S.Description) 
    WHEN MATCHED 
    THEN UPDATE SET T.BookName=S.BookName,T.BDate=S.BDate,T.Description=S.Description; 

END 

还有就是里面的文字文件的一些记录重复了两次问题,因此合并功能,插入文件,在第一和第二次抛出异常:[违反PRIMARY KEY约束]

我想知道是否有任何方法可以设置MERGE忽略它,如果再次找到Bookname。

+0

我不知道这是否会解决,但在'WHEN MATCHED'可以从'SET'中删除'T.BookName = S.BookName',因为这两个值已经是相同的 –

+0

是否有可能存在多个同名但日期不同的书?如果是这样,你可以尝试创建一个复合主键(名字,日期)。 – Coder1991

+0

不是,在我的情况下,我们不能有两个不同的同名书,这是源文件中的错误,我应该忽略它。 –

回答

1

如果您source table有两行具有相同BookName中不存在Target table,你可以使用CTE这样

;WITH temp AS 
(
    SELECT st.* , 
      row_number() over(PARTITION BY st.BookName ORDER BY BookDate desc) as Rn 
    FROM @SourceTable st 
) 
MERGE dbo.MyTarget AS T 
USING (SELECT * FROM temp t WHERE Rn = 1) AS S ON (T.BookName=S.BookName) 
............ 
2

合并之前,请尝试从基于BDate的表@SourceTable中删除重复的记录。以下查询将删除预订日期较短的书名,并保留该书的最高预订日期,以便您可以拥有唯一的BookName。

;with cte (BookName,BDate,Description,RowNum)AS 
(

Select BookName,BDate,Description,Row_number() over(partition by BookName order by BDate desc) 
from @SourceTable 
) 
delete from cte where rownum>1 
+0

你的回答是部分正确的,唯一的问题是从cte删除后,CTE会消失。谢谢 –

相关问题