Upsert — SQL Server 2005

#sql #sql-server-2005 #upsert

#sql #sql-server-2005 #upsert

Вопрос:

У меня есть две таблицы:

  1. NewNotes
  2. MasterNotes

Каждый месяц NewNotes таблица обновляется новыми примечаниями как для новых, так и для существующих учетных записей. Мне нужно либо обновить существующие заметки в MasterNotes таблице, либо вставить новые заметки, если номер счета еще не указан в MasterNotes таблице.

Обе таблицы имеют три столбца: REPORT , ACCOUNT_NUMBER , NOTES .

Для обновления записи и номер счета, и отчет должны быть одинаковыми (в MasterNotes таблице могут быть два разных номера счетов с двумя разными отчетами).

Кто-нибудь может помочь с этим?

Вот мое мышление до сих пор:

 IF NOT EXISTS
(
SELECT REP, ACCOUNT_NUMBER
FROM MasterNotes
WHERE REP = (SELECT Report FROM NewNotes) AND
      ACCOUNT_NUMBER = (SELECT AccountNo FROM NewNotes)
)
INSERT INTO MasterNotes
ELSE
UPDATE
  

Я знаю, что это неверно, потому что подзапрос возвращает более одного значения, но я не уверен, как это сделать строка за строкой.

Или, может быть, что-то вроде этого?

 INSERT INTO MasterNotes
SELECT Report, AccountNo, A.Notes
FROM NewNotes A 
LEFT OUTER JOIN MasterNotes B
    ON A.Report = B.REP AND A.AccountNo = B.ACCOUNT_NUMBER
WHERE B.ACCOUNT_NUMBER IS NULL AND B.REP IS NULL
UPDATE MasterNotes
SET NOTE = B.Notes
FROM MasterNotes A, NewNotes B
WHERE A.ACCOUNT_NUMBER = B.AccountNo AND A.REP = B.Report
  

Комментарии:

1. Покажите нам, что вы уже пробовали! Мы будем рады помочь вам в решении любых проблем, но SO — это не сервис write my codez for me …. сначала вам нужно приложить некоторые усилия !

Ответ №1:

Вот несколько примеров, которые помогут вам начать работу. Я предоставил два способа выполнения обоих действий в SQL2005. Лично я предпочитаю методы объединения, но они, как было показано, немного медленнее, но я нахожу их более удобными для записи / чтения. Они находятся внутри, но закомментированы.

 DECLARE @NewNotes TABLE (REPORT VARCHAR(10), ACCOUNT_NUMBER INT, NOTES VARCHAR(50))
DECLARE @MasterNotes TABLE (REPORT VARCHAR(10), ACCOUNT_NUMBER INT, NOTES VARCHAR(50))

INSERT INTO @MasterNotes (REPORT, ACCOUNT_NUMBER, NOTES)
SELECT 'ABC', 123, 'CUSTOMER IS VERY NICE, SOMETIMES...' UNION
SELECT 'DEF', 456, 'CUSTOMER IS ANGRY'

INSERT INTO @NewNotes (REPORT, ACCOUNT_NUMBER, NOTES)
SELECT 'ABC', 123, 'CUSTOMER IS VERY NICE' UNION
SELECT 'DEF', 456, 'CUSTOMER IS ANGRY' UNION
SELECT 'GHI', 789, 'CUSTOMER WANTS CALL BACK'

UPDATE M SET NOTES = N.NOTES
FROM @MasterNotes M, @NewNotes N
WHERE M.REPORT = N.REPORT
AND M.ACCOUNT_NUMBER = N.ACCOUNT_NUMBER

/** ALTERNATE UPDATE METHOD **/
--UPDATE M SET NOTES = N.NOTES
--FROM @MasterNotes M
--JOIN @NewNotes N
--   ON M.REPORT = N.REPORT
--   AND M.ACCOUNT_NUMBER = N.ACCOUNT_NUMBER

INSERT INTO @MasterNotes (REPORT, ACCOUNT_NUMBER, NOTES)
SELECT N.REPORT, N.ACCOUNT_NUMBER, N.NOTES
FROM @NewNotes N
WHERE NOT EXISTS (SELECT ACCOUNT_NUMBER FROM @MasterNotes M WHERE M.REPORT = N.REPORT)  

/** ALTERNATE INSERT METHOD **/
--INSERT INTO @MasterNotes (REPORT, ACCOUNT_NUMBER, NOTES)
--SELECT  N.REPORT, N.ACCOUNT_NUMBER, N.NOTES
--FROM @NewNotes N
--LEFT OUTER JOIN @MasterNotes M 
--   ON N.REPORT = M.REPORT
--   AND N.ACCOUNT_NUMBER = M.ACCOUNT_NUMBER
--WHERE M.ACCOUNT_NUMBER IS NULL   

SELECT *
FROM @MasterNotes
  

ПРИМЕЧАНИЕ: если вы когда-либо обновитесь до SQL2008 , вы можете использовать MERGE функцию следующим образом:

 DECLARE @NewNotes TABLE (REPORT VARCHAR(10), ACCOUNT_NUMBER INT, NOTES VARCHAR(50))
DECLARE @MasterNotes TABLE (REPORT VARCHAR(10), ACCOUNT_NUMBER INT, NOTES VARCHAR(50))

INSERT INTO @MasterNotes (REPORT, ACCOUNT_NUMBER, NOTES)
SELECT 'ABC', 123, 'CUSTOMER IS VERY NICE, SOMETIMES...' UNION
SELECT 'DEF', 456, 'CUSTOMER IS ANGRY'

INSERT INTO @NewNotes (REPORT, ACCOUNT_NUMBER, NOTES)
SELECT 'ABC', 123, 'CUSTOMER IS VERY NICE' UNION
SELECT 'DEF', 456, 'CUSTOMER IS ANGRY' UNION
SELECT 'GHI', 789, 'CUSTOMER WANTS CALL BACK'

MERGE INTO @MasterNotes AS DST
USING (SELECT REPORT, ACCOUNT_NUMBER, NOTES FROM @NewNotes) AS SRC
    ON SRC.ACCOUNT_NUMBER = DST.ACCOUNT_NUMBER
WHEN MATCHED THEN UPDATE
    SET DST.REPORT = SRC.REPORT,
        DST.NOTES = SRC.NOTES
WHEN NOT MATCHED THEN 
    INSERT (REPORT, ACCOUNT_NUMBER, NOTES)
    VALUES (SRC.REPORT, SRC.ACCOUNT_NUMBER, SRC.NOTES);

SELECT *
FROM @MasterNotes