我是MERGE
的新用户,我确信我的代码中有一些错误。
此代码将运行并创建我的场景:
我有两个表,一个名为TempUpsert
的表填充SqlBulkCopy
操作(百万条记录中的100条)和一个Sales
表,其中包含生成数据被索引和使用。
我希望将TempUpsert
表与Sales
一个
我显然做错了,因为即使是最小的例子也失败了
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TempUpsert]') )
drop table TempUpsert;
CREATE TABLE [dbo].[TempUpsert](
[FirstName] [varchar](200) NOT NULL,
[LastName] [varchar](200) NOT NULL,
[Score] [int] NOT NULL
) ON [PRIMARY] ;
CREATE TABLE [dbo].[Sales](
[FullName] [varchar](200) NOT NULL,
[LastName] [varchar](200) NOT NULL,
[FirstName] [varchar](200) NOT NULL,
[lastUpdated] [date] NOT NULL,
CONSTRAINT [PK_Sales] PRIMARY KEY CLUSTERED
(
[FullName] ASC
)
---- PROC
CREATE PROCEDURE [dbo].[sp_MoveFromTempUpsert_to_Sales]
(@HashMod int)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
MERGE Sales AS trget
USING (
SELECT
--- Edit: Thanks to Mikal added DISTINCT
DISTINCT
FirstName, LastName , [Score], LastName+'.'+FirstName AS FullName
FROM TempUpsert AS ups) AS src (FirstName, LastName, [Score], FullName)
ON
(
src.[Score] = @hashMod
AND
trget.FullName=src.FullName
)
WHEN MATCHED
THEN
UPDATE SET trget.lastUpdated = GetDate()
WHEN NOT MATCHED
THEN INSERT ([FullName], [LastName], [FirstName], [lastUpdated])
VALUES (FullName, src.LastName, src.FirstName, GetDate())
OUTPUT $action, Inserted.*, Deleted.* ;
--print @@rowcount
END
GO
--- Insert dummie data
INSERT INTO TempUpsert (FirstName, LastName, Score)
VALUES ('John','Smith',2);
INSERT INTO TempUpsert (FirstName, LastName, Score)
VALUES ('John','Block',2);
INSERT INTO TempUpsert (FirstName, LastName, Score)
VALUES ('John','Smith',2); --make multiple on purpose
----- EXECUTE PROC
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[sp_MoveFromTempUpsert_to_Sales]
@HashMod = 2
SELECT 'Return Value' = @return_value
GO
返回:
(1行受影响)
(1行受影响)
(1行受影响)消息2627,级别14,状态1,过程sp_MoveFromTempUpsert_to_Sales,第12行
违反PRIMARY KEY约束'PK_Sales'。无法在对象中插入重复键 'dbo.Sales'。声明已经终止。(1行受影响)
我做错了什么?
非常感谢
答案 0 :(得分:2)
临时表中的前两行将为您提供重复的PK。违反。 Conc是PK,你用两次相同的值插入tmain + dmain。
答案 1 :(得分:1)
总结
MERGE要求其输入(使用)重复免费 Using是一个常规的SQL语句,因此您可以使用Group By,distinct和Where子句。
我的最终合并看起来像这样:
MERGE Sales AS trget
USING (
SELECT FirstName, LastName, Score, LastName + '.' + FirstName AS FullName
FROM TempUpsert AS ups
WHERE Score = @hashMod
GROUP BY FirstName, LastName, Score, LastName + '.' + FirstName
) AS src (FirstName, LastName, [Score], FullName)
ON
(
-- src.[Score] = @hashMod
--AND
trget.FullName=src.FullName
)
WHEN MATCHED
THEN
UPDATE SET trget.lastUpdated = GetDate()
WHEN NOT MATCHED
THEN INSERT ([FullName], [LastName], [FirstName], [lastUpdated])
VALUES (FullName, src.LastName, src.FirstName, GetDate())
OUTPUT $action, Inserted.*, Deleted.* ;
--print @@rowcount
END
它有效!
谢谢大家:)
答案 2 :(得分:0)
在MERING的US部分中使用的子查询中没有DISTINCT或正确的AGGREGATE函数,将有两行适合MERGE的ON部分使用的标准,这是不允许的。 (两个John.Smith)
和强>
将条件src.[Score] = @hashMod
移到子查询中,
相反,如果ON子句没有成功,例如John.Smith的得分为2,而@HashMod = 1 - 那么如果你已经在目标表中有了John.Smith的行 - 那么主键会出错约束