Я новичок в MERGE
, и я уверен, что в моем коде есть какая-то ошибка.
Этот код запустится и создаст мой сценарий:
У меня есть две таблицы, одна из которых называется TempUpsert
, которая заполняется из операции SqlBulkCopy
(100 миллионов записей), и таблица Sales
, которая содержит производственные данные, которые нужно проиндексировать и использовать.
Я хочу объединить таблицу TempUpsert
с Sales
one
Я, очевидно, что-то делаю не так, потому что это не получается даже с самым маленьким примером
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 ряд)
Что я делаю не так, пожалуйста?
С благодарностью