微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

多个行上的唯一约束..如何在不停止所有操作的情况下不插入重复项

如何解决多个行上的唯一约束..如何在不停止所有操作的情况下不插入重复项

我有一个表,我试图向其中添加以下约束,以避免在插入约束列的重复项时出现重复,但是我不确定如何使它不会完全导致插入失败如果要插入多行,则重复插入尝试。

这是我要添加的约束:

BEGIN
IF NOT EXISTS (SELECT * FROM sys.tables where name = N'T_1321_PNAnnotationCommitReport')
        BEGIN
            CREATE TABLE AnnotationCommitReport (
                 [id] [INT] IDENTITY(1,1) PRIMARY KEY not null,--key
                 [progressnote_id] [INT] NOT NULL,[form_id] [INT] NOT NULL,[question_id] [INT],[question_value] [VARCHAR](max),[associatedconcept_id] [INT],[OI_create_date] [DATETIME],--SCHED_RPT_DATE
                 [crte_date] [DATETIME] DEFAULT CURRENT_TIMESTAMP,);
            --create unique constraint on indicated columns to prevent dups inserted
            ALTER TABLE AnnotationCommitReport
            ADD CONSTRAINT PN_Unique UNIQUE (progressnote_id,form_id,question_id,question_value,associatedconcept_id,OI_create_date)
        END

这是我在其中添加可以重复的行的地方:

INSERT INTO AnnotationCommitReport(progressnote_id,OI_create_date,crte_date)
        SELECT  progressnote_id,questionvalue,concept_id,create_date as OI_create_date,getdate()
        FROM FORM_QUESTION 
        WHERE
            (create_date > @LAST_RUN_DATE
            AND
            create_date <= @RUN_TO_DATE)
END --it's much more complicated than this,so I simplified for this example

如何使其不插入重复的行?有人建议使用try / catch,但我认为如果在重复行之后有要插入的行,它将防止其余部分被插入。我找到了postgresql - avoid duplicate inserts without unique constraint,但不确定是否可以使用它,也不确定他们在谈论地图,以及如何将其应用于我拥有的地图。

更新:这是最后一个插入内容的详细信息,比我最初提供的要多:

INSERT INTO dbo.AnnotationCommitReport(progressnote_id,crte_date) 
        SELECT  progressnote_id,a.form_id,fq.concept_id,a.create_date as OI_create_date,getdate()
        FROM (
            SELECT  form_id,progressnote_id,R.Q.value('@id','varchar(max)') AS questionid,R.Q.value('@value','varchar(max)') AS questionvalue,t.create_date
            FROM
                    @tableNotes t
            OUTER APPLY t.form_questions.nodes('/RESULT/QUESTIONS/QUESTION') AS R(Q)
            WHERE 
                    ISNUMERIC(R.Q.value('@id','varchar(max)')) <> 0
            ) a
        INNER JOIN [CKOLTP_DEV]..FORM_QUESTION fq ON
                   fq.form_id = a.form_id AND
                   fq.question_id  = a.questionid
        
        WHERE
            (a.create_date > @LAST_RUN_DATE
            AND
            a.create_date <= @RUN_TO_DATE)

解决方法

为什么不将您的insert编写为select语句,以使用where条件过滤出重复项。

有这种方法的示例(尽管显然不是完全相同的问题),但请参见:Avoid duplicates in INSERT INTO SELECT query in SQL Server

在您的情况下,这将涉及在AnnotationCommitReport和insert作为select之间进行联接,以避免重复。

,

如何使其不插入重复的行?

使用MERGE而不是INSERT,因此您可以检查重复项,并且仅在目标未匹配新行时插入,或在唯一索引上设置IGNORE_DUP_KEY选项。

,

这是我在@Menios的建议下完成的工作

--I created a temp table with what I intend to put in DB table
INSERT INTO @pnAnnotationCommitReport_ToBeInserted(progressnote_id,form_id,question_id,question_value,associatedconcept_id,OI_create_date,crte_date) 
        SELECT  progressnote_id,a.form_id,questionvalue,fq.concept_id,a.create_date as OI_create_date,getdate()
        FROM (
            SELECT  form_id,progressnote_id,R.Q.value('@id','varchar(max)') AS questionid,R.Q.value('@value','varchar(max)') AS questionvalue,t.create_date
            FROM
                    @tableNotes t
            OUTER APPLY t.form_questions.nodes('/RESULT/QUESTIONS/QUESTION') AS R(Q)
            WHERE 
                    ISNUMERIC(R.Q.value('@id','varchar(max)')) <> 0
            --AND 
            --      create_date > @LAST_RUN_DATE
            ) a
        INNER JOIN [CKOLTP_DEV]..FORM_QUESTION fq ON
                   fq.form_id = a.form_id AND
                   fq.question_id  = a.questionid
        
        WHERE
            (a.create_date > @LAST_RUN_DATE
            AND
            a.create_date <= @RUN_TO_DATE)
            --AND NOT EXISTS(SELECT progressnote_id,a.questionvalue,a.create_date where pn.progressnote_id=a.progressnote_id,)

--Insert into main table,only values that aren't duplicated
INSERT INTO AnnotationCommitReport(progressnote_id,crte_date) 
        SELECT 
          pni.progressnote_id,pni.form_id,pni.question_id,pni.question_value,pni.associatedconcept_id,pni.OI_create_date
         FROM @pnAnnotationCommitReport_ToBeInserted pni
         WHERE NOT EXISTS 
            (SELECT progressnote_id,crte_date 
             FROM AnnotationCommitReport pn
             WHERE 
             pni.progressnote_id=pni.progressnote_id
             AND
             pni.form_id=pn.form_id
             AND
             pni.question_id=pn.question_id
             AND
             pni.question_value=pn.question_value
             AND
             pni.associatedconcept_id=pn.associatedconcept_id
             AND
             pni.OI_create_date=pn.OI_create_date)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。