About the problem of returning the GET DIAGNOSTICS abnormal catch message in the MYSQL stored procedure/function

When processing SQLEXCEPTION in MySQL storage, if you use GET CURRENT DIAGNOSTICS CONDITION 1 @SQL_MSG_CODE = RETURNED_SQLSTATE, @SQL_MSG_TEXT = MESSAGE_TEXT; to read the message that is the first error message displayed every time, then how? How about displaying the latest error information? Please refer to the following example:

 

DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 TEXT NOT NULL);
DROP PROCEDURE IF EXISTS p;
delimiter //
CREATE PROCEDURE p ()
BEGIN
  -- Declare variables to hold diagnostics area information
  DECLARE errcount INT;
  DECLARE errno INT;
  DECLARE msg TEXT;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    -- Here the current DA is nonempty because no prior statements
    -- executing within the handler have cleared it
    GET CURRENT DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'current DA before mapped insert' AS op, errno, msg;
    GET STACKED DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA before mapped insert' AS op, errno, msg;

    -- Map attempted NULL insert to empty string insert
    INSERT INTO t1 (c1) VALUES('');

    -- Here the current DA should be empty (if the INSERT succeeded),
    -- so check whether there are conditions before attempting to
    -- obtain condition information
    GET CURRENT DIAGNOSTICS errcount = NUMBER;
    IF errcount = 0
    THEN
      SELECT 'mapped insert succeeded, current DA is empty' AS op;
    ELSE
      GET CURRENT DIAGNOSTICS CONDITION 1
        errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
      SELECT 'current DA after mapped insert' AS op, errno, msg;
    END IF ;
    GET STACKED DIAGNOSTICS CONDITION 1
      errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
    SELECT 'stacked DA after mapped insert' AS op, errno, msg;
  END;
  INSERT INTO t1 (c1) VALUES('string 1');
  INSERT INTO t1 (c1) VALUES(NULL);
END;
//
delimiter ;
CALL p();
SELECT * FROM t1;

It should be noted that
1. GET DIAGNOSTICS statement will also clear the content in the current diagnostic area, so the insert statement in the condition handler is removed from the above code, and the result is the same.
2. If the above stored procedure is modified as follows, That is, put the three declare variable statements in the
declare handler. The actual result will depend on the version of MySQL. If it is a version before MySQL-5.7.2, the following modifications will not affect the content in the diagnostic area. The actual result is the same as the above result. If it is in MySQL-5.7.2 and later versions, the declare variable statement will clear the content in the current diagnostic area.

 

CREATE PROCEDURE p ()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errcount INT;
DECLARE errno INT;
DECLARE msg TEXT;
GET CURRENT DIAGNOSTICS CONDITION 1
errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
SELECT 'current DA before mapped insert' AS op, errno, msg;

GET STACKED DIAGNOSTICS CONDITION 1
errno = MYSQL_ERRNO, msg = MESSAGE_TEXT;
SELECT 'stacked DA before mapped insert' AS op, errno, msg;
...

So when you need to get the content in the diagnostic area, you must get it from the stack diagnostic area, not the current diagnostic area. 

 

Guess you like

Origin blog.csdn.net/bj_chengrong/article/details/103297865