如何解决多个行上的唯一约束..如何在不停止所有操作的情况下不插入重复项
我有一个表,我试图向其中添加以下约束,以避免在插入约束列的重复项时出现重复,但是我不确定如何使它不会完全导致插入失败如果要插入多行,则重复插入尝试。
这是我要添加的约束:
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 举报,一经查实,本站将立刻删除。