2016-09-16 54 views
0

我有一個名爲currentItem的字段,該字段有一個觸發器,它調用存儲過程(使用事務)sp_TransferData來執行一些信息傳輸到工作表。如果存儲過程失敗 - 我想恢復currentItem的舊值 - 因爲它沒有有效改變。MySQL如何將字段重置爲觸發失敗時具有觸發器的舊值?

我正在使用MySQL,我希望這個邏輯在我的觸發器 - 顯然我們不想要一個無限循環,所以我該如何做到這一點?

觸發僞代碼:

Call sp_TransferData(@ResultCode); 
Select @ResultCode into Result; 
If Result < 0 THEN 
thisField Value = OLD.Value; 
End If; 

//編輯 2016年9月16日13:00 // 只有1排在該表中從來沒有任何東西更多!爲了簡潔而編輯列列表。

table global_items 

Id INT PK, 
lsize INT, 
wsize INT, 
currentItem INT 

觸發是CURRENTITEM更新之後或之前,我爲它工作,不重燒觸發沒有哪個只要關心:

If the value has changed CALL sp_TransferData(@ResultCode); 
If (SELECT @ResultCode) < 0 THEN 
Reset currentItem to old value but do not cycle the trigger since we are only resetting it. 
EndIf; 

我想補充這是我在我的觸發代碼不正確。 提供了表格定義。

BEGIN 

    IF NEW.currentItem <> OLD.currentItem THEN 

    call sp_CurrentItemChanged(NEW.currentItem, @ResultCode, @ResultMsg); 

     IF ((Select @ResultCode) < 0) THEN 

     NEW.currentItem = OLD.currentItem; 

     END IF; 

    END IF; 

END 



    CREATE TABLE working_table (
    Id int(11) NOT NULL AUTO_INCREMENT, 
    Mbf float DEFAULT NULL, 
    Width float DEFAULT NULL, 
    Pulse int(11) DEFAULT NULL, 
    PRIMARY KEY (Id) 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 1 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 

CREATE TABLE recipe (
    Id int(11) NOT NULL AUTO_INCREMENT, 
    Name varchar(80) NOT NULL DEFAULT 'UnAssigned', 
    IsDefault tinyint(1) DEFAULT 0, 
    PRIMARY KEY (Id), 
    UNIQUE INDEX Id_UNIQUE (Id), 
    UNIQUE INDEX Name_UNIQUE (Name) 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 1 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 


CREATE TABLE Packs (
    Id int(11) NOT NULL AUTO_INCREMENT, 
    Name varchar(45) NOT NULL DEFAULT 'UNDEFINED', 
    Width float NOT NULL DEFAULT 0, 
    Pulse int(11) NOT NULL DEFAULT 0, 
    Mbf float NOT NULL DEFAULT 0, 
    RecipeID int(11) NOT NULL DEFAULT 0, 
    SetupID int(11) DEFAULT 1, 
    PRIMARY KEY (Id), 
    INDEX SetupID_ndx (SetupID), 
    INDEX FK_PackRecipeID_Recipe_ID_idx (RecipeID), 
    INDEX FK_RecipeID_PackS_idx (RecipeID), 
    CONSTRAINT FK_PackRecipeID_Recipe_ID FOREIGN KEY (RecipeID) 
    REFERENCES recipe (Id) ON DELETE CASCADE ON UPDATE CASCADE 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 1 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 

CREATE TABLE global_items (
    Id int(11) NOT NULL AUTO_INCREMENT, 
    PackSys_Count int(11) DEFAULT NULL, 
    Active_Recipe int(11) DEFAULT 1, 
    PRIMARY KEY (Id) 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 2 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 

當global_items.Active_recipe改變觸發器觸發..這移動的數據是在包和其相關的表(這裏簡潔)與working_table。 global_items表永遠不會被冗長的存儲過程或任何其他觸發器或任何其他sql代碼中的任何內容所觸及。它不會被SQL存儲內部的任何內容修改 - 它只能被外部應用程序觸及。我不知道如何將存儲過程失敗時的值恢復爲原始值。

enter image description here

+0

currentItem=部分,我相信這是可以回答卻是模糊的。什麼是tableName?什麼是更新觸發器類型(以及什麼tableName?)。另外你的數據視覺會清楚表明。也就是說,如果你真的想要吸引一個答案 – Drew

+0

@Drew觸發器是在一個列而不是表。我發佈了觸發器設置,包含列的表名(不知道爲什麼表名很重要),觸發器在currentItem列上它是一個INT。我只是想要將失敗的價值重新調整到原來的水平。 – Ken

+0

觸發器在桌子上。 http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html。如果觸發器(在'tableName'上)也影響'tableName',那麼顯式是明確的,因爲相同表的自我修改可以是錯誤條件。也就是說,如果我們甚至從這裏顯示的網址談論通常理解的概念 – Drew

回答

1

我想我可能會理解你做了什麼。但是,既然你沒有完全展示你的觸發器,我猜測,而不是存儲過程,我只是將它展開並進行了調查。

我認爲問題在於你的存儲過程沒有一個OUT限定符來使它可寫。下面的工作正常,我認爲它捕捉如何解決您的問題。

模式:

-- drop table global_items; 
create table global_items 
( Id INT primary key, 
    lsize INT not null, 
    wsize INT not null, 
    currentItem INT not null, 
    theCount int not null 
); 
insert global_items(Id,lsize,wsize,currentItem,theCount) VALUES 
(1,1,1,100,0); 

select * from global_items; 

觸發:

DROP TRIGGER IF EXISTS giBeforeUpdate; 
DELIMITER $$ 
CREATE TRIGGER giBeforeUpdate 
BEFORE UPDATE 
    ON global_items FOR EACH ROW 
BEGIN 
    DECLARE tRet INT; 
    SET tRet=0; 
    SET NEW.theCount=OLD.theCount+1; 
    CALL uspDoSomething7(tRet); 
    IF tRet=1 THEN 
     -- stored proc said FAILURE 
     SET NEW.currentItem=OLD.currentItem; 
    END IF; 
END;$$ 
DELIMITER ; 

存儲過程:

DROP PROCEDURE IF EXISTS uspDoSomething7; 
DELIMITER $$ 
CREATE PROCEDURE uspDoSomething7(OUT retVal INT) 
BEGIN 
    DECLARE rndNum INT; 
    SET rndNum=FLOOR(RAND()*2)+1; -- random number 1 or 2 

    -- sets retVal to 1 on FAILURE 
    IF rndNum=2 THEN 
     SET retVal=1; -- FAIL 
    ELSE 
     SET retVal=0; -- SUCCESS 
    END IF; 
END$$ 
DELIMITER ; 

測試:

反覆調用此確​​認其大致失敗一半的時間

就是CURRENTITEM保留其舊值

但CHG每次下面的更新語句爲它

update global_items set currentItem=410,lsize=2 where Id=1; 
select * from global_items; 
+0

我是新來的使用觸發器一些東西是我朦朧 - 不是你的例子 - 只是我實現觸發器;在這裏觸發器的語句IF tRet = 1 THEN - 存儲過程稱爲FAILURE SET NEW.currentItem = OLD.currentItem;萬一;這是在更新之前完成的,所以該值尚未改變?正因爲如此 - 我可以將該值重置爲原始值,並且觸發器不會無休止地循環。這是我想弄明白的答案。 thx .. – Ken

+0

隨時來[廣告活動](http://chat.stackoverflow.com/rooms/95290)聊天,並要求離開。只需使用'@'來ping RIck或我自己 – Drew