Stack Exchange
last_insert_id() inside mysql procedure returns 0
I use procedure to insert or update data in table and i want last inserted id to be returned.
Here is my procedure:
/* insert or update task */
DROP PROCEDURE IF EXISTS `proc_update_task`;
DELIMITER $$
CREATE PROCEDURE `proc_update_task`(IN TaskID INT, IN Name VARCHAR(100), IN Description TEXT, IN ProjectID INT, IN StatusID INT, IN ExpectedTime TIME, IN PriorityID INT, IN CategoryID INT, IN MilestoneID INT, IN UserID INT, IN DateDeadline DATE, OUT lastID INT)
BEGIN
    DECLARE Status INT;
    DECLARE Project INT;
    DECLARE TimeExp DATE;
    DECLARE Priority INT;
    DECLARE Milestone INT;
    DECLARE Category INT;
    DECLARE User INT;
    DECLARE Deadline DATE;

    SET @Status = StatusID;
    SET @Project = ProjectID;
    SET @TimeExp = ExpectedTime;
    SET @Priority = PriorityID; 
    SET @Milestone = MilestoneID;
    SET @Category = CategoryID;
    SET @User = UserID;
    SET @Deadline = DateDeadline;

    INSERT INTO tasks (ID, Name, Description, Project_ID, Status_ID, TimeExpected, Priority_ID, Category_ID, Milestone_ID, User_ID, DateDeadline)
        VALUES (TaskID, Name, Description, @Project, @Status, @TimeExp, @Priority, @Category, @Milestone, @User, @Deadline)
            ON DUPLICATE KEY UPDATE
        Name=VALUES(Name), Description=VALUES(Description), Project_ID=@Project, Status_ID=@Status, TimeExpected=@TimeExp, Priority_ID=@Priority, Category_ID=@Category, Milestone_ID=@Milestone, User_ID=@User, DateDeadline=@Deadline;

    SET lastID =  LAST_INSERT_ID();
    INSERT INTO debug(debug_output) VALUES (lastID);
END;

The last bit - INSERT INTO debug(debug_output) VALUES (lastID) - is just to verify, that indeed, value returned by LAST_INSERT_ID() is 0. I know, that LAST_INSERT_ID() is meaningless in case of updating, which is fine. But even if new record is inserted, I still get 0.
Any ideas how to fix this?
Thanks, zbynek

Are you sure MySQL auto generates any id in this case ? It does look like you're inserting the ID yourself

i dont think so - ID which I insert is either -1, in which case a new row is inserted with autogenerated ID, or it is some value > 0, which is always duplicate and therefore the row will be updated

You are wrong assuming that inserting an ID value of -1 will generate a new ID. Either a new row is inserted with value -1 when the ID column is signed or you get an error like

ERROR 1264 (22003): Out of range value for column 'id' at row 1

when your ID column is unsigned.
Your LAST_INSERT_ID is always 0 when a row gets updated, because your ON DUPLICATE KEY clause has to be modified to this:
...
ON DUPLICATE KEY UPDATE 
ID = LAST_INSERT_ID(ID),
Name=VALUES(Name),
...

(Note though, that it will also be 0, if the insert matches an existing row, but there's nothing to update, e.g. column Name has value Peter and you want to update it with value Peter (vice versa for every column))
And it's always 0 because you always specify a value for the auto_increment column.

Ok, thanks. I changed the procedure so now it contains if else condition to decide, whether to update the value or insert new row and returned last_insert_id is now correct.
