За последние пару дней я пытался написать хранимую процедуру в MySQL, и у меня возникли проблемы с ее работой. Надеюсь, кто-то здесь может дать мне некоторую информацию :)

Пример, который я публикую, предназначен для поставщика членства asp.Net для создания нового пользователя. Я ожидаю отправить адрес электронной почты и пароль в БД и получить int return, чтобы убедиться, что userdeatils был записан в БД.

Я использую MySQL DB 5.1 (я думаю) и пишу SQL в веб-интерфейс.

У меня есть 2 побочных вопроса, может кто-нибудь объяснить это тоже :): 1) Я использую DELIMITER, но не знаю, что он делает. 2) Я не уверен, нужно ли мне делать что-то еще, кроме как установить autocommit = 0, чтобы заставить транзакции работать, или мне вообще нужно это делать.

Я знаю, что мог бы использовать оператор IF/ELSE вместо транзакции, но хотел бы сделать это с ним, чтобы узнать, как он работает. (Я ожидаю использовать его намного позже)

Код, который я не могу заставить работать:

DELIMITER //

CREATE DEFINER=`websharp_dk`@`%` PROCEDURE `CreateUser`(
    IN _username VARCHAR(100),
    IN _Password VARCHAR(100))
    RETURNS INT

    BEGIN
    SET autocommit = 0;
    DECLARE return_value INT;

    BEGIN TRY
        START TRANSACTION
                INSERT INTO User 
                (Email
                ,Password
                ,Failed_Password_Count
                ,Creation_Date)
                VALUES
                (_username
                ,_Password
                ,0
                ,Datetime.Now())
            SET return_value = 1;
        COMMIT;
    END TRY

    BEGIN CATCH
        ROLLBACK
        SET return_value = 0;
    END CATCH

    BEGIN FINALLY
    RETURN return_value;
    END FINALLY 
    END//
DELIMITER ;

Изменить: сообщение об ошибке, которое я получаю:

1064 - У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, на предмет правильного синтаксиса для использования рядом с 'INT BEGIN SET autocommit = 0; ОБЪЯВИТЬ return_value INT; ' в строке 4

1
Jorn 16 Дек 2009 в 11:59
Возможно, вы захотите написать более осмысленное название для своего вопроса.
 – 
TK.
16 Дек 2009 в 12:08
В чем ошибка? Вам никогда не нужно оборачивать одно действие в транзакцию, поэтому в этом случае транзакция вообще ничего не делает.
 – 
Paul Creasey
16 Дек 2009 в 12:09
Изменил заголовок, чтобы лучше описать проблему.
 – 
Jorn
16 Дек 2009 в 12:13
Что должна сделать транзакция, так это установить return_value, поэтому она возвращает 0, если что-то не удается. Я знаю, что это можно было бы сделать лучше, но мне нужно получить представление о транзакциях. Я получаю сообщение об ошибке: # 1064 - у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, на предмет правильного синтаксиса для использования рядом с 'INT BEGIN SET autocommit = 0; ОБЪЯВИТЬ return_value INT; ' в строке 4
 – 
Jorn
16 Дек 2009 в 12:17

2 ответа

Чтобы получить поддержку транзакций, убедитесь, что вы используете механизм хранения InnoDB, а не MyISAM по умолчанию.

Что касается самого кода, мой первый вопрос: почему вы заключаете этот единственный запрос в транзакцию? Кроме того, какие ошибки вы видите?

1
phoebus 16 Дек 2009 в 12:10
Сейчас ищу InnoDB, спасибо. Я только что написал об ошибке выше, должен был сделать это с самого начала, извините
 – 
Jorn
16 Дек 2009 в 12:19
Спасибо за информацию о движке БД. Кажется, InnoBD достался мне по счастливой случайности :)
 – 
Jorn
16 Дек 2009 в 12:46

Разделитель переопределяет последовательность символов, которую вы используете для завершения инструкции sql. Вся процедура создания представляет собой один большой оператор, и вам нужно указать MySQL, где он чем-то заканчивается (обычно это ';'). Но поскольку у вас есть куча других операторов в «теле» (между BEGIN и END) оператора создания процедуры, все они также должны быть завершены, вам нужно переопределить разделитель, чтобы вы не заканчивали оператор создания процедуры в конце первый ';'.

Без переопределения разделителя MySQL будет думать, что оператор создания процедуры выглядит так, а затем начнет новый оператор:

CREATE DEFINER=`websharp_dk`@`%` PROCEDURE `CreateUser`(
    IN _username VARCHAR(100),
    IN _Password VARCHAR(100))
    RETURNS INT

    BEGIN
    SET autocommit = 0;

Использование DELIMITER ; в конце скрипта меняет разделитель обратно на ';' и не требуется, хотя это хорошая практика.

1
Andreas 16 Дек 2009 в 12:23