将多行插入到具有2列索引的表中,忽略重复项而不会导致查询失败

时间:2013-07-15 17:36:47

标签: sql-server-2008 tsql sql-insert

我有一个包含3列的关系表

formsFields

[formID] [int] NOT NULL,
[fieldGUID] [varchar](50) NOT NULL,
[position] [int] NOT NULL

formIDfieldGUID列在索引/键中具有唯一约束。

目前我正在同时插入所有关系,如:

INSERT INTO formsFields(formID, fieldGUID, position)
VALUES 
(1, '{52E9A16E-B489-4577-955F-05749AB0481B}', 0),
(1, '{52E9A16E-B489-4577-955F-05749AB0481B}', 1), 
....

使用唯一约束,数据库不允许重复,但如果我插入的任何行都是重复的,查询将失败。

他们是否可以像这样运行插件并忽略重复项?甚至可能插入临时表将其合并到真实表中?需要一点帮助为此编写查询。

1 个答案:

答案 0 :(得分:0)

这是使用临时表,聚合和合并的实现。我假设您希望保存最大位置值。

现在看一下你可能会认为你可以跳过临时表,只需使用values作为merge中的来源。虽然您可以将值用作源,但on只能有0或1个匹配项,多行将导致错误消息。

你可能认为我对索引感兴趣,但它们会加速聚合和加入。如果性能不是问题或空间是一个问题,请跳过它们。

如果您认为表格中的位置不会高于您正在接受的值,或者如果您不在乎,则可以从AND ff.position < source.pos删除MATCHED结束了较低的职位。

IF OBJECT_ID('tempdb..#formsFields2') IS NOT NULL
BEGIN
    DROP TABLE #formsFields2
END

CREATE TABLE #formsFields2 (
[formID] [int] NOT NULL,
[fieldGUID] [varchar](50) NOT NULL,
[position] [int] NOT NULL
)

CREATE NONCLUSTERED INDEX #formsFields2_IX_position
    ON #formsFields2([position])

CREATE NONCLUSTERED INDEX #formsFields2_IX_ids
    ON #formsFields2([formID], [fieldGUID])

INSERT INTO #formsFields2(formID, fieldGUID, position)
VALUES 
(1, '{52E9A16E-B489-4577-955F-05749AB0481B}', 1),
(1, '{52E9A16E-B489-4577-955F-05749AB0481B}', 2)

MERGE formsFields AS ff
USING (
    SELECT formID, fieldGUID, MAX(position)
    FROM #formsFields2
    GROUP BY formID, fieldGUID
) AS source (formID, fieldGUID, pos)
ON (ff.formID = source.formID AND ff.fieldGUID = source.fieldGUID)
WHEN MATCHED AND ff.position < source.pos THEN UPDATE SET ff.Position = source.pos
WHEN NOT MATCHED THEN INSERT VALUES (formID, fieldGUID, pos);