2016-04-26 22 views
0

So habe ich diese Tabellen:Datenbank-Trigger vor dem Einsetzen und Berechnungen

CREATE TABLE `chittytransactions` (
    `ChittyTransactionID` int(11) NOT NULL, 
    `AuctionID` int(11) NOT NULL, 
    `ChittyAccNo` int(11) DEFAULT NULL, 
    `Date` datetime DEFAULT NULL, 
    `Amount` double DEFAULT NULL, 
    `Description` varchar(50) DEFAULT NULL, 
    `TransRefence` varchar(50) DEFAULT NULL COMMENT 'Reference from actual Bank transaction', 
    `TransStatus` tinyint(1) DEFAULT NULL COMMENT 'If Transaction Pending or Cleared', 
    `ClearanceDate` datetime DEFAULT NULL, 
    `PaymentMethod` int(1) DEFAULT NULL COMMENT '0- Cash, 1- bank transfer, 2- personal credit etc' 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `chittyusers` (
    `ChittyAccNo` int(11) NOT NULL, 
    `UserId` int(11) NOT NULL, 
    `ChittyID` int(11) NOT NULL, 
    `LatePaymentFee` int(11) DEFAULT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `users` (
    `UserId` int(11) NOT NULL, 
    `UserName` varchar(45) NOT NULL, 
    `UserNameVerified` tinyint(1) DEFAULT '0', 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Was Im versuchen zu tun ist, zu überprüfen, ob ein Transaktionsdatum gleich dem gelöschten Datums in der chittytransaction Tabelle ist und wenn nicht ein spätes hinzufügen Zahlungsgebühr an die chittyusers Tabelle (vorzugsweise berechnet auf der Grundlage eines jeden Tages wird eine zusätzliche Gebühr zu verspäteter Zahlung basierend auf Datum hinzugefügt). Dies sollte vorher geschehen und einfügen und ich verwende einen Trigger. Bisher habe ich dies:

ROP TRIGGER IF EXISTS chitty_beforet_trig; 

DELIMITER ;; 
CREATE TRIGGER chitty_beforet_trig BEFORE Insert ON chittytransaction 
FOR EACH ROW 
    BEGIN 
    DECLARE `mainDate` datetime; 
    DECLARE `claredDate` datetime; 
    DECLARE `chitAccNo` INT(11); 
    DECLARE `userId` INT(11); 
    DECLARE `latePay` DOUBLE; 
    DECLARE late TINYINT; 
    DECLARE cursor1 CURSOR FOR SELECT ChittyAccNo FROM accounting.`chittyusers`; 
    DECLARE cursor2 CURSOR FOR SELECT `Date` FROM accounting.`chittyTransaction`; 
    DECLARE cursor3 CURSOR FOR SELECT ClearanceDate FROM accounting.`chittyTransaction`; 
    DECLARE cursor4 CURSOR FOR SELECT UserId FROM accounting.`users`; 

    OPEN cursor1; 
    OPEN cursor2; 
    OPEN cursor3; 
    OPEN cursor4; 

    FETCH cursor1 INTO chitAccNo; 
    FETCH cursor2 INTO mainDate 
    FETCH cursor3 INTO claredDate; 
    FETCH cursor3 INTO userId; 
    CASE 
     WHEN claredDated <> mainDate THEN 
      SET late ='1'; 
     ELSE 
      SET late = '0'; 
     END; 
    END CASE; 

    IF late THEN 
     UPDATE `chittyusers` SET LatePaymentFee = 50 WHERE UserId = userId; 
    END IF; 
CLOSE cursor1; 
CLOSE cursor2; 
CLOSE cursor3; 
CLOSE cursor4; 

END;; 
DELIMITER; 

Ich halte viele verschiedene Fehler bekommen etc Anzeige Ich weiß nicht, ob ich es richtig oder nicht mache. Habe diese vorher noch nie benutzt also ist es etwas schwierig. Kann mir bitte jemand sagen was ich falsch mache und jede Lösung würde mir gefallen.

Antwort

1

Meine Güte, wo ich anfangen soll?

Zunächst sollte ein Zeilentrigger niemals die Tabelle abfragen, an die er angehängt ist. (MySQL wird dies ermöglichen, viele DBMSes nicht.)

Ein INSERT Zeilentrigger hat immer Zugriff auf die Zeile über den NEW pseudorecord eingeführt wird, die dieselben Spalten wie die darunter liegende Tabelle enthält. Der Inhalt von NEW aus der VALUES-Klausel der INSERT Anweisung initialisiert, und alle Änderungen, die Sie an NEW wird in der Tabellenzeile reflektiert werden, sobald der Einsatz abgeschlossen ist.

Ein weiteres Problem ist, dass Sie den Cursor auf chittyusers hat einen unbedingten SELECT, die jede Zeile aus der Tabelle greifen wird, nicht nur die, die Sie wollen. Was Sie eigentlich machen, ist ein nahezu zufälliger Wert für userId, der wahrscheinlich nichts mit dem gewünschten zu tun hat. Sie brauchen dazu eigentlich gar keinen Cursor; eine einfache INSERT ... INTO mit einer WHERE Klausel wird besser funktionieren:

SELECT `UserId` 
    INTO `userId` 
    FROM chittyusers 
    WHERE ChittyAccNo = NEW.ChittyAccNo; 

Drittens Ihre CASE-Struktur ist überflüssig; Sie können genau das gleiche tun mit einem einfachen IF:

IF NEW.ClearanceDate <> NEW.`Date` THEN 
    UPDATE `chittyusers` 
    SET LatePaymentFee = 50 
    WHERE UserId = userId; 
END IF; 

ich nicht bin den gesamten Auslöser für Sie zu schreiben, aber diese Zeiger zumindest sollten die Fehlermeldungen auf eine überschaubare Zahl bekommen.

+0

Danke. Ich habe es dank dir herausgefunden. Aber warum gibt es ein Problem mit einem Fall? – luffy

+0

Es gibt kein Problem; es ist einfach nicht notwendig. Durch das Verbergen werden Variablen, Codezeilen und Komplexität reduziert. –

+0

verwende ich es falsch? Wenn ja, wie würde ich es ändern? – luffy