Способы обновления зависимой таблицы в одной транзакции MySQL?

Мне нужно обновить две таблицы внутри одной транзакции. Индивидуальные запросы выглядят примерно так:

1. INSERT INTO t1 (col1, col2) 
 VALUES (val1, val2) 
 ON DUPLICATE KEY 
 UPDATE col2 = val2;

Если приведенный выше запрос вызывает вставку, мне нужно запустить следующую инструкцию во второй таблице:

2. INSERT INTO t2 (col1, col2) 
 VALUES (val1, val2) 
 ON DUPLICATE KEY 
 UPDATE col2 = col2 + val2;

в противном случае,

3. UPDATE t2 
 SET col2 = col2 - old_val2 + val2 
 WHERE col1 = val1; 
 -- old_val2 is the value of 
 t1.col2 before it was updated

Сейчас я сначала запускаю SELECT на t1, чтобы определить, приведет ли оператор 1 к вставке или обновлению по t1. Затем я запускаю оператор 1 и один из 2 и 3 внутри транзакции. Каковы способы, которыми я могу выполнять все эти операции внутри одной транзакции?

Подход, о котором я думал, следующий:

UPDATE t2, t1 
 set t2.col2 = t2.col2 - t1.col2 
 WHERE t1.col1 = t2.col2 
 and t1.col1 = val1;
INSERT INTO t1 (col1, col2) 
VALUES (val1, val2) 
ON DUPLICATE KEY 
 UPDATE col2 = val2;
INSERT INTO t2, t1 (t2.col1, t2.col2) 
VALUES (t1.col1, t1.col2) 
ON DUPLICATE KEY 
 UPDATE t2.col2 = t2.col2 + t1.col2 
WHERE t1.col1 = t2.col2 
 and t1.col1 = val1;

К сожалению, нет многостраничного INSERT... ON DUPLICATE KEY UPDATE в MySQL 5.0. Что еще я мог сделать?

2 ответа

Хорошо, поэтому я понял это и сделал так, как мне нравится:

UPDATE t2, t1 
 SET t2.col2 = t2.col2 - t1.col2 
 WHERE t1.col1 = t2.col2 
 AND t1.col1 = val1;
INSERT INTO t1 (col1, col2) VALUES (val1, val2) 
ON DUPLICATE KEY UPDATE
 col2 = val2;
INSERT INTO t2 (col1, col2) VALUES (val1, val2) 
ON DUPLICATE KEY UPDATE
 col2 = col2 + VALUES(col2);

Третий запрос может быть переписан для ссылки на значения из t1 следующим образом:

INSERT INTO t2 (col1, col2)
 SELECT col1, col2 FROM t1 WHERE col1 = val1
ON DUPLICATE KEY UPDATE
 t2.col2 = t2.col2 + VALUES(col2);


Если вы выполняете INSERT или UPDATE, ваш клиент может получить количество строк, которые были изменены. Как это сделать зависит от вашего клиента, но для нескольких языков программирования это число возвращается вашим INSERT, если оно было успешным.

Если вы выполните INSERT...ON DUPLICATE KEY UPDATE, вы также можете получить это число, но это не совсем то, что вы ожидаете от него. Если вы вставляете/обновляете одну строку, вы получаете 1 как число строк, которые были изменены в случае INSERT и 2 в случае UPDATE, хотя есть только одна строка, которая изменилась. Вы можете использовать этот номер, чтобы решить, на какой стороне клиента будет выполняться запрос для следующего.

Не так хорошо, как одна транзакция, но по крайней мере вы избавитесь от одного SELECT.

licensed under cc by-sa 3.0 with attribution.