Mysql 查询中回滚事务

问题描述 投票:0回答:1
DELIMITER ;;
CREATE DEFINER=root@localhost PROCEDURE ExecuteDataFill(IN p_internalCompanyId INT)
BEGIN
    DECLARE u_cursor CURSOR FOR
        SELECT name, address, area, pincode, city, state, state_code, country,
               pan_number, gst_number, bank_name, account_number, ifsc_code,
               phone_number, role
        FROM user_data;

    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        DECLARE p_name VARCHAR(225);
        DECLARE p_address VARCHAR(225);
        DECLARE p_area VARCHAR(50);
        DECLARE p_pincode VARCHAR(10);
        DECLARE p_city VARCHAR(20);
        DECLARE p_state VARCHAR(20);
        DECLARE p_state_code VARCHAR(10);
        DECLARE p_tin VARCHAR(10);
        DECLARE p_country VARCHAR(20);
        DECLARE p_pan_number VARCHAR(20);
        DECLARE p_gst_number VARCHAR(20);
        DECLARE p_bank_name VARCHAR(20);
        DECLARE p_account_number VARCHAR(20);
        DECLARE p_ifsc_code VARCHAR(20);
        DECLARE p_phone_number VARCHAR(20);
        DECLARE p_latest_org_external_id VARCHAR(50);
        DECLARE p_role VARCHAR(10);
        DECLARE done INT DEFAULT 0;
        DECLARE p_returned_sqlstate CHAR(5) DEFAULT '00000';
        DECLARE p_message_text TEXT DEFAULT '';
        DECLARE p_mysql_errno INT DEFAULT 0;

        GET DIAGNOSTICS CONDITION 1
            p_returned_sqlstate = RETURNED_SQLSTATE,
            p_message_text = MESSAGE_TEXT,
            p_mysql_errno = MYSQL_ERRNO;

        -- Log the error
        SELECT CONCAT('Error: ', p_returned_sqlstate, ', Message: ', p_message_text, ', MySQL Error: ', p_mysql_errno) AS Error_Message;

        -- Rollback the transaction
        ROLLBACK;

        -- Return the error details
        SELECT
            p_returned_sqlstate AS RETURNED_SQLSTATE,
            p_message_text AS MESSAGE_TEXT,
            p_mysql_errno AS MYSQL_ERRNO;
    END;

    -- Start the transaction
    START TRANSACTION;
    OPEN u_cursor;

    read_loop: LOOP
        -- Fetch the next row
FETCH u_cursor INTO p_name, p_address, p_area, p_pincode, p_city, p_state,p_state_code,p_country, p_pan_number, p_gst_number, p_bank_name, p_account_number,p_ifsc_code, p_phone_number, p_role;

        -- Exit the loop if no more rows
        IF done = 1 THEN
            LEAVE read_loop;
        END IF;

        BEGIN
            -- Insert into users table
            INSERT INTO users (username, name, whatsapp_number, created_by, updated_by, code, created_at, updated_at)
            VALUES (p_phone_number, p_name, p_phone_number, p_internalCompanyId, p_internalCompanyId, '', current_timestamp, current_timestamp);

            -- Insert into procedure_log
            INSERT INTO procedure_log (log_message) VALUES ('Inserted user: ' || p_name);
        END;

    END LOOP read_loop;

    CLOSE u_cursor;
    COMMIT;
END;;
DELIMITER ;

此存储过程会将数据插入到 SQL users 表中。

如果游标中的任何一个插入查询中断,我正在尝试回滚所有插入查询?

我尝试了一些其他选项来回滚所有事务,但如果遇到 mysql 错误,它不会回滚整个事务。

现在,我的问题是:

  • 这将如何影响循环内调用回滚事务的数据?
  • 它会再次读取所有行并将其发送到服务器进行插入还是只会读取执行过程中失败的行?

我需要一些建议。谢谢

mysql stored-procedures transactions rollback
1个回答
0
投票

您当前的设置有一些问题,主要是游标处理和 EXIT HANDLER 中 DECLARE 的使用,以及使用 CONCAT 函数进行字符串连接。 以下查询可能会解决该问题。

DELIMITER ;;

CREATE DEFINER=root@localhost PROCEDURE ExecuteDataFill(IN p_internalCompanyId INT)
BEGIN
    DECLARE done INT DEFAULT 0;

    DECLARE p_name VARCHAR(225);
    DECLARE p_address VARCHAR(225);
    DECLARE p_area VARCHAR(50);
    DECLARE p_pincode VARCHAR(10);
    DECLARE p_city VARCHAR(20);
    DECLARE p_state VARCHAR(20);
    DECLARE p_state_code VARCHAR(10);
    DECLARE p_country VARCHAR(20);
    DECLARE p_pan_number VARCHAR(20);
    DECLARE p_gst_number VARCHAR(20);
    DECLARE p_bank_name VARCHAR(20);
    DECLARE p_account_number VARCHAR(20);
    DECLARE p_ifsc_code VARCHAR(20);
    DECLARE p_phone_number VARCHAR(20);
    DECLARE p_role VARCHAR(10);

    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        DECLARE p_returned_sqlstate CHAR(5) DEFAULT '00000';
        DECLARE p_message_text TEXT DEFAULT '';
        DECLARE p_mysql_errno INT DEFAULT 0;

        GET DIAGNOSTICS CONDITION 1
            p_returned_sqlstate = RETURNED_SQLSTATE,
            p_message_text = MESSAGE_TEXT,
            p_mysql_errno = MYSQL_ERRNO;

        -- Log the error
        SELECT CONCAT('Error: ', p_returned_sqlstate, ', Message: ', p_message_text, ', MySQL Error: ', p_mysql_errno) AS Error_Message;

        -- Rollback the transaction
        ROLLBACK;
    END;

    -- Start the transaction
    START TRANSACTION;

    -- Declare the cursor
    DECLARE u_cursor CURSOR FOR
        SELECT name, address, area, pincode, city, state, state_code, country,
               pan_number, gst_number, bank_name, account_number, ifsc_code,
               phone_number, role
        FROM user_data;

    -- Declare the NOT FOUND handler
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    -- Open the cursor
    OPEN u_cursor;

    -- Read the data from the cursor
    read_loop: LOOP
        FETCH u_cursor INTO p_name, p_address, p_area, p_pincode, p_city, p_state, p_state_code, p_country, p_pan_number, p_gst_number, p_bank_name, p_account_number, p_ifsc_code, p_phone_number, p_role;

        -- Exit the loop if no more rows
        IF done = 1 THEN
            LEAVE read_loop;
        END IF;

        BEGIN
            -- Insert into users table
            INSERT INTO users (username, name, whatsapp_number, created_by, updated_by, code, created_at, updated_at)
            VALUES (p_phone_number, p_name, p_phone_number, p_internalCompanyId, p_internalCompanyId, '', current_timestamp, current_timestamp);

            -- Insert into procedure_log
            INSERT INTO procedure_log (log_message) VALUES (CONCAT('Inserted user: ', p_name));
        END;

    END LOOP read_loop;

    -- Close the cursor
    CLOSE u_cursor;

    -- Commit the transaction
    COMMIT;
END;;

DELIMITER ;
© www.soinside.com 2019 - 2024. All rights reserved.