【问题标题】:All Tables cant' perform INSERT OR UPDATE所有表都不能执行 INSERT OR UPDATE
【发布时间】:2017-07-30 23:30:04
【问题描述】:

我使用了一个存储过程,该存储过程使用游标循环并处理 Mariadb 10.1 数据库上的出勤数据表,在第一次调用该过程后,数据库上的所有表都失去了执行 INSERT INTO 或 UPDATE 语句的能力,除非目标表首先被截断,谁能告诉我出了什么问题以及如何解决它 导致问题的程序:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `settle_attendance`()
    MODIFIES SQL DATA
BEGIN
DECLARE trans_done BOOLEAN DEFAULT FALSE;
DECLARE punchid BIGINT(20);
DECLARE timein DATETIME;
DECLARE utctimein DATETIME;
DECLARE timeout DATETIME;
DECLARE utctimeout DATETIME;
DECLARE inday DATE;
DECLARE outday DATE;
DECLARE todaysdate DATE;

DECLARE attendcur CURSOR FOR
     SELECT id, punch_in_utc_time, punch_in_user_time,
                punch_out_utc_time, punch_out_user_time
         FROM ohrm_attendance_record
         ORDER BY id ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET trans_done = TRUE;

OPEN attendcur;
edit_loop: LOOP
SET todaysdate = CURRENT_DATE();
FETCH attendcur INTO punchid, utctimein, timein, utctimeout, timeout;

IF trans_done THEN
        CLOSE attendcur;
        LEAVE edit_loop;
END IF;

SET inday = DATE(timein);
SET outday = DATE(timeout);
SET todaysdate = CURRENT_DATE();


IF (inday < todaysdate) OR (outday < todaysdate) THEN
    CASE 
        WHEN (timein IS NULL OR timein = '')
          OR (utctimein IS NULL OR utctimein = '') THEN
            UPDATE ohrm_attendance_record
               SET punch_in_utc_time = utctimeout,
                   punch_in_user_time = timeout,
                   state = 'PUNCHED OUT'
               WHERE punchid = id;
        ELSE BEGIN END;
    END CASE;

    CASE 
        WHEN (timeout IS NULL OR timeout = '')
          OR (utctimeout IS NULL OR utctimeout = '') THEN
            UPDATE ohrm_attendance_record
               SET punch_out_utc_time = utctimein,
                   punch_out_user_time = timein,
                   state = 'PUNCHED OUT'
               WHERE punchid = id;
        ELSE BEGIN END;
    END CASE;
END IF;

END LOOP edit_loop;
END $$
DELIMITER ;

【问题讨论】:

  • “表失去执行插入的能力”是什么意思?如果您遇到任何错误,请将它们逐字添加到您的问题中。
  • 当我手动执行查询时它可以工作,但它在存储过程中不起作用

标签: mysql stored-procedures innodb mariadb


【解决方案1】:

我选择回避你提出的问题。相反,让我们通过摆脱讨厌的CURSOR 来尝试将查询速度提高 10 倍。整个存储过程可以在2个UPDATEs中完成,no循环:

UPDATE  ohrm_attendance_record
    SET punch_in_utc_time = utctimeout,
        punch_in_user_time = timeout,
        state = 'PUNCHED OUT'
    WHERE  ( timein < CURDATE()  OR  timeout < CURDATE() )
      AND  ( ( timein IS NULL     OR  timein = '' )
          OR ( utctimein IS NULL  OR  utctimein = '' )
           );

UPDATE  ohrm_attendance_record
    SET punch_out_utc_time = utctimein,
        punch_out_user_time = timein,
        state = 'PUNCHED OUT'
    WHERE  ( timein < CURDATE()  OR  timeout < CURDATE() )
      AND  ( ( timeout IS NULL    OR  timeout = '' )
          OR ( utctimeout IS NULL OR  utctimeout = '' )
           );

不过,我怀疑您对 timeintimeout 的测试。

如果您选择NULL'' 来确定缺失时间,查询会更容易阅读。

如果您在 TIMESTAMP 中仅存储 UTC 值,您可以让用户的时区负责转换为本地时间 - 这将消除相当多的列并简化 UPDATEs

我会尝试解决这个问题...SHOW CREATE PROCEDURE settle_attendance;,您可能发现CHARACTER SETCOLLATION 与您认为的不一致。

【讨论】:

  • 感谢您完全理顺了程序。我只是在 3 点惊慌失措,正在处理涉及游标的多个过程(我讨厌它们,但我需要它们),结果问题是在另一个调用它的过程中的表名称放错了位置。
  • 本论坛中包含CURSOR 的大多数问题都可以在没有这样的情况下重写。你的是另一个例子。有时候最好明天去睡觉,换个角度看。
  • 我正在使用一个包含光标的过程,它的不一致行为让我疯狂了好几天
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多