2016-05-16 3 views
0

просмотра на различных примерах о том, как создать «хороший» UPSERT заявление shown here, я создал следующий код (я изменил имена столбцов):SQL Server: UPSERT транзакция не доходя вставки

BEGIN TRANSACTION 

IF EXISTS (SELECT * 
      FROM Table1 WITH (UPDLOCK, SERIALIZABLE), Table2 
      WHERE Table1.Data3 = Table2.data3) 
BEGIN 
    UPDATE Table1 
    SET Table1.someColumn = Table2.someColumn, 
     Table1.DateData2 = GETDATE() 
    FROM Table1 
    INNER JOIN Table2 ON Table1.Data3 = Table2.data3 
END 
ELSE 
BEGIN 
    INSERT INTO Table1 (DataComment, Data1, Data2, Data3, Data4, DateData1, DateData2) 
     SELECT 
      'some comment', data1, data2, data3, data4, GETDATE(), GETDATE() 
     FROM 
      Table2 
END 

COMMIT TRANSACTION 

Мои проблема в том, что она никогда не делает часть INSERT. Только INSERT отлично работает. Текущий скрипт выполняет только часть обновления.

У меня есть идея, что вставка только хороша, если она может вставить все данные, которые она находит (из-за запроса выбора)? Иначе это не сработает. Если да, то как я могу его улучшить?

Я также прочитал о статье MERGE и хотел бы избежать этого.

// EDIT:

осла несколько образцов, найденных в Интернете, и объяснено здесь, я вновь сделали мою логику выглядит следующим образом:

BEGIN TRANSACTION 
    BEGIN 
     UPDATE table1 
     SET something 
     WHERE condition is met 

     UPDATE table2 
     SET helpColumn = 'DONE' 
     WHERE condition is met 
    END 
    BEGIN 
     INSERT INTO table1(data) 
     SELECT data 
     FROM table2 
     WHERE helpColumn != 'DONE' 
    END 
COMMIT TRANSACTION 

При попытке других решений, то INSERT обычно терпели неудачу или длились долго (на нескольких таблицах я могу принять это, но не очень хорошо, если вы планируете перенести целые данные из одной базы данных в другую базу данных).

Возможно, это не лучшее решение. Но на данный момент это работает, любые комментарии?

+1

Вы в настоящее время проверить, если EXISTS возвращает любую строку, но нет никакой корреляции с фактическим UPDATE. Почему вы не хотите использовать MERGE, именно поэтому он был реализован? – dnoeth

+2

ваш существующий запрос всегда возвращает true, когда есть *** какая-либо *** строка, которая успешно соединяется между 'table1' и' table2' - вам нужно сделать это на основе ключевой информации, которую вы проверяете снова (как пример) – Kritner

+0

Насколько я читал, у MERGE есть свои недостатки, и, как я вижу, у меня гораздо больше контроля над данными, когда я делаю пользовательские UPDATE, INSERTS. – Asko

ответ

0

Вместо

if (something) 
update query 
else 
insert query 

Структура логика, как это:

update yourTable 
etc 
where some condition is met 

insert into yourTable 
etc 
select etc 
where some condition is met. 
+0

Кажется опасным - потенциально одна заданная строка, соответствующая условию, будет * первой * обновляться, а затем на втором шаге * вставлена ​​* тоже?!?!?!? Не похоже, что ищет OP ..... –

+0

Два условия не обязательно должны быть одинаковыми. –

+0

Я повторил свою логику с чем-то подобным (вы можете видеть это на исходном посту). Я попытался внедрить INSERT, где условия контролировались несколькими таблицами, что делает INSERT очень медленным (от нескольких секунд до нескольких минут медленнее). Поэтому, чтобы исправить это, я также обновляю строки таблицы данных temp со статусом для INSERT, чтобы этого избежать. Не уверен, если это лучший подход. – Asko

0

Вы не можете проверить это в целом, как вы делаете. Вы должны проверить каждый ID из Таблицы 2, если он существует в Таблице 1 или нет. Если он существует, обновите таблицу 1, а затем вставьте в таблицу 1. Это можно сделать следующим образом.

Мы будем перебирать в Таблице 2 для каждого идентификатора с помощью курсоров в SQL,

DECLARE @ID int 
DECLARE mycursor CURSOR 
FOR 
SELECT ID FROM Table2 FORWARD_ONLY --Any Unique Column 

OPEN mycursor 
FETCH NEXT FROM mycursor 
INTO @ID 

WHILE @@FETCH_STATUS = 0 
BEGIN 

IF EXISTS (SELECT 1 FROM Table1 WHERE ID = @ID) 
    UPDATE t1 SET t1.data= T2.data --And whatever else you want to update 
    FROM 
    Table1 t1 
    INNER JOIN 
    Table2 t2 
    ON t1.ID = t2.ID --Joining column 
    WHERE t1.id = @ID 
ELSE 
    INSERT INTO Table1 
    SELECT * FROM Table2 WHERE ID = @ID 

FETCH NEXT FROM mycursor 
INTO @ID 
END 
CLOSE mycursor 
DEALLOCATE mycursor 
+0

Может ли объявление @ID быть текстовым значением? Или это все время? – Asko

+0

Это может быть любой тип данных. Просто объявите переменную и введите значение столбца в курсор.Оба должны иметь одинаковый тип данных, то есть он. –

Смежные вопросы