Есть ли эквивалент для ошибки @@ SQL Server в MySQL? - PullRequest
3 голосов
/ 16 февраля 2009

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

BEGIN TRANSACTION
    UPDATE table_x SET col_y = 'some_value'
    .
    .
    .
IF (@@error <> 0)
BEGIN
    ROLLBACK
END
ELSE
BEGIN
    COMMIT
END

Вышеуказанное должно работать в SQL Server, но мне нужно это для работы с базой данных MySQL.

EDIT: К сожалению, существует более 1 оператора для выполнения. Да, я знаю, что нет необходимости заключать в транзакцию ни одного запроса.

Ответы [ 3 ]

1 голос
/ 16 февраля 2009
CREATE PROCEDURE prc_test()
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    ROLLBACK;
  END;
  START TRANSACTION;
    INSERT
    INTO t_test VALUES ('test', 'test');
    INSERT
    INTO no_such_table
    VALUES ('no');
  COMMIT;
END;

CALL prc_test();

SELECT *
FROM t_test;

0 rows fetched.
0 голосов
/ 16 февраля 2009
BEGIN;
UPDATE foo SET bar = 3;
UPDATE bar SET thing = 5;
COMMIT;

В случае ошибки вся транзакция будет автоматически откатана. Вам действительно нужно выполнить ROLLBACK, только если что-то в вашем приложении указывает на необходимость отката.

<ч />

Возможно обрабатывать ошибки явно в рамках процедур или составных операторов в MySQL, но я бы не рекомендовал идти по этому пути. См. Эту статью с практическими рекомендациями и документы для DECLARE HANDLER . Вам также придется найти конкретный код ошибки, который вы хотите обработать , или вы можете использовать общее условие SQLEXCEPTION. Вы также захотите просмотреть составные операторы и , определяющие хранимые программы .

В любом случае, основываясь на документах, вы могли бы сделать что-то вроде запроса ниже, но, честно говоря, это не сделало бы ничего, кроме моего предыдущего ответа выше. Это также даст вам очень странные взгляды от любого, кто использует MySQL (включая меня).

BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
  START TRANSACTION;
    UPDATE foo SET bar = 3;
    UPDATE bar SET thing = 5;
  COMMIT;
END;
<ч />

Старый ответ:

Если вы выполняете один запрос, это не имеет смысла. Просто выполните запрос; если произойдет ошибка, ничего не произойдет - ваша транзакция автоматически откатится.

Причина в том, что по умолчанию все отдельные запросы заключаются в «скрытую» транзакцию, называемую режимом «автоматической фиксации» в MySQL. Типичная альтернатива - явное использование транзакций - как только вы выполняете «BEGIN», вы начинаете транзакцию. Как только вы нажмете COMMIT или ROLLBACK, вы вернетесь в режим автоматической фиксации.

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

Наконец, можно полностью отключить это поведение, и тогда вы должны всегда использовать транзакции явно. Я полагаю, что «НАЧАЛО» подразумевается с момента вашей последней фиксации или отката, но вы должны либо УДАЛИТЬ, либо ОТКЛЮЧИТЬ любые выполненные запросы.

См. Модель транзакций InnoDB в руководстве MySQL для получения дополнительной информации.

0 голосов
/ 16 февраля 2009

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

Из Документы MySQL :

По умолчанию MySQL начинает сеанс за каждое новое соединение с режим автоматической фиксации включен, поэтому MySQL делает коммит после каждого оператора SQL, если это утверждение не вернуло ошибка. Если заявление возвращает ошибка, фиксация или откат зависит от ошибки. Смотрите раздел 13.6.13, «Обработка ошибок InnoDB».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...