2017-03-09 1 views
-1

Ich habe eine gespeicherte Prozedur verwendet, die einen Cursor zum Durchlaufen und Verarbeiten einer Anwesenheitsdatentabelle in der Mariadb 10.1-Datenbank nach dem ersten Aufruf aller Tabellen in der Datenbank verwendet ausführen INSERT INTO oder UPDATE-Anweisungen, wenn die Zieltabelle zuerst abgeschnitten wird, kann jemand mir sagen, was schief gelaufen ist und wie es das Verfahren zu beheben, die das Problem verursacht:Alle Tabellen können 'INSERT' oder 'UPDATE' nicht ausführen

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 ; 
+0

Was meinen Sie mit "Tabellen verloren die Fähigkeit, INSERT durchzuführen"? Wenn Sie Fehler bekommen, fügen Sie sie wörtlich zu Ihrer Frage hinzu. – mustaccio

+0

Wenn ich eine Abfrage manuell ausführen, funktioniert es, aber es funktioniert nicht in der gespeicherten Prozedur –

Antwort

0

ich wählen, die Frage zu vermeiden, würden wir Sie bitten . Versuchen wir stattdessen, die Abfrage 10-mal so schnell zu erledigen, indem wir die lästigen CURSOR loswerden.

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 = '') 
      ); 

Ich bin jedoch misstrauisch Ihre Tests gegen timein und timeout: Die gesamte gespeicherte Prozedur kann in 2 UPDATEs, keine Schleife erfolgen.

Die Abfragen wären einfacher zu lesen, wenn Sie sich entweder auf NULL oder '' für fehlende Zeiten festgelegt haben.

Wenn Sie nur UTC-Werte in einer TIMESTAMP speichern, können Sie die Zeitzone des Benutzers für die Umrechnung auf lokale Zeit sorgen lassen - dies würde einige Spalten eliminieren und die UPDATEs vereinfachen.

Ich werde einen Stich an die Frage stellen ... SHOW CREATE PROCEDURE settle_attendance; Haben Sie können feststellen, dass die CHARACTER SET oder COLLATION ist unvereinbar mit dem, was Sie denken, es sein sollte.

+0

Dank Sie wirklich die Prozedur vollständig begradigt. Ich war panisch um 3 Uhr morgens und arbeitete an mehreren Prozeduren mit Cursors (ich hasse sie, aber ich brauche sie) und das Problem stellte sich als ein fehlplatzierter Name einer Tabelle bei einer anderen Prozedur heraus, die diese nennt. –

+0

Die meisten Fragen in diesem Forum, die einen 'CURSOR' enthalten, können ohne diese überschrieben werden. Dein ist ein anderes Beispiel. Manchmal ist es am besten, ins Bett zu gehen und morgen einen neuen Blick zu werfen. –

+0

Ich benutze eine Prozedur mit einem Cursor und sein inkonsistentes Verhalten macht mich seit Tagen verrückt –

Verwandte Themen